def retrieve_plan(self, plan_uuid): """Loads the given plan. :type plan_uuid: str :rtype: tuskar.manager.models.DeploymentPlan :raises tuskar.storage.exceptions.UnknownUUID: if there is no plan with the given UUID """ # Load the plan from the database. db_plan = self.plan_store.retrieve(plan_uuid) # Parse the plan into the template model. master_template = parser.parse_template( db_plan.master_template.contents) environment = parser.parse_environment( db_plan.environment_file.contents) # Create the Tuskar model for the plan. deployment_plan = models.DeploymentPlan( plan_uuid, db_plan.name, master_template.description, created_at=db_plan.created_at, updated_at=db_plan.updated_at, ) roles = self._find_roles(environment) deployment_plan.add_roles(*roles) params = self._find_parameters(master_template, environment) deployment_plan.add_parameters(*params) return deployment_plan
def test_package_templates_seeded_plan(self): # Setup self.seed_store.create(MASTER_SEED_NAME, TEST_SEED) self.registry_store.create(RESOURCE_REGISTRY_NAME, RESOURCE_REGISTRY) # more setup (this is normally called in load_roles) self.registry_mapping_store.create('required_file.yaml', 'some fake template data') test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Test templates = self.plans_manager.package_templates(test_plan.uuid) # Verify self.assertTrue(isinstance(templates, dict)) self.assertEqual(4, len(templates)) self.assertTrue('plan.yaml' in templates) parsed_plan = parser.parse_template(templates['plan.yaml']) self.assertEqual(parsed_plan.description, 'd1') self.assertTrue('environment.yaml' in templates) self.assertTrue('required_file.yaml' in templates) parsed_env = parser.parse_environment(templates['environment.yaml']) self.assertEqual(2, len(parsed_env.registry_entries)) role_filename = name_utils.role_template_filename('r1', '1', None) self.assertTrue(role_filename in templates) parsed_role = parser.parse_template(templates[role_filename]) self.assertEqual(parsed_role.description, 'Test provider resource foo')
def set_parameter_values(self, plan_uuid, params): """Sets the values for a plan's parameters. :type plan_uuid: str :type params: [tuskar.manager.models.ParameterValue] :return: plan instance with the updated values :rtype: tuskar.manager.models.DeploymentPlan """ # Load the plan from the database. db_plan = self.plan_store.retrieve(plan_uuid) # Save the values to the parsed environment. environment = parser.parse_environment( db_plan.environment_file.contents ) for param_value in params: p = environment.find_parameter_by_name(param_value.name) p.value = param_value.value # Save the updated environment. env_contents = composer.compose_environment(environment) self.plan_store.update_environment(plan_uuid, env_contents) updated_plan = self.retrieve_plan(plan_uuid) return updated_plan
def test_package_templates_seeded_plan(self): # Setup self.seed_store.create(MASTER_SEED_NAME, TEST_SEED) self.registry_store.create(RESOURCE_REGISTRY_NAME, RESOURCE_REGISTRY) # more setup (this is normally called in load_roles) self.registry_mapping_store.create('required_file.yaml', 'some fake template data') test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Test templates = self.plans_manager.package_templates(test_plan.uuid) # Verify self.assertTrue(isinstance(templates, dict)) self.assertEqual(4, len(templates)) self.assertTrue('plan.yaml' in templates) parsed_plan = parser.parse_template(templates['plan.yaml']) self.assertEqual(parsed_plan.description, 'd1') self.assertTrue('environment.yaml' in templates) self.assertTrue('required_file.yaml' in templates) parsed_env = parser.parse_environment(templates['environment.yaml']) self.assertEqual(2, len(parsed_env.registry_entries)) role_filename = name_utils.role_template_filename('r1', '1', None) self.assertTrue(role_filename in templates) parsed_role = parser.parse_template(templates[role_filename]) self.assertEqual(parsed_role.description, 'Test provider resource foo')
def test_parse_environment(self): # Test e = parser.parse_environment(TEST_ENVIRONMENT) # Verify self.assertTrue(isinstance(e, heat.Environment)) # Parameters self.assertEqual(3, len(e.parameters)) ordered_params = sorted(e.parameters, key=lambda x: x.name) self.assertEqual('image_id', ordered_params[0].name) self.assertEqual('3e6270da-fbf7-4aef-bc78-6d0cfc3ad11b', ordered_params[0].value) self.assertEqual('instance_type', ordered_params[1].name) self.assertEqual('m1.small', ordered_params[1].value) self.assertEqual('key_name', ordered_params[2].name) self.assertEqual('heat_key', ordered_params[2].value) # Resource Registry self.assertEqual(3, len(e.registry_entries)) ordered_entries = sorted(e.registry_entries, key=lambda x: x.alias) self.assertEqual('OS::TripleO::SoftwareDeployment', ordered_entries[0].alias) self.assertEqual('OS::Heat::StructuredDeployment', ordered_entries[0].filename) self.assertEqual('Tuskar::Bar', ordered_entries[1].alias) self.assertEqual('provider-bar.yaml', ordered_entries[1].filename) self.assertEqual('Tuskar::Foo', ordered_entries[2].alias) self.assertEqual('provider-foo.yaml', ordered_entries[2].filename)
def test_parse_environment(self): # Test e = parser.parse_environment(TEST_ENVIRONMENT) # Verify self.assertTrue(isinstance(e, heat.Environment)) # Parameters self.assertEqual(3, len(e.parameters)) ordered_params = sorted(e.parameters, key=lambda x: x.name) self.assertEqual('image_id', ordered_params[0].name) self.assertEqual('3e6270da-fbf7-4aef-bc78-6d0cfc3ad11b', ordered_params[0].value) self.assertEqual('instance_type', ordered_params[1].name) self.assertEqual('m1.small', ordered_params[1].value) self.assertEqual('key_name', ordered_params[2].name) self.assertEqual('heat_key', ordered_params[2].value) # Resource Registry self.assertEqual(2, len(e.registry_entries)) ordered_entries = sorted(e.registry_entries, key=lambda x: x.alias) self.assertEqual('Tuskar::Bar', ordered_entries[0].alias) self.assertEqual('provider-bar.yaml', ordered_entries[0].filename) self.assertEqual('Tuskar::Foo', ordered_entries[1].alias) self.assertEqual('provider-foo.yaml', ordered_entries[1].filename)
def test_package_templates(self): # Setup test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Test templates = self.plans_manager.package_templates(test_plan.uuid) # Verify self.assertTrue(isinstance(templates, dict)) self.assertEqual(3, len(templates)) self.assertTrue('plan.yaml' in templates) parsed_plan = parser.parse_template(templates['plan.yaml']) self.assertEqual(parsed_plan.description, 'd1') self.assertTrue('environment.yaml' in templates) parsed_env = parser.parse_environment(templates['environment.yaml']) self.assertEqual(1, len(parsed_env.registry_entries)) role_filename = name_utils.role_template_filename('r1', '1', None) self.assertTrue(role_filename in templates) parsed_role = parser.parse_template(templates[role_filename]) self.assertEqual(parsed_role.description, 'Test provider resource foo')
def test_package_templates(self): # Setup test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Test templates = self.plans_manager.package_templates(test_plan.uuid) # Verify self.assertTrue(isinstance(templates, dict)) self.assertEqual(3, len(templates)) self.assertTrue('plan.yaml' in templates) parsed_plan = parser.parse_template(templates['plan.yaml']) self.assertEqual(parsed_plan.description, 'd1') self.assertTrue('environment.yaml' in templates) parsed_env = parser.parse_environment(templates['environment.yaml']) self.assertEqual(1, len(parsed_env.registry_entries)) role_filename = name_utils.role_template_filename('r1', '1', None) self.assertTrue(role_filename in templates) parsed_role = parser.parse_template(templates[role_filename]) self.assertEqual(parsed_role.description, 'Test provider resource foo')
def _plan_to_template_object(db_plan): master_template = parser.parse_template( db_plan.master_template.contents) environment = parser.parse_environment( db_plan.environment_file.contents) deployment_plan = plan.DeploymentPlan(master_template=master_template, environment=environment) return deployment_plan
def _plan_to_template_object(db_plan): master_template = parser.parse_template( db_plan.master_template.contents ) environment = parser.parse_environment( db_plan.environment_file.contents ) deployment_plan = plan.DeploymentPlan(master_template=master_template, environment=environment) return deployment_plan
def _check_roles_in_use(role_ids): manager = PlansManager() plan_list = manager.list_plans() plan_store = DeploymentPlanStore() for plan in plan_list: db_plan = plan_store.retrieve(plan.uuid) environment = parser.parse_environment( db_plan.environment_file.contents ) roles_in_use = ( [role.uuid for role in manager._find_roles(environment)]) intersection = set(roles_in_use) & set(role_ids) if intersection: raise OvercloudRoleInUse(name=", ".join(intersection))
def _check_roles_in_use(role_ids): manager = PlansManager() plan_list = manager.list_plans() plan_store = DeploymentPlanStore() for plan in plan_list: db_plan = plan_store.retrieve(plan.uuid) environment = parser.parse_environment( db_plan.environment_file.contents) roles_in_use = ([ role.uuid for role in manager._find_roles(environment) ]) intersection = set(roles_in_use) & set(role_ids) if intersection: raise OvercloudRoleInUse(name=", ".join(intersection))
def set_parameter_values(self, plan_uuid, params): """Sets the values for a plan's parameters. :type plan_uuid: str :type params: [tuskar.manager.models.ParameterValue] :return: plan instance with the updated values :rtype: tuskar.manager.models.DeploymentPlan """ # Load the plan from the database. db_plan = self.plan_store.retrieve(plan_uuid) # Save the values to the parsed environment. environment = parser.parse_environment( db_plan.environment_file.contents ) non_existent_params = [] for param_value in params: p = environment.find_parameter_by_name(param_value.name) if p: p.value = param_value.value else: non_existent_params.append(param_value.name) if non_existent_params: param_names = ', '.join(non_existent_params) LOG.error( 'There are no parameters named %(param_names)s' ' in plan %(plan_uuid)s.' % {'param_names': param_names, 'plan_uuid': plan_uuid}) raise exception.PlanParametersNotExist( plan_uuid=plan_uuid, param_names=param_names ) # Save the updated environment. env_contents = composer.compose_environment(environment) self.plan_store.update_environment(plan_uuid, env_contents) updated_plan = self.retrieve_plan(plan_uuid) return updated_plan
def set_parameter_values(self, plan_uuid, params): """Sets the values for a plan's parameters. :type plan_uuid: str :type params: [tuskar.manager.models.ParameterValue] :return: plan instance with the updated values :rtype: tuskar.manager.models.DeploymentPlan """ # Load the plan from the database. db_plan = self.plan_store.retrieve(plan_uuid) # Save the values to the parsed environment. environment = parser.parse_environment( db_plan.environment_file.contents ) non_existent_params = [] for param_value in params: p = environment.find_parameter_by_name(param_value.name) if p: p.value = param_value.value else: non_existent_params.append(param_value.name) if non_existent_params: param_names = ', '.join(non_existent_params) LOG.error( 'There are no parameters named %(param_names)s' ' in plan %(plan_uuid)s.' % {'param_names': param_names, 'plan_uuid': plan_uuid}) raise exception.PlanParametersNotExist( plan_uuid=plan_uuid, param_names=param_names ) # Save the updated environment. env_contents = composer.compose_environment(environment) self.plan_store.update_environment(plan_uuid, env_contents) updated_plan = self.retrieve_plan(plan_uuid) return updated_plan
def test_find_roles(self): # Setup self.seed_store.create(MASTER_SEED_NAME, TEST_SEED) self.registry_store.create(RESOURCE_REGISTRY_NAME, RESOURCE_REGISTRY) # more setup (this is normally called in load_roles) self.registry_mapping_store.create('required_file.yaml', 'some fake template data') test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') # Test self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Verify only one role is found db_plan = self.plan_store.retrieve(test_plan.uuid) parsed_env = parser.parse_environment( db_plan.environment_file.contents) roles = self.plans_manager._find_roles(parsed_env) self.assertEqual(1, len(roles))
def package_templates(self, plan_uuid): """Packages and returns all of the templates related to the given plan. The returned dictionary is keyed by filename and contains the contents of that file (a template or an environment file). :type plan_uuid: str :return: mapping of filename to contents for each file in the plan :rtype: dict :raises tuskar.storage.exceptions.UnknownUUID: if there is no plan with the given UUID """ # Load and parse the plan. db_plan = self.plan_store.retrieve(plan_uuid) master_template = parser.parse_template( db_plan.master_template.contents ) environment = parser.parse_environment( db_plan.environment_file.contents ) # Compose the plan files and all plan roles and package them into # a single dictionary. plan_contents = composer.compose_template(master_template) env_contents = composer.compose_environment(environment) files_dict = { 'plan.yaml': plan_contents, 'environment.yaml': env_contents, } plan_roles = self._find_roles(environment) for role in plan_roles: contents = composer.compose_template(role.template) filename = name_utils.role_template_filename(role.name, role.version) files_dict[filename] = contents return files_dict
def package_templates(self, plan_uuid): """Packages and returns all of the templates related to the given plan. The returned dictionary is keyed by filename and contains the contents of that file (a template or an environment file). :type plan_uuid: str :return: mapping of filename to contents for each file in the plan :rtype: dict :raises tuskar.storage.exceptions.UnknownUUID: if there is no plan with the given UUID """ # Load and parse the plan. db_plan = self.plan_store.retrieve(plan_uuid) master_template = parser.parse_template( db_plan.master_template.contents ) environment = parser.parse_environment( db_plan.environment_file.contents ) # Compose the plan files and all plan roles and package them into # a single dictionary. plan_contents = composer.compose_template(master_template) env_contents = composer.compose_environment(environment) files_dict = { 'plan.yaml': plan_contents, 'environment.yaml': env_contents, } plan_roles = self._find_roles(environment) for role in plan_roles: contents = composer.compose_template(role.template) filename = name_utils.role_template_filename(role.name, role.version) files_dict[filename] = contents return files_dict
def test_find_roles(self): # Setup self.seed_store.create(MASTER_SEED_NAME, TEST_SEED) self.registry_store.create(RESOURCE_REGISTRY_NAME, RESOURCE_REGISTRY) # more setup (this is normally called in load_roles) self.registry_mapping_store.create('required_file.yaml', 'some fake template data') test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') # Test self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Verify only one role is found db_plan = self.plan_store.retrieve(test_plan.uuid) parsed_env = parser.parse_environment( db_plan.environment_file.contents ) roles = self.plans_manager._find_roles(parsed_env) self.assertEqual(1, len(roles))
def retrieve_plan(self, plan_uuid): """Loads the given plan. :type plan_uuid: str :rtype: tuskar.manager.models.DeploymentPlan :raises tuskar.storage.exceptions.UnknownUUID: if there is no plan with the given UUID """ # Load the plan from the database. db_plan = self.plan_store.retrieve(plan_uuid) # Parse the plan into the template model. master_template = parser.parse_template( db_plan.master_template.contents ) environment = parser.parse_environment( db_plan.environment_file.contents ) # Create the Tuskar model for the plan. deployment_plan = models.DeploymentPlan( plan_uuid, db_plan.name, master_template.description, created_at=db_plan.created_at, updated_at=db_plan.updated_at, ) roles = self._find_roles(environment) deployment_plan.add_roles(*roles) params = self._find_parameters(master_template, environment) deployment_plan.add_parameters(*params) return deployment_plan
def test_add_role_to_seeded_plan(self): # Setup self.seed_store.create(MASTER_SEED_NAME, TEST_SEED) self.registry_store.create(RESOURCE_REGISTRY_NAME, RESOURCE_REGISTRY) # more setup (this is normally called in load_roles) self.registry_mapping_store.create('required_file.yaml', 'some fake template data') test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') # Test self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Verify db_plan = self.plan_store.retrieve(test_plan.uuid) parsed_plan = parser.parse_template(db_plan.master_template.contents) self.assertEqual(2, len(parsed_plan.resources)) # The role generated in the plan has a different name: my_role = parsed_plan.find_resource_by_id('r1') self.assertIsNot(my_role, None) # The reference to the role in some_config should be updated: some_config = parsed_plan.find_resource_by_id('some_config') self.assertIsNot(some_config, None) config_property = some_config.find_property_by_name('config') self.assertIsNot(config_property, None) self.assertEqual(config_property.value, {'ip_addresses': { 'get_attr': ['r1', 'foo_ip'] }}) # verify both entries are present from RESOURCE_REGISTRY parsed_env = parser.parse_environment( db_plan.environment_file.contents) self.assertEqual(2, len(parsed_env.registry_entries))
def test_add_role_to_seeded_plan(self): # Setup self.seed_store.create(MASTER_SEED_NAME, TEST_SEED) self.registry_store.create(RESOURCE_REGISTRY_NAME, RESOURCE_REGISTRY) # more setup (this is normally called in load_roles) self.registry_mapping_store.create('required_file.yaml', 'some fake template data') test_role = self._add_test_role() test_plan = self.plans_manager.create_plan('p1', 'd1') # Test self.plans_manager.add_role_to_plan(test_plan.uuid, test_role.uuid) # Verify db_plan = self.plan_store.retrieve(test_plan.uuid) parsed_plan = parser.parse_template(db_plan.master_template.contents) self.assertEqual(2, len(parsed_plan.resources)) # The role generated in the plan has a different name: my_role = parsed_plan.find_resource_by_id('r1') self.assertIsNot(my_role, None) # The reference to the role in some_config should be updated: some_config = parsed_plan.find_resource_by_id('some_config') self.assertIsNot(some_config, None) config_property = some_config.find_property_by_name('config') self.assertIsNot(config_property, None) self.assertEqual(config_property.value, {'ip_addresses': {'get_attr': ['r1', 'foo_ip']}}) # verify both entries are present from RESOURCE_REGISTRY parsed_env = parser.parse_environment( db_plan.environment_file.contents ) self.assertEqual(2, len(parsed_env.registry_entries))
def add_role_to_plan(self, plan_uuid, role_uuid): """Adds a role to the given plan, storing the changes in Tuskar's storage. :type plan_uuid: str :type role_uuid: str :return: updated plan model instance :rtype: tuskar.manager.models.DeploymentPlan :raises tuskar.storage.exceptions.UnknownUUID: if either the plan or the role cannot be found """ # Load the plan and role from storage db_plan = self.plan_store.retrieve(plan_uuid) db_role = self.template_store.retrieve(role_uuid) # Parse the plan and role template into template objects. deployment_plan = self._plan_to_template_object(db_plan) role_template = self._role_to_template_object(db_role) # See if a master seed template has been set. try: db_master_seed = self.seed_store.retrieve_by_name(MASTER_SEED_NAME) master_seed = parser.parse_template(db_master_seed.contents) except UnknownName: master_seed = None special_properties = None def _find_role_type(registry): for path in registry.keys(): if path in db_role.registry_path: return registry[path] if master_seed is not None: try: db_registry_env = self.registry_store.retrieve_by_name( RESOURCE_REGISTRY_NAME).contents except UnknownName: LOG.error("Could not load resource_registry. Make sure you " "pass --resource-registry to tuskar-load-roles.") raise parsed_registry_env = parser.parse_environment(db_registry_env) registry = dict((e.filename, e.alias) for e in parsed_registry_env.registry_entries) role_type = _find_role_type(registry) special_properties = template_seed.get_property_map_for_role( master_seed, role_type) # Use the combination logic to perform the addition. role_namespace = name_utils.generate_role_namespace(db_role.name, db_role.version) template_filename = ( name_utils.role_template_filename(db_role.name, db_role.version, db_role.relative_path)) deployment_plan.add_template(role_namespace, role_template, template_filename, override_properties=special_properties) # If there is a master seed, add its top-level elements to the plan. # These calls are idempotent, so it's safe to call each time a role # is added. if master_seed is not None: template_seed.add_top_level_parameters( master_seed, deployment_plan.master_template, deployment_plan.environment) template_seed.add_top_level_resources( master_seed, deployment_plan.master_template) template_seed.add_top_level_outputs( master_seed, deployment_plan.master_template) if role_type is None: LOG.error( "Role '%s' not found in seed template." % db_role.name) raise ValueError(db_role.name) seed_role = template_seed.find_role_from_type( master_seed.resources, role_type) if seed_role is None: LOG.error( "Role '%s' of type '%s' not found in seed template." % (db_role.name, role_type)) raise ValueError(db_role.name) # These calls are idempotent, but must be called on each role as # new references may have been added. template_seed.update_role_resource_references( deployment_plan.master_template, seed_role, db_role.name) template_seed.update_role_property_references( deployment_plan.master_template, seed_role, role_namespace) # Update environment file to add top level mappings, which is made # up of all non-role files present in the resource registry, plus # required aliases reg_mapping = self.registry_mapping_store.list() environment = deployment_plan.environment for entry in parsed_registry_env.registry_entries: # check if registry_mapping is in database, if so add to # environment (later will become environment.yaml) if any(x.name == entry.filename for x in reg_mapping): additem = RegistryEntry(entry.alias, entry.filename) environment.add_registry_entry(additem, unique=True) # Save the updated plan. updated = self._save_updated_plan(plan_uuid, deployment_plan) return updated
def package_templates(self, plan_uuid): """Packages and returns all of the templates related to the given plan. The returned dictionary is keyed by filename and contains the contents of that file (a template or an environment file). :type plan_uuid: str :return: mapping of filename to contents for each file in the plan :rtype: dict :raises tuskar.storage.exceptions.UnknownUUID: if there is no plan with the given UUID """ # Load and parse the plan. db_plan = self.plan_store.retrieve(plan_uuid) master_template = parser.parse_template( db_plan.master_template.contents) environment = parser.parse_environment( db_plan.environment_file.contents) # Compose the plan files and all plan roles and package them into # a single dictionary. plan_contents = composer.compose_template(master_template) env_contents = composer.compose_environment(environment) files_dict = { 'plan.yaml': plan_contents, 'environment.yaml': env_contents, } plan_roles = self._find_roles(environment) manager = RoleManager() for role in plan_roles: contents = composer.compose_template(role.template) filename = name_utils.role_template_filename( role.name, role.version, role.relative_path) files_dict[filename] = contents def _add_template_extra_data_for(templates, template_store): template_extra_data = manager.retrieve_db_role_extra() for template in templates: db_template = template_store.retrieve_by_name(template.name) prefix = os_path.split(db_template.name)[0] template_extra_paths = utils.resolve_template_extra_data( db_template, template_extra_data) extra_data_output = manager.template_extra_data_for_output( template_extra_paths, prefix) files_dict.update(extra_data_output) # also grab any extradata files for the role _add_template_extra_data_for(plan_roles, self.template_store) # in addition to provider roles above, return non-role template files reg_mapping = self.registry_mapping_store.list() for entry in reg_mapping: if os_path.splitext(entry.name)[1] in ('.yaml', '.yml'): # if entry is an alias, don't include it files_dict[entry.name] = entry.contents # similarly, also grab extradata files for the non role templates _add_template_extra_data_for(reg_mapping, self.registry_mapping_store) return files_dict
def add_role_to_plan(self, plan_uuid, role_uuid): """Adds a role to the given plan, storing the changes in Tuskar's storage. :type plan_uuid: str :type role_uuid: str :return: updated plan model instance :rtype: tuskar.manager.models.DeploymentPlan :raises tuskar.storage.exceptions.UnknownUUID: if either the plan or the role cannot be found """ # Load the plan and role from storage db_plan = self.plan_store.retrieve(plan_uuid) db_role = self.template_store.retrieve(role_uuid) # Parse the plan and role template into template objects. deployment_plan = self._plan_to_template_object(db_plan) role_template = self._role_to_template_object(db_role) # See if a master seed template has been set. try: db_master_seed = self.seed_store.retrieve_by_name(MASTER_SEED_NAME) master_seed = parser.parse_template(db_master_seed.contents) except UnknownName: master_seed = None special_properties = None if master_seed is not None: try: db_registry_env = self.registry_store.retrieve_by_name( RESOURCE_REGISTRY_NAME).contents except UnknownName: LOG.error("Could not load resource_registry. Make sure you " "pass --resource-registry to tuskar-load-roles.") raise parsed_registry_env = parser.parse_environment(db_registry_env) registry = dict((role_name_from_path(e.filename), e.alias) for e in parsed_registry_env.registry_entries) special_properties = template_seed.get_property_map_for_role( master_seed, registry[db_role.name]) # Use the combination logic to perform the addition. role_namespace = name_utils.generate_role_namespace(db_role.name, db_role.version) template_filename = name_utils.role_template_filename(db_role.name, db_role.version) deployment_plan.add_template(role_namespace, role_template, template_filename, override_properties=special_properties) # If there is a master seed, add its top-level elements to the plan. # These calls are idempotent, so it's safe to call each time a role # is added. if master_seed is not None: template_seed.add_top_level_parameters( master_seed, deployment_plan.master_template, deployment_plan.environment) template_seed.add_top_level_resources( master_seed, deployment_plan.master_template) template_seed.add_top_level_outputs( master_seed, deployment_plan.master_template) try: role_type = registry[db_role.name] except KeyError: LOG.error( "Role '%s' not found in seed template." % db_role.name) raise seed_role = template_seed.find_role_from_type( master_seed.resources, role_type) if seed_role is None: LOG.error( "Role '%s' of type '%s' not found in seed template." % (db_role.name, role_type)) raise ValueError(db_role.name) # These calls are idempotent, but must be called on each role as # new references may have been added. template_seed.update_role_resource_references( deployment_plan.master_template, seed_role, plan.generate_group_id(role_namespace)) template_seed.update_role_property_references( deployment_plan.master_template, seed_role, role_namespace) # Save the updated plan. updated = self._save_updated_plan(plan_uuid, deployment_plan) return updated
def load_roles(roles, seed_file=None, resource_registry_path=None, role_extra=None): """Given a list of roles files import them into the add any to the store. TemplateStore. The returned tuple contains all the role names and then the names split over where were created and updated. On a dry run the first item will contain all of the roles found while the second two will be empty lists as no files were updated or created. :param roles: A list of yaml files (as strings) :type roles: [str] :param seed_file: full path to the template seed that should be used for plan master templates :type seed_file: str :param resource_registry_path: path to the Heat environment which declares the custom types for Tuskar roles. :type resource_registry_path: str :param role_extra: A list of yaml files (as strings) that may be consumed (referenced) by any of the role files. :type roles: [str] :return: Summary of the results as a tuple with the total count and then the names of the created and updated roles. :rtype: tuple(list, list, list) """ all_roles, created, updated = [], [], [] def _process_roles(roles, store=None): for role_name, role_path in roles: process_role(role_path, role_name, store, all_roles, created, updated) roles = [(role_name_from_path(r), r) for r in roles] _process_roles(roles) template_extra_store = TemplateExtraStore() if role_extra is not None: role_extra = [(utils.resolve_role_extra_name_from_path(re), re) for re in role_extra] _process_roles(role_extra, template_extra_store) if seed_file is not None: process_role(seed_file, MASTER_SEED_NAME, MasterSeedStore(), all_roles, created, updated) if resource_registry_path is not None: process_role(resource_registry_path, RESOURCE_REGISTRY_NAME, ResourceRegistryStore(), all_roles, created, updated) contents = load_file(resource_registry_path) parsed_env = parser.parse_environment(contents) mapping_store = ResourceRegistryMappingStore() dirname = path.dirname(resource_registry_path) role_paths = [r[1] for r in roles] for entry in parsed_env.registry_entries: complete_path = path.join(dirname, entry.filename) # skip adding if template has already been stored as a role if (complete_path in role_paths): continue if (entry.is_filename()): process_role(complete_path, entry.filename, mapping_store, None, created, updated) else: # if entry is not a filename, (is an alias) add to mappings create_or_update(entry.filename, entry.alias, mapping_store) return all_roles, created, updated
def package_templates(self, plan_uuid): """Packages and returns all of the templates related to the given plan. The returned dictionary is keyed by filename and contains the contents of that file (a template or an environment file). :type plan_uuid: str :return: mapping of filename to contents for each file in the plan :rtype: dict :raises tuskar.storage.exceptions.UnknownUUID: if there is no plan with the given UUID """ # Load and parse the plan. db_plan = self.plan_store.retrieve(plan_uuid) master_template = parser.parse_template( db_plan.master_template.contents ) environment = parser.parse_environment( db_plan.environment_file.contents ) # Compose the plan files and all plan roles and package them into # a single dictionary. plan_contents = composer.compose_template(master_template) env_contents = composer.compose_environment(environment) files_dict = { 'plan.yaml': plan_contents, 'environment.yaml': env_contents, } plan_roles = self._find_roles(environment) manager = RoleManager() for role in plan_roles: contents = composer.compose_template(role.template) filename = name_utils.role_template_filename(role.name, role.version, role.relative_path) files_dict[filename] = contents def _add_template_extra_data_for(templates, template_store): template_extra_data = manager.retrieve_db_role_extra() for template in templates: db_template = template_store.retrieve_by_name(template.name) prefix = os_path.split(db_template.name)[0] template_extra_paths = utils.resolve_template_extra_data( db_template, template_extra_data) extra_data_output = manager.template_extra_data_for_output( template_extra_paths, prefix) files_dict.update(extra_data_output) # also grab any extradata files for the role _add_template_extra_data_for(plan_roles, self.template_store) # in addition to provider roles above, return non-role template files reg_mapping = self.registry_mapping_store.list() for entry in reg_mapping: if os_path.splitext(entry.name)[1] in ('.yaml', '.yml'): # if entry is an alias, don't include it files_dict[entry.name] = entry.contents # similarly, also grab extradata files for the non role templates _add_template_extra_data_for(reg_mapping, self.registry_mapping_store) return files_dict
def add_role_to_plan(self, plan_uuid, role_uuid): """Adds a role to the given plan, storing the changes in Tuskar's storage. :type plan_uuid: str :type role_uuid: str :return: updated plan model instance :rtype: tuskar.manager.models.DeploymentPlan :raises tuskar.storage.exceptions.UnknownUUID: if either the plan or the role cannot be found """ # Load the plan and role from storage db_plan = self.plan_store.retrieve(plan_uuid) db_role = self.template_store.retrieve(role_uuid) # Parse the plan and role template into template objects. deployment_plan = self._plan_to_template_object(db_plan) role_template = self._role_to_template_object(db_role) # See if a master seed template has been set. try: db_master_seed = self.seed_store.retrieve_by_name(MASTER_SEED_NAME) master_seed = parser.parse_template(db_master_seed.contents) except UnknownName: master_seed = None special_properties = None def _find_role_type(registry): for path in registry.keys(): if path in db_role.registry_path: return registry[path] if master_seed is not None: try: db_registry_env = self.registry_store.retrieve_by_name( RESOURCE_REGISTRY_NAME).contents except UnknownName: LOG.error("Could not load resource_registry. Make sure you " "pass --resource-registry to tuskar-load-roles.") raise parsed_registry_env = parser.parse_environment(db_registry_env) registry = dict((e.filename, e.alias) for e in parsed_registry_env.registry_entries) role_type = _find_role_type(registry) special_properties = template_seed.get_property_map_for_role( master_seed, role_type) # Use the combination logic to perform the addition. role_namespace = name_utils.generate_role_namespace( db_role.name, db_role.version) template_filename = (name_utils.role_template_filename( db_role.name, db_role.version, db_role.relative_path)) deployment_plan.add_template(role_namespace, role_template, template_filename, override_properties=special_properties) # If there is a master seed, add its top-level elements to the plan. # These calls are idempotent, so it's safe to call each time a role # is added. if master_seed is not None: template_seed.add_top_level_parameters( master_seed, deployment_plan.master_template, deployment_plan.environment) template_seed.add_top_level_resources( master_seed, deployment_plan.master_template) template_seed.add_top_level_outputs( master_seed, deployment_plan.master_template) if role_type is None: LOG.error("Role '%s' not found in seed template." % db_role.name) raise ValueError(db_role.name) seed_role = template_seed.find_role_from_type( master_seed.resources, role_type) if seed_role is None: LOG.error( "Role '%s' of type '%s' not found in seed template." % (db_role.name, role_type)) raise ValueError(db_role.name) # These calls are idempotent, but must be called on each role as # new references may have been added. template_seed.update_role_resource_references( deployment_plan.master_template, seed_role, db_role.name) template_seed.update_role_property_references( deployment_plan.master_template, seed_role, role_namespace) # Update environment file to add top level mappings, which is made # up of all non-role files present in the resource registry, plus # required aliases reg_mapping = self.registry_mapping_store.list() environment = deployment_plan.environment for entry in parsed_registry_env.registry_entries: # check if registry_mapping is in database, if so add to # environment (later will become environment.yaml) if any(x.name == entry.filename for x in reg_mapping): additem = RegistryEntry(entry.alias, entry.filename) environment.add_registry_entry(additem, unique=True) # Save the updated plan. updated = self._save_updated_plan(plan_uuid, deployment_plan) return updated
def load_roles(roles, seed_file=None, resource_registry_path=None, role_extra=None): """Given a list of roles files import them into the add any to the store. TemplateStore. The returned tuple contains all the role names and then the names split over where were created and updated. On a dry run the first item will contain all of the roles found while the second two will be empty lists as no files were updated or created. :param roles: A list of yaml files (as strings) :type roles: [str] :param seed_file: full path to the template seed that should be used for plan master templates :type seed_file: str :param resource_registry_path: path to the Heat environment which declares the custom types for Tuskar roles. :type resource_registry_path: str :param role_extra: A list of yaml files (as strings) that may be consumed (referenced) by any of the role files. :type roles: [str] :return: Summary of the results as a tuple with the total count and then the names of the created and updated roles. :rtype: tuple(list, list, list) """ all_roles, created, updated = [], [], [] def _process_roles(roles, store=None): for role_name, role_path in roles: process_role(role_path, role_name, store, all_roles, created, updated) roles = [(role_name_from_path(r), r) for r in roles] _process_roles(roles) template_extra_store = TemplateExtraStore() if role_extra is not None: role_extra = [(utils.resolve_role_extra_name_from_path(re), re) for re in role_extra] _process_roles(role_extra, template_extra_store) if seed_file is not None: process_role(seed_file, MASTER_SEED_NAME, MasterSeedStore(), all_roles, created, updated) if resource_registry_path is not None: process_role(resource_registry_path, RESOURCE_REGISTRY_NAME, ResourceRegistryStore(), all_roles, created, updated) contents = load_file(resource_registry_path) parsed_env = parser.parse_environment(contents) mapping_store = ResourceRegistryMappingStore() dirname = path.dirname(resource_registry_path) role_paths = [r[1] for r in roles] for entry in parsed_env.registry_entries: complete_path = path.join(dirname, entry.filename) # skip adding if template has already been stored as a role if (complete_path in role_paths): continue if (entry.is_filename()): process_role(complete_path, entry.filename, mapping_store, None, created, updated) else: # if entry is not a filename, (is an alias) add to mappings create_or_update(entry.filename, entry.alias, mapping_store) return all_roles, created, updated