diff --git a/tacker/nfvo/drivers/vim/openstack_driver.py b/tacker/nfvo/drivers/vim/openstack_driver.py index 39cc60cc9..a395bb4cc 100644 --- a/tacker/nfvo/drivers/vim/openstack_driver.py +++ b/tacker/nfvo/drivers/vim/openstack_driver.py @@ -482,7 +482,7 @@ class OpenStack_Driver(abstract_vim_driver.VimAbstractDriver, auth_token).get_client() wg = workflow_generator.WorkflowGenerator(resource, action) wg.task(**kwargs) - definition_yaml = yaml.dump(wg.definition) + definition_yaml = yaml.safe_dump(wg.definition) workflow = mistral_client.workflows.create(definition_yaml) return {'id': workflow[0].id, 'input': wg.get_input_dict()} diff --git a/tacker/nfvo/drivers/workflow/mistral.py b/tacker/nfvo/drivers/workflow/mistral.py index 0bf45c301..59d9104a9 100644 --- a/tacker/nfvo/drivers/workflow/mistral.py +++ b/tacker/nfvo/drivers/workflow/mistral.py @@ -31,7 +31,7 @@ class MistralClient(object): self.wg.task(**kwargs) def create_workflow(self): - definition_yaml = yaml.dump(self.wg.definition) + definition_yaml = yaml.safe_dump(self.wg.definition) wf = self.client.workflows.create(definition_yaml) wf_id = wf[0].id return wf_id diff --git a/tacker/nfvo/nfvo_plugin.py b/tacker/nfvo/nfvo_plugin.py index 8f46414d8..e2f70b5b0 100644 --- a/tacker/nfvo/nfvo_plugin.py +++ b/tacker/nfvo/nfvo_plugin.py @@ -448,7 +448,7 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin, def _parse_template_input(self, context, nsd): nsd_dict = nsd['nsd'] nsd_yaml = nsd_dict['attributes'].get('nsd') - inner_nsd_dict = yaml.load(nsd_yaml) + inner_nsd_dict = yaml.safe_load(nsd_yaml) nsd['vnfds'] = dict() LOG.debug(_('nsd_dict: %s'), inner_nsd_dict) @@ -459,7 +459,7 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin, for vnfd_name in vnfd_imports: vnfd = vnfm_plugin.get_vnfd(context, vnfd_name) # Copy VNF types and VNF names - sm_dict = yaml.load(vnfd['attributes']['vnfd'])[ + sm_dict = yaml.safe_load(vnfd['attributes']['vnfd'])[ 'topology_template'][ 'substitution_mappings'] nsd['vnfds'][sm_dict['node_type']] = vnfd['name'] @@ -516,7 +516,7 @@ class NfvoPlugin(nfvo_db.NfvoPluginDb, vnffg_db.VnffgPluginDbMixin, step-3: Create mistral workflow and execute the workflow """ nsd = self.get_nsd(context, ns['ns']['nsd_id']) - nsd_dict = yaml.load(nsd['attributes']['nsd']) + nsd_dict = yaml.safe_load(nsd['attributes']['nsd']) vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM'] onboarded_vnfds = vnfm_plugin.get_vnfds(context, []) region_name = ns.setdefault('placement_attr', {}).get( diff --git a/tacker/tests/functional/base.py b/tacker/tests/functional/base.py index 4af41120f..d6a7cc92a 100644 --- a/tacker/tests/functional/base.py +++ b/tacker/tests/functional/base.py @@ -52,7 +52,7 @@ class BaseTackerTest(base.BaseTestCase): @classmethod def get_credentials(cls): - vim_params = yaml.load(read_file('local-vim.yaml')) + vim_params = yaml.safe_load(read_file('local-vim.yaml')) vim_params['auth_url'] += '/v3' return vim_params @@ -95,7 +95,7 @@ class BaseTackerTest(base.BaseTestCase): @classmethod def heatclient(cls): - data = yaml.load(read_file('local-vim.yaml')) + data = yaml.safe_load(read_file('local-vim.yaml')) data['auth_url'] = data['auth_url'] + '/v3' domain_name = data.pop('domain_name') data['user_domain_name'] = domain_name diff --git a/tacker/tests/functional/nfvo/test_vim.py b/tacker/tests/functional/nfvo/test_vim.py index 037a5ee31..fa9c7bf2b 100644 --- a/tacker/tests/functional/nfvo/test_vim.py +++ b/tacker/tests/functional/nfvo/test_vim.py @@ -25,7 +25,7 @@ SECRET_PASSWORD = '***' class VimTestCreate(base.BaseTackerTest): def _test_create_delete_vim(self, vim_file, name, description, vim_type, version=None): - data = yaml.load(read_file(vim_file)) + data = yaml.safe_load(read_file(vim_file)) password = data['password'] username = data['username'] diff --git a/tacker/tests/functional/vnfm/test_tosca_vnf.py b/tacker/tests/functional/vnfm/test_tosca_vnf.py index c421f950d..ee40990c7 100644 --- a/tacker/tests/functional/vnfm/test_tosca_vnf.py +++ b/tacker/tests/functional/vnfm/test_tosca_vnf.py @@ -51,7 +51,7 @@ class VnfTestToscaCreate(base.BaseTackerTest): if template_source == 'inline': # create vnf directly from template - template = yaml.load(values_str) + template = yaml.safe_load(values_str) vnf_arg = {'vnf': {'vnfd_template': template, 'name': vnf_name}} vnf_instance = self.client.create_vnf(body=vnf_arg) vnfd_id = vnf_instance['vnf']['vnfd_id'] @@ -64,14 +64,14 @@ class VnfTestToscaCreate(base.BaseTackerTest): vnf_show_out = self.client.show_vnf(vnf_id)['vnf'] self.assertIsNotNone(vnf_show_out['mgmt_url']) - input_dict = yaml.load(values_str) + input_dict = yaml.safe_load(values_str) prop_dict = input_dict['topology_template']['node_templates'][ 'CP1']['properties'] # Verify if ip_address is static, it is same as in show_vnf if prop_dict.get('ip_address'): mgmt_url_input = prop_dict.get('ip_address') - mgmt_info = yaml.load( + mgmt_info = yaml.safe_load( vnf_show_out['mgmt_url']) self.assertEqual(mgmt_url_input, mgmt_info['VDU1']) diff --git a/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py b/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py index 3affd64dd..2cc152f66 100644 --- a/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py +++ b/tacker/tests/functional/vnfm/test_tosca_vnf_multiple_vdu.py @@ -60,9 +60,9 @@ class VnfTestToscaMultipleVDU(base.BaseTackerTest): # Validate mgmt_url with input yaml file mgmt_url = self.client.show_vnf(vnf_id)['vnf']['mgmt_url'] self.assertIsNotNone(mgmt_url) - mgmt_dict = yaml.load(str(mgmt_url)) + mgmt_dict = yaml.safe_load(str(mgmt_url)) - input_dict = yaml.load(input_yaml) + input_dict = yaml.safe_load(input_yaml) toscautils.updateimports(input_dict) tosca = tosca_template.ToscaTemplate(parsed_params={}, a_file=False, diff --git a/tacker/tests/functional/vnfm/test_tosca_vnfc.py b/tacker/tests/functional/vnfm/test_tosca_vnfc.py index f4b54e521..e2ea7fbfa 100644 --- a/tacker/tests/functional/vnfm/test_tosca_vnfc.py +++ b/tacker/tests/functional/vnfm/test_tosca_vnfc.py @@ -71,9 +71,9 @@ class VnfTestToscaVNFC(base.BaseTackerTest): # Validate mgmt_url with input yaml file mgmt_url = self.client.show_vnf(vnf_id)['vnf']['mgmt_url'] self.assertIsNotNone(mgmt_url) - mgmt_dict = yaml.load(str(mgmt_url)) + mgmt_dict = yaml.safe_load(str(mgmt_url)) - input_dict = yaml.load(input_yaml) + input_dict = yaml.safe_load(input_yaml) toscautils.updateimports(input_dict) tosca = tosca_template.ToscaTemplate(parsed_params={}, a_file=False, diff --git a/tacker/tests/unit/db/utils.py b/tacker/tests/unit/db/utils.py index f1c9f02e5..2268c3895 100644 --- a/tacker/tests/unit/db/utils.py +++ b/tacker/tests/unit/db/utils.py @@ -29,18 +29,19 @@ tosca_vnfd_openwrt = _get_template('test_tosca_openwrt.yaml') config_data = _get_template('config_data.yaml') update_config_data = _get_template('update_config_data.yaml') vnffg_params = _get_template('vnffg_params.yaml') -vnffgd_template = yaml.load(_get_template('vnffgd_template.yaml')) -vnffgd_tosca_template = yaml.load(_get_template('tosca_vnffgd_template.yaml')) -vnffgd_tosca_param_template = yaml.load(_get_template( +vnffgd_template = yaml.safe_load(_get_template('vnffgd_template.yaml')) +vnffgd_tosca_template = yaml.safe_load(_get_template( + 'tosca_vnffgd_template.yaml')) +vnffgd_tosca_param_template = yaml.safe_load(_get_template( 'tosca_vnffgd_param_template.yaml')) -vnffgd_invalid_tosca_template = yaml.load(_get_template( +vnffgd_invalid_tosca_template = yaml.safe_load(_get_template( 'tosca_invalid_vnffgd_template.yaml')) vnfd_scale_tosca_template = _get_template('tosca_scale.yaml') vnfd_alarm_respawn_tosca_template = _get_template( 'test_tosca_vnfd_alarm_respawn.yaml') vnfd_alarm_scale_tosca_template = _get_template( 'test_tosca_vnfd_alarm_scale.yaml') -nsd_tosca_template = yaml.load(_get_template('tosca_nsd_template.yaml')) +nsd_tosca_template = yaml.safe_load(_get_template('tosca_nsd_template.yaml')) def get_dummy_vnfd_obj(): diff --git a/tacker/tests/unit/vm/infra_drivers/openstack/test_openstack.py b/tacker/tests/unit/vm/infra_drivers/openstack/test_openstack.py index f6bb25d8f..b2cc41c67 100644 --- a/tacker/tests/unit/vm/infra_drivers/openstack/test_openstack.py +++ b/tacker/tests/unit/vm/infra_drivers/openstack/test_openstack.py @@ -179,9 +179,9 @@ class TestOpenStack(base.TestCase): vnf_id=vnf_id, vnf_dict=vnf_obj, vnf=vnf_config_obj, auth_attr=utils.get_vim_auth_obj()) - expected_vnf_update['attributes']['config'] = yaml.load( + expected_vnf_update['attributes']['config'] = yaml.safe_load( expected_vnf_update['attributes']['config']) - vnf_obj['attributes']['config'] = yaml.load(vnf_obj['attributes'][ + vnf_obj['attributes']['config'] = yaml.safe_load(vnf_obj['attributes'][ 'config']) self.assertEqual(expected_vnf_update, vnf_obj) diff --git a/tacker/tests/unit/vm/test_toscautils.py b/tacker/tests/unit/vm/test_toscautils.py index 242dd8bc9..62051ae0f 100644 --- a/tacker/tests/unit/vm/test_toscautils.py +++ b/tacker/tests/unit/vm/test_toscautils.py @@ -31,7 +31,7 @@ def _get_template(name): class TestToscaUtils(testtools.TestCase): tosca_openwrt = _get_template('test_tosca_openwrt.yaml') - vnfd_dict = yaml.load(tosca_openwrt) + vnfd_dict = yaml.safe_load(tosca_openwrt) toscautils.updateimports(vnfd_dict) tosca = tosca_template.ToscaTemplate(parsed_params={}, a_file=False, yaml_dict_tpl=vnfd_dict) @@ -111,8 +111,8 @@ class TestToscaUtils(testtools.TestCase): heat_tpl = toscautils.post_process_heat_template( heat_template_yaml, mgmt_ports, {}, {}) - heatdict = yaml.load(heat_tpl) - expecteddict = yaml.load(expected_heat_tpl) + heatdict = yaml.safe_load(heat_tpl) + expecteddict = yaml.safe_load(expected_heat_tpl) self.assertEqual(expecteddict, heatdict) def test_findvdus(self): @@ -125,7 +125,7 @@ class TestToscaUtils(testtools.TestCase): toscautils.TACKERVDU)) def test_get_flavor_dict(self): - vnfd_dict = yaml.load(self.tosca_flavor) + vnfd_dict = yaml.safe_load(self.tosca_flavor) toscautils.updateimports(vnfd_dict) tosca = tosca_template.ToscaTemplate(a_file=False, yaml_dict_tpl=vnfd_dict) @@ -140,9 +140,9 @@ class TestToscaUtils(testtools.TestCase): self.assertEqual(expected_flavor_dict, actual_flavor_dict) def test_add_resources_tpl_for_flavor(self): - dummy_heat_dict = yaml.load(_get_template( + dummy_heat_dict = yaml.safe_load(_get_template( 'hot_flavor_and_capabilities.yaml')) - expected_dict = yaml.load(_get_template('hot_flavor.yaml')) + expected_dict = yaml.safe_load(_get_template('hot_flavor.yaml')) dummy_heat_res = { "flavor": { "VDU1": { @@ -158,7 +158,7 @@ class TestToscaUtils(testtools.TestCase): def test_get_flavor_dict_extra_specs_all_numa_count(self): tosca_fes_all_numa_count = _get_template( 'tosca_flavor_all_numa_count.yaml') - vnfd_dict = yaml.load(tosca_fes_all_numa_count) + vnfd_dict = yaml.safe_load(tosca_fes_all_numa_count) toscautils.updateimports(vnfd_dict) tosca = tosca_template.ToscaTemplate(a_file=False, yaml_dict_tpl=vnfd_dict) @@ -181,7 +181,7 @@ class TestToscaUtils(testtools.TestCase): def test_tacker_conf_heat_extra_specs_all_numa_count(self): tosca_fes_all_numa_count = _get_template( 'tosca_flavor_all_numa_count.yaml') - vnfd_dict = yaml.load(tosca_fes_all_numa_count) + vnfd_dict = yaml.safe_load(tosca_fes_all_numa_count) toscautils.updateimports(vnfd_dict) tosca = tosca_template.ToscaTemplate(a_file=False, yaml_dict_tpl=vnfd_dict) @@ -204,9 +204,9 @@ class TestToscaUtils(testtools.TestCase): self.assertEqual(expected_flavor_dict, actual_flavor_dict) def test_add_resources_tpl_for_image(self): - dummy_heat_dict = yaml.load(_get_template( + dummy_heat_dict = yaml.safe_load(_get_template( 'hot_image_before_processed_image.yaml')) - expected_dict = yaml.load(_get_template( + expected_dict = yaml.safe_load(_get_template( 'hot_image_after_processed_image.yaml')) dummy_heat_res = { "image": { @@ -223,8 +223,9 @@ class TestToscaUtils(testtools.TestCase): def test_convert_unsupported_res_prop_kilo_ver(self): unsupported_res_prop_dict = {'OS::Neutron::Port': { 'port_security_enabled': 'value_specs', }, } - dummy_heat_dict = yaml.load(_get_template('hot_tosca_openwrt.yaml')) - expected_heat_dict = yaml.load(_get_template( + dummy_heat_dict = yaml.safe_load(_get_template( + 'hot_tosca_openwrt.yaml')) + expected_heat_dict = yaml.safe_load(_get_template( 'hot_tosca_openwrt_kilo.yaml')) toscautils.convert_unsupported_res_prop(dummy_heat_dict, unsupported_res_prop_dict) @@ -240,7 +241,7 @@ class TestToscaUtils(testtools.TestCase): 'network_name': 'net_mgmt', 'vendor': 'tacker'}}, 'requirements': {'virtualLink2': 'VL2', 'virtualLink1': 'VL1'}}} - template = yaml.load(tosca_sb_map) + template = yaml.safe_load(tosca_sb_map) toscautils.updateimports(template) toscautils.check_for_substitution_mappings(template, param) self.assertNotIn('substitution_mappings', param) diff --git a/tacker/vnfm/infra_drivers/openstack/openstack.py b/tacker/vnfm/infra_drivers/openstack/openstack.py index be91dde99..164a2bc55 100644 --- a/tacker/vnfm/infra_drivers/openstack/openstack.py +++ b/tacker/vnfm/infra_drivers/openstack/openstack.py @@ -200,13 +200,13 @@ class OpenStack(abstract_driver.DeviceAbstractDriver, LOG.debug('yaml orig %(orig)s update %(update)s', {'orig': config_yaml, 'update': update_yaml}) - # If config_yaml is None, yaml.load() will raise Attribute Error. + # If config_yaml is None, yaml.safe_load() will raise Attribute Error. # So set config_yaml to {}, if it is None. if not config_yaml: config_dict = {} else: - config_dict = yaml.load(config_yaml) or {} - update_dict = yaml.load(update_yaml) + config_dict = yaml.safe_load(config_yaml) or {} + update_dict = yaml.safe_load(update_yaml) if not update_dict: return @@ -225,7 +225,7 @@ class OpenStack(abstract_driver.DeviceAbstractDriver, deep_update(config_dict, update_dict) LOG.debug('dict new %(new)s update %(update)s', {'new': config_dict, 'update': update_dict}) - new_yaml = yaml.dump(config_dict) + new_yaml = yaml.safe_dump(config_dict) vnf_dict.setdefault('attributes', {})['config'] = new_yaml @log.log diff --git a/tacker/vnfm/infra_drivers/openstack/translate_template.py b/tacker/vnfm/infra_drivers/openstack/translate_template.py index bfcd8faf1..df6af6e66 100644 --- a/tacker/vnfm/infra_drivers/openstack/translate_template.py +++ b/tacker/vnfm/infra_drivers/openstack/translate_template.py @@ -25,6 +25,8 @@ from tacker.extensions import common_services as cs from tacker.extensions import vnfm from tacker.vnfm.tosca import utils as toscautils +from collections import OrderedDict + LOG = logging.getLogger(__name__) CONF = cfg.CONF @@ -136,7 +138,7 @@ class TOSCAToHOT(object): if is_scaling_needed: if is_enabled_alarm: main_dict['resources'].update(alarm_resource) - main_yaml = yaml.dump(main_dict) + main_yaml = yaml.safe_dump(main_dict) self.fields['template'] = main_yaml self.fields['files'] = {'scaling.yaml': self.heat_template_yaml} vnf['attributes']['heat_template'] = main_yaml @@ -181,7 +183,7 @@ class TOSCAToHOT(object): param_vattrs_yaml = dev_attrs.pop('param_values', None) if param_vattrs_yaml: try: - param_vattrs_dict = yaml.load(param_vattrs_yaml) + param_vattrs_dict = yaml.safe_load(param_vattrs_yaml) LOG.debug('param_vattrs_yaml', param_vattrs_dict) except Exception as e: LOG.debug("Not Well Formed: %s", str(e)) @@ -284,7 +286,7 @@ class TOSCAToHOT(object): parsed_params = {} if 'param_values' in dev_attrs and dev_attrs['param_values'] != "": try: - parsed_params = yaml.load(dev_attrs['param_values']) + parsed_params = yaml.safe_load(dev_attrs['param_values']) except Exception as e: LOG.debug("Params not Well Formed: %s", str(e)) raise vnfm.ParamYAMLNotWellFormed(error_msg_details=str(e)) @@ -328,7 +330,7 @@ class TOSCAToHOT(object): def _generate_hot_scaling(self, vnfd_dict, scale_resource_type="OS::Nova::Server"): # Initialize the template - template_dict = yaml.load(HEAT_TEMPLATE_BASE) + template_dict = yaml.safe_load(HEAT_TEMPLATE_BASE) template_dict['description'] = 'Tacker scaling template' parameters = {} @@ -429,6 +431,32 @@ class TOSCAToHOT(object): resources[policy_rsc_name] = policy_hot_in return resources, scaling_group_names + @log.log + def represent_odict(self, dump, tag, mapping, flow_style=None): + value = [] + node = yaml.MappingNode(tag, value, flow_style=flow_style) + if dump.alias_key is not None: + dump.represented_objects[dump.alias_key] = node + best_style = True + if hasattr(mapping, 'items'): + mapping = mapping.items() + for item_key, item_value in mapping: + node_key = dump.represent_data(item_key) + node_value = dump.represent_data(item_value) + if not (isinstance(node_key, yaml.ScalarNode) + and not node_key.style): + best_style = False + if not (isinstance(node_value, yaml.ScalarNode) + and not node_value.style): + best_style = False + value.append((node_key, node_value)) + if flow_style is None: + if dump.default_flow_style is not None: + node.flow_style = dump.default_flow_style + else: + node.flow_style = best_style + return node + @log.log def _generate_hot_alarm_resource(self, topology_tpl_dict): alarm_resource = dict() @@ -450,7 +478,10 @@ class TOSCAToHOT(object): trigger_name: trigger_dict}, self.vnf) heat_dict['resources'].update(alarm_resource) - heat_tpl_yaml = yaml.dump(heat_dict) + yaml.SafeDumper.add_representer(OrderedDict, + lambda dumper, value: self.represent_odict(dumper, + u'tag:yaml.org,2002:map', value)) + heat_tpl_yaml = yaml.safe_dump(heat_dict) return (is_enabled_alarm, alarm_resource, heat_tpl_yaml diff --git a/tacker/vnfm/mgmt_drivers/openwrt/openwrt.py b/tacker/vnfm/mgmt_drivers/openwrt/openwrt.py index 6fc294c22..f3ada2c51 100644 --- a/tacker/vnfm/mgmt_drivers/openwrt/openwrt.py +++ b/tacker/vnfm/mgmt_drivers/openwrt/openwrt.py @@ -79,7 +79,7 @@ class DeviceMgmtOpenWRT(abstract_driver.DeviceMGMTAbstractDriver): return vdus_config = dev_attrs.get('config', '') - config_yaml = yaml.load(vdus_config) + config_yaml = yaml.safe_load(vdus_config) if not config_yaml: return vdus_config_dict = config_yaml.get('vdus', {}) diff --git a/tacker/vnfm/plugin.py b/tacker/vnfm/plugin.py index f30bffe10..0e649877d 100644 --- a/tacker/vnfm/plugin.py +++ b/tacker/vnfm/plugin.py @@ -179,7 +179,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin): if vnfd_yaml is None: return - inner_vnfd_dict = yaml.load(vnfd_yaml) + inner_vnfd_dict = yaml.safe_load(vnfd_yaml) LOG.debug(_('vnfd_dict: %s'), inner_vnfd_dict) # Prepend the tacker_defs.yaml import file with the full @@ -224,7 +224,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin): def add_alarm_url_to_vnf(self, context, vnf_dict): vnfd_yaml = vnf_dict['vnfd']['attributes'].get('vnfd', '') - vnfd_dict = yaml.load(vnfd_yaml) + vnfd_dict = yaml.safe_load(vnfd_yaml) if vnfd_dict and vnfd_dict.get('tosca_definitions_version'): polices = vnfd_dict['topology_template'].get('policies', []) for policy_dict in polices: @@ -655,7 +655,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin): def get_vnf_policies( self, context, vnf_id, filters=None, fields=None): vnf = self.get_vnf(context, vnf_id) - vnfd_tmpl = yaml.load(vnf['vnfd']['attributes']['vnfd']) + vnfd_tmpl = yaml.safe_load(vnf['vnfd']['attributes']['vnfd']) policy_list = [] polices = vnfd_tmpl['topology_template'].get('policies', []) diff --git a/tacker/vnfm/tosca/utils.py b/tacker/vnfm/tosca/utils.py index b9d8f695f..05ffd1d79 100644 --- a/tacker/vnfm/tosca/utils.py +++ b/tacker/vnfm/tosca/utils.py @@ -25,6 +25,7 @@ from tacker.common import log from tacker.common import utils from tacker.extensions import vnfm +from collections import OrderedDict FAILURE = 'tosca.policies.tacker.Failure' LOG = logging.getLogger(__name__) @@ -225,6 +226,32 @@ def convert_unsupported_res_prop(heat_dict, unsupported_res_prop): prop_dict[new_prop] = prop_dict.pop(prop) +@log.log +def represent_odict(dump, tag, mapping, flow_style=None): + value = [] + node = yaml.MappingNode(tag, value, flow_style=flow_style) + if dump.alias_key is not None: + dump.represented_objects[dump.alias_key] = node + best_style = True + if hasattr(mapping, 'items'): + mapping = mapping.items() + for item_key, item_value in mapping: + node_key = dump.represent_data(item_key) + node_value = dump.represent_data(item_value) + if not (isinstance(node_key, yaml.ScalarNode) and not node_key.style): + best_style = False + if not (isinstance(node_value, yaml.ScalarNode) + and not node_value.style): + best_style = False + value.append((node_key, node_value)) + if flow_style is None: + if dump.default_flow_style is not None: + node.flow_style = dump.default_flow_style + else: + node.flow_style = best_style + return node + + @log.log def post_process_heat_template(heat_tpl, mgmt_ports, metadata, res_tpl, unsupported_res_prop=None): @@ -264,7 +291,12 @@ def post_process_heat_template(heat_tpl, mgmt_ports, metadata, if unsupported_res_prop: convert_unsupported_res_prop(heat_dict, unsupported_res_prop) - return yaml.dump(heat_dict) + + yaml.SafeDumper.add_representer(OrderedDict, + lambda dumper, value: represent_odict(dumper, + u'tag:yaml.org,2002:map', value)) + + return yaml.safe_dump(heat_dict) @log.log