def test_obj_to_yaml_no_line_wrap(self): ruamel_data = { 'key': ("this is some super super super long line that would normally cause" " a line wrap when converting from dict to yaml. instead we don't want" " to do that and just keep this one crazy long line.") } result = yaml_utils.obj_to_yaml(ruamel_data) self.assertEqual(result, self.get_fixture_content('yaml/no_line_wrap.yaml'))
def test_obj_to_yaml(self): ruamel_data = OrderedMap([ ('test_dict', OrderedMap([ ('a', True) ])) ]) result = yaml_utils.obj_to_yaml(ruamel_data) self.assertEqual(result, self.get_fixture_content('yaml/simple.yaml'))
def convert_file(self, filename, expr_type=None): # parse the Mistral workflow from file mistral_wf_data, mistral_wf_data_ruamel = yaml_utils.read_yaml( filename) # validate the Mistral workflow before we start mistral_wf_spec = mistral_workflow.instantiate(mistral_wf_data) self.validate_workflow_spec(mistral_wf_spec) # convert Mistral -> Orquesta mistral_wf = mistral_wf_data_ruamel[mistral_wf_spec.name] workflow_converter = WorkflowConverter() orquesta_wf_data_ruamel = workflow_converter.convert( mistral_wf, expr_type, force=self.args.force) orquesta_wf_data_str = yaml_utils.obj_to_yaml(orquesta_wf_data_ruamel) orquesta_wf_data = yaml_utils.yaml_to_obj(orquesta_wf_data_str) # validate we've generated a proper Orquesta workflow orquesta_wf_spec = orquesta_workflow.instantiate(orquesta_wf_data) if not self.args.force: self.validate_workflow_spec(orquesta_wf_spec) # write out the new Orquesta workflow to a YAML string return yaml_utils.obj_to_yaml(orquesta_wf_data_ruamel)
def test_obj_to_yaml_dict(self): ruamel_data = {'test_dict': {'a': True}} result = yaml_utils.obj_to_yaml(ruamel_data) self.assertEqual(result, self.get_fixture_content('yaml/simple.yaml'))
def run(self, argv, output_stream, client=None): self.args, args = self.parser().parse_known_args(argv) wf_type = self.args.workflow_type directory = self.args.actions_directory if wf_type: for action, workflow in self.get_workflow_files( wf_type, directory).items(): output_stream.write("{} --> {}\n".format(action, workflow)) return 0 if self.args.validate: args.append('--validate') filenames = self.get_workflow_files('orquesta', directory).values() total = 0 for f in filenames: fargs = list(args) fargs.append(f) total += client.run(fargs, output_stream) return total filenames = self.get_workflow_files('mistral-v2', directory) exceptions = {} for a_f, m_f in six.iteritems(filenames): fargs = list(args) # make a copy fargs.append(m_f) # Get the backup filenames m_f_backup = '{}.{}'.format(m_f, BACKUP_EXTENSION) a_f_backup = '{}.{}'.format(a_f, BACKUP_EXTENSION) o_f = '{}.{}'.format(m_f, TMP_EXTENSION) # Orquesta workflow file # Convert the workflow and save the YAML string in output output = six.moves.StringIO() # In this next block of code we are attempting to create a filesystem # transaction, where we either want to commit all of the changes to # disk or none of the changes. # Usually you want to minimize what you put into a try block, so you # can catch different errors and handle them differently. However, in # this case, there are so many file operations that can fail that it # ends up nesting try/except/else blocks very deep, and exception # handlers simply do cleanup and re-raise the exception. # So instead, we do all of our work in the try block, and handle # cleaning up after the different failure conditions in the except # block, and handle success conditions in the else block. try: client.run(fargs, output) # Write the workflow file with open(o_f, 'w') as o_file: o_file.write(str(output.getvalue())) # If the backup files already exist, they were created by a # previous run. In that case, we want to preserve the original # backup file, because it is more likely a valid Mistral # workflow than whatever the current workflow file is. if not os.path.isfile(m_f_backup): # Move the existing workflow file to a backup os.rename(m_f, m_f_backup) if not os.path.isfile(a_f_backup): # Move the existing metadata file to a backup shutil.copy2(a_f, a_f_backup) # Read the file into a dict, tweak the runner_type, and write # the dict back into a string action_data, action_data_ruamel = yaml_utils.read_yaml(a_f) action_data_ruamel['runner_type'] = 'orquesta' write_data = yaml_utils.obj_to_yaml(action_data_ruamel) # Promote/move the new workflow file into place shutil.move(o_f, m_f) # Rewrite the metadata file with the tweaked runner_rtype with open(a_f, 'w') as a_file: a_file.write(write_data) # SUCCESS! except Exception as e: # Anything could have happened, so we check for bad conditions # If we have a backup workflow file, revert it if os.path.isfile(m_f_backup): # Remove the converted workflow file if os.path.isfile(m_f): os.remove(m_f) # Move the backup file back os.rename(m_f_backup, m_f) # If we have a backup action metadata file if os.path.isfile(a_f_backup): # Remove the converted metadata file if os.path.isfile(a_f): os.remove(a_f) # Move the backup file back os.rename(a_f_backup, a_f) # If we ever support just Python 3, we can add the exception # directly to the dictionary value: # # .append({'file': m_f, 'exception': e}) # exceptions.setdefault(str(e), []).append(m_f) else: # Remove the backup files os.remove(m_f_backup) os.remove(a_f_backup) if exceptions: sys.stderr.write( "ERROR: Unable to convert all Mistral workflows.\n") for e, wfs in exceptions.items(): sys.stderr.write("ISSUE: {}\n".format(e)) sys.stderr.write("Affected files:\n") for wf in wfs: sys.stderr.write(" - {}\n".format(wf)) sys.stderr.write("\n") return len(exceptions)