1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
2 # not use this file except in compliance with the License. You may obtain
3 # a copy of the License at
5 # http://www.apache.org/licenses/LICENSE-2.0
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 # License for the specific language governing permissions and limitations
26 from toscaparser.tosca_template import ToscaTemplate
27 from toscaparser.utils.gettextutils import _
28 from toscaparser.utils.urlutils import UrlUtils
29 from translator.common import utils
30 from translator.conf.config import ConfigProvider
31 from translator.hot.tosca_translator import TOSCATranslator
34 Test the heat-translator translation from command line as:
36 --template-file=<path to the YAML template>
37 --template-type=<type of template e.g. tosca>
38 --parameters="purpose=test"
39 Takes three user arguments,
40 1. type of translation (e.g. tosca) (required)
41 2. Path to the file that needs to be translated (required)
42 3. Input parameters (optional)
44 In order to use heat-translator to only validate template,
45 without actual translation, pass --validate-only=true along with
46 other required arguments.
49 conf_file = ConfigProvider.get_translator_logging_file()
50 logging.config.fileConfig(conf_file)
51 log = logging.getLogger("heat-translator")
54 class TranslatorShell(object):
56 SUPPORTED_TYPES = ['tosca']
59 parser = argparse.ArgumentParser(prog="heat-translator")
61 parser.add_argument('--template-file',
64 help=_('Template file to load.'))
66 parser.add_argument('--output-file',
68 help=_('Where to store the output file. If not '
69 'passed, it will be printed to stdin.'))
71 parser.add_argument('--template-type',
72 metavar='<input-template-type>',
73 choices=self.SUPPORTED_TYPES,
75 help=(_('Template type to parse. Choose between '
76 '%s.') % self.SUPPORTED_TYPES))
78 parser.add_argument('--parameters',
79 metavar='<param1=val1;param2=val2;...>',
80 help=_('Optional input parameters.'))
82 parser.add_argument('--validate-only',
85 help=_('Only validate input template, do not '
86 'perform translation.'))
88 parser.add_argument('--deploy',
91 help=_('Whether to deploy the generated template '
98 parser = self.get_parser()
99 (args, args_list) = parser.parse_known_args(argv)
101 template_file = args.template_file
102 template_type = args.template_type
103 output_file = args.output_file
104 validate_only = args.validate_only
109 parsed_params = self._parse_parameters(args.parameters)
111 a_file = os.path.isfile(template_file)
112 a_url = UrlUtils.validate_url(template_file) if not a_file else False
115 ToscaTemplate(template_file, parsed_params, a_file)
116 msg = (_('The input "%(template_file)s" successfully passed '
117 'validation.') % {'template_file': template_file})
120 heat_tpl = self._translate(template_type, template_file,
121 parsed_params, a_file, deploy)
123 if utils.check_for_env_variables() and deploy:
125 heatclient(heat_tpl, parsed_params)
127 log.error(_("Unable to launch the heat stack"))
129 self._write_output(heat_tpl, output_file)
131 msg = (_('The path %(template_file)s is not a valid '
132 'file or URL.') % {'template_file': template_file})
135 raise ValueError(msg)
137 def _parse_parameters(self, parameter_list):
140 # Parameters are semi-colon separated
141 inputs = parameter_list.replace('"', '').split(';')
142 # Each parameter should be an assignment
144 keyvalue = param.split('=')
145 # Validate the parameter has both a name and value
146 msg = _("'%(param)s' is not a well-formed parameter.") % {
148 if keyvalue.__len__() is 2:
149 # Assure parameter name is not zero-length or whitespace
150 stripped_name = keyvalue[0].strip()
151 if not stripped_name:
153 raise ValueError(msg)
154 # Add the valid parameter to the dictionary
155 parsed_inputs[keyvalue[0]] = keyvalue[1]
158 raise ValueError(msg)
161 def _translate(self, sourcetype, path, parsed_params, a_file, deploy):
163 if sourcetype == "tosca":
164 log.debug(_('Loading the tosca template.'))
165 tosca = ToscaTemplate(path, parsed_params, a_file)
166 translator = TOSCATranslator(tosca, parsed_params, deploy)
167 log.debug(_('Translating the tosca template.'))
168 output = translator.translate()
171 def _write_output(self, output, output_file=None):
174 with open(output_file, 'w+') as f:
180 def heatclient(output, params):
182 access_dict = utils.get_ks_access_dict()
183 endpoint = utils.get_url_for(access_dict, 'orchestration')
184 token = utils.get_token_id(access_dict)
185 except Exception as e:
188 'Content-Type': 'application/json',
189 'X-Auth-Token': token
191 heat_stack_name = "heat_" + str(uuid.uuid4()).split("-")[0]
192 output = yaml.load(output)
193 output['heat_template_version'] = str(output['heat_template_version'])
195 'stack_name': heat_stack_name,
199 response = requests.post(endpoint + '/stacks',
200 data=json.dumps(data),
202 content = ast.literal_eval(response._content)
203 if response.status_code == 201:
204 stack_id = content["stack"]["id"]
205 get_url = endpoint + '/stacks/' + heat_stack_name + '/' + stack_id
206 get_stack_response = requests.get(get_url,
208 stack_details = json.loads(get_stack_response.content)["stack"]
209 col_names = ["id", "stack_name", "stack_status", "creation_time",
211 pt = prettytable.PrettyTable(col_names)
213 for col in col_names:
214 stack_list.append(stack_details[col])
215 pt.add_row(stack_list)
218 err_msg = content["error"]["message"]
219 log(_("Unable to deploy to Heat\n%s\n") % err_msg)
225 TranslatorShell().main(args)
228 if __name__ == '__main__':