Example #1
0
    def _create_with_remote_credential(self,
                                       credential_secret_id=None,
                                       ca_cert=None,
                                       insecure=False):

        t = template_format.parse(parent_stack_template)
        properties = t['resources']['remote_stack']['properties']
        if credential_secret_id:
            properties['context']['credential_secret_id'] = (
                credential_secret_id)
        if ca_cert:
            properties['context']['ca_cert'] = (ca_cert)
        if insecure:
            properties['context']['insecure'] = insecure
        t = json.dumps(t)
        self.patchobject(policy.Enforcer, 'check_is_admin')

        rsrc = self.create_remote_stack(stack_template=t)
        env = environment.get_child_environment(rsrc.stack.env,
                                                {'name': 'foo'})
        args = {
            'stack_name': rsrc.physical_resource_name(),
            'template': template_format.parse(remote_template),
            'timeout_mins': 60,
            'disable_rollback': True,
            'parameters': {
                'name': 'foo'
            },
            'files': self.files,
            'environment': env.user_env_as_dict(),
        }
        self.heat.stacks.create.assert_called_with(**args)
        self.assertEqual(2, len(self.heat.stacks.get.call_args_list))
        rsrc.validate()
        return rsrc
Example #2
0
    def _create_with_remote_credential(self, credential_secret_id=None,
                                       ca_cert=None, insecure=False):

        t = template_format.parse(parent_stack_template)
        properties = t['resources']['remote_stack']['properties']
        if credential_secret_id:
            properties['context']['credential_secret_id'] = (
                credential_secret_id)
        if ca_cert:
            properties['context']['ca_cert'] = (
                ca_cert)
        if insecure:
            properties['context']['insecure'] = insecure
        t = json.dumps(t)
        self.patchobject(policy.Enforcer, 'check_is_admin')

        rsrc = self.create_remote_stack(stack_template=t)
        env = environment.get_child_environment(rsrc.stack.env,
                                                {'name': 'foo'})
        args = {
            'stack_name': rsrc.physical_resource_name(),
            'template': template_format.parse(remote_template),
            'timeout_mins': 60,
            'disable_rollback': True,
            'parameters': {'name': 'foo'},
            'files': self.files,
            'environment': env.user_env_as_dict(),
        }
        self.heat.stacks.create.assert_called_with(**args)
        self.assertEqual(2, len(self.heat.stacks.get.call_args_list))
        rsrc.validate()
        return rsrc
Example #3
0
    def _create_template(self, num_instances, num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self,
                                                          include_failed=True)
        definitions = list(template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace,
            short_id.generate_id))

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(), item_to_remove=self.resource_info)

        tmpl = template.make_template(definitions, version=template_version,
                                      child_env=child_env)

        # Subclasses use HOT templates
        att_func, res_func = 'get_attr', 'get_resource'
        if att_func not in tmpl.functions or res_func not in tmpl.functions:
            att_func, res_func = 'Fn::GetAtt', 'Ref'
        get_attr = functools.partial(tmpl.functions[att_func], None, att_func)
        get_res = functools.partial(tmpl.functions[res_func], None, res_func)
        for odefn in self._nested_output_defns([k for k, d in definitions],
                                               get_attr, get_res):
            tmpl.add_output(odefn)

        return tmpl
Example #4
0
    def _stack_kwargs(self, user_params, child_template, adopt_data=None):

        if user_params is None:
            user_params = self.child_params()
        if child_template is None:
            child_template = self.child_template()
        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)
        if adopt_data is None:
            template_id = parsed_template.store(self.context)
            return {
                'template_id': template_id,
                'template': None,
                'params': None,
                'files': None,
            }
        else:
            return {
                'template': parsed_template.t,
                'params': child_env.user_env_as_dict(),
                'files': parsed_template.files,
            }
Example #5
0
 def test_drill_down_prefer_exact_match(self):
     env = {
         u'resource_registry': {
             u'resources': {
                 u'*esource': {
                     u'hooks': 'pre-create',
                 },
                 u'res*': {
                     u'hooks': 'pre-create',
                 },
                 u'resource': {
                     u'OS::Fruit': u'carrots.yaml',
                     u'hooks': 'pre-update',
                 },
                 u'resource*': {
                     u'hooks': 'pre-create',
                 },
                 u'*resource': {
                     u'hooks': 'pre-create',
                 },
                 u'*sour*': {
                     u'hooks': 'pre-create',
                 },
             }
         }
     }
     penv = environment.Environment(env)
     cenv = environment.get_child_environment(
         penv, None, child_resource_name=u'resource')
     registry = cenv.user_env_as_dict()['resource_registry']
     resources = registry['resources']
     self.assertEqual(u'carrots.yaml', resources[u'OS::Fruit'])
     self.assertEqual('pre-update', resources[u'hooks'])
Example #6
0
 def test_drill_down_matching_wildcard(self):
     env = {
         u'resource_registry': {
             u'resources': {
                 u'nested': {
                     u'c': {
                         u'OS::Fruit': u'carrots.yaml',
                         u'hooks': 'pre-create',
                     },
                 },
                 u'nest*': {
                     u'nested_res': {
                         u'hooks': 'pre-create',
                     },
                 }
             }
         }
     }
     penv = environment.Environment(env)
     cenv = environment.get_child_environment(penv,
                                              None,
                                              child_resource_name=u'nested')
     registry = cenv.user_env_as_dict()['resource_registry']
     resources = registry['resources']
     self.assertIn('c', resources)
     self.assertIn('nested_res', resources)
     res = cenv.get_resource_info('OS::Fruit', resource_name='c')
     self.assertIsNotNone(res)
     self.assertEqual(u'carrots.yaml', res.value)
Example #7
0
 def test_drill_down_to_child_resource(self):
     env = {
         u'resource_registry': {
             u'OS::Food': u'fruity.yaml',
             u'resources': {
                 u'a': {
                     u'OS::Fruit': u'apples.yaml',
                     u'hooks': 'pre-create',
                 },
                 u'nested': {
                     u'b': {
                         u'OS::Fruit': u'carrots.yaml',
                     },
                     u'nested_res': {
                         u'hooks': 'pre-create',
                     }
                 }
             }
         }
     }
     penv = environment.Environment(env)
     cenv = environment.get_child_environment(penv,
                                              None,
                                              child_resource_name=u'nested')
     registry = cenv.user_env_as_dict()['resource_registry']
     resources = registry['resources']
     self.assertIn('nested_res', resources)
     self.assertIn('hooks', resources['nested_res'])
     self.assertIsNotNone(
         cenv.get_resource_info('OS::Food', resource_name='abc'))
     self.assertIsNone(
         cenv.get_resource_info('OS::Fruit', resource_name='a'))
     res = cenv.get_resource_info('OS::Fruit', resource_name='b')
     self.assertIsNotNone(res)
     self.assertEqual(u'carrots.yaml', res.value)
Example #8
0
    def _create_template(self, num_instances, num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self,
                                                          include_failed=True)
        definitions = list(template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace,
            short_id.generate_id))

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(), item_to_remove=self.resource_info)

        tmpl = template.make_template(definitions, version=template_version,
                                      child_env=child_env)

        # Subclasses use HOT templates
        att_func = 'get_attr'
        if att_func not in tmpl.functions:
            att_func = 'Fn::GetAtt'
        get_attr = functools.partial(tmpl.functions[att_func], None, att_func)
        for odefn in self._nested_output_defns([k for k, d in definitions],
                                               get_attr):
            tmpl.add_output(odefn)

        return tmpl
Example #9
0
 def test_registry_merge_favor_child(self):
     env1 = {u'resource_registry': {u'OS::Food': u'carrots.yaml'}}
     env2 = {u'resource_registry': {u'OS::Food': u'apples.yaml'}}
     penv = environment.Environment(env=env1)
     cenv = environment.get_child_environment(penv, env2)
     res = cenv.get_resource_info('OS::Food')
     self.assertEqual('apples.yaml', res.value)
Example #10
0
 def test_drill_down_to_child_resource(self):
     env = {
         u'resource_registry': {
             u'OS::Food': u'fruity.yaml',
             u'resources': {
                 u'a': {
                     u'OS::Fruit': u'apples.yaml',
                     u'hooks': 'pre-create',
                 },
                 u'nested': {
                     u'b': {
                         u'OS::Fruit': u'carrots.yaml',
                     },
                     u'nested_res': {
                         u'hooks': 'pre-create',
                     }
                 }
             }
         }
     }
     penv = environment.Environment(env)
     cenv = environment.get_child_environment(
         penv, None, child_resource_name=u'nested')
     registry = cenv.user_env_as_dict()['resource_registry']
     resources = registry['resources']
     self.assertIn('nested_res', resources)
     self.assertIn('hooks', resources['nested_res'])
     self.assertIsNotNone(
         cenv.get_resource_info('OS::Food', resource_name='abc'))
     self.assertIsNone(
         cenv.get_resource_info('OS::Fruit', resource_name='a'))
     res = cenv.get_resource_info('OS::Fruit', resource_name='b')
     self.assertIsNotNone(res)
     self.assertEqual(u'carrots.yaml', res.value)
Example #11
0
    def validate(self):
        super(RemoteStack, self).validate()

        try:
            self.heat()
        except Exception as ex:
            exc_info = dict(region=self._region_name, exc=six.text_type(ex))
            msg = _('Cannot establish connection to Heat endpoint at region '
                    '"%(region)s" due to "%(exc)s"') % exc_info
            raise exception.StackValidationFailed(message=msg)

        try:
            params = self.properties[self.PARAMETERS]
            env = environment.get_child_environment(self.stack.env, params)
            tmpl = template_format.parse(self.properties[self.TEMPLATE])
            args = {
                'template': tmpl,
                'files': self.stack.t.files,
                'environment': env.user_env_as_dict(),
            }
            self.heat().stacks.validate(**args)
        except Exception as ex:
            exc_info = dict(region=self._region_name, exc=six.text_type(ex))
            LOG.error(_LE('exception: %s'), type(ex))
            msg = _('Failed validating stack template using Heat endpoint at '
                    'region "%(region)s" due to "%(exc)s"') % exc_info
            raise exception.StackValidationFailed(message=msg)
Example #12
0
    def _create_template(self,
                         num_instances,
                         num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """
        Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = self._get_instance_templates()
        definitions = template.member_definitions(old_resources,
                                                  instance_definition,
                                                  num_instances, num_replace,
                                                  short_id.generate_id)

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(),
            item_to_remove=self.resource_info)

        return template.make_template(definitions,
                                      version=template_version,
                                      child_env=child_env)
Example #13
0
    def _parse_nested_stack(self, stack_name, child_template,
                            child_params, timeout_mins=None,
                            adopt_data=None):
        if timeout_mins is None:
            timeout_mins = self.stack.timeout_mins

        stack_user_project_id = self.stack.stack_user_project_id
        new_nested_depth = self._child_nested_depth()

        child_env = environment.get_child_environment(
            self.stack.env, child_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)
        self._validate_nested_resources(parsed_template)

        # Note we disable rollback for nested stacks, since they
        # should be rolled back by the parent stack on failure
        nested = parser.Stack(self.context,
                              stack_name,
                              parsed_template,
                              timeout_mins=timeout_mins,
                              disable_rollback=True,
                              parent_resource=self.name,
                              owner_id=self.stack.id,
                              user_creds_id=self.stack.user_creds_id,
                              stack_user_project_id=stack_user_project_id,
                              adopt_stack_data=adopt_data,
                              nested_depth=new_nested_depth)
        nested.set_parent_stack(self.stack)
        return nested
Example #14
0
 def test_drill_down_matching_wildcard(self):
     env = {
         u'resource_registry': {
             u'resources': {
                 u'nested': {
                     u'c': {
                         u'OS::Fruit': u'carrots.yaml',
                         u'hooks': 'pre-create',
                     },
                 },
                 u'nest*': {
                     u'nested_res': {
                         u'hooks': 'pre-create',
                     },
                 }
             }
         }
     }
     penv = environment.Environment(env)
     cenv = environment.get_child_environment(
         penv, None, child_resource_name=u'nested')
     registry = cenv.user_env_as_dict()['resource_registry']
     resources = registry['resources']
     self.assertIn('c', resources)
     self.assertIn('nested_res', resources)
     res = cenv.get_resource_info('OS::Fruit', resource_name='c')
     self.assertIsNotNone(res)
     self.assertEqual(u'carrots.yaml', res.value)
Example #15
0
    def _stack_kwargs(self, user_params, child_template, adopt_data=None):

        if user_params is None:
            user_params = self.child_params()
        if child_template is None:
            child_template = self.child_template()
        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)
        if adopt_data is None:
            template_id = parsed_template.store(self.context)
            return {
                'template_id': template_id,
                'template': None,
                'params': None,
                'files': None,
            }
        else:
            return {
                'template': parsed_template.t,
                'params': child_env.user_env_as_dict(),
                'files': parsed_template.files,
            }
Example #16
0
 def test_drill_down_prefer_exact_match(self):
     env = {
         u'resource_registry': {
             u'resources': {
                 u'*esource': {
                     u'hooks': 'pre-create',
                 },
                 u'res*': {
                     u'hooks': 'pre-create',
                 },
                 u'resource': {
                     u'OS::Fruit': u'carrots.yaml',
                     u'hooks': 'pre-update',
                 },
                 u'resource*': {
                     u'hooks': 'pre-create',
                 },
                 u'*resource': {
                     u'hooks': 'pre-create',
                 },
                 u'*sour*': {
                     u'hooks': 'pre-create',
                 },
             }
         }
     }
     penv = environment.Environment(env)
     cenv = environment.get_child_environment(
         penv, None, child_resource_name=u'resource')
     registry = cenv.user_env_as_dict()['resource_registry']
     resources = registry['resources']
     self.assertEqual(u'carrots.yaml', resources[u'OS::Fruit'])
     self.assertEqual('pre-update', resources[u'hooks'])
Example #17
0
    def test_update(self):
        stacks = [get_stack(stack_status='UPDATE_IN_PROGRESS'),
                  get_stack(stack_status='UPDATE_COMPLETE')]

        rsrc = self.create_remote_stack()

        props = copy.deepcopy(rsrc.parsed_template()['Properties'])
        props['parameters']['name'] = 'bar'
        update_snippet = rsrc_defn.ResourceDefinition(rsrc.name,
                                                      rsrc.type(),
                                                      props)

        self.heat.stacks.get = mock.MagicMock(side_effect=stacks)
        scheduler.TaskRunner(rsrc.update, update_snippet)()

        self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
        self.assertEqual('bar', rsrc.properties.get('parameters')['name'])
        env = environment.get_child_environment(rsrc.stack.env,
                                                {'name': 'bar'})
        fields = {
            'stack_id': rsrc.resource_id,
            'template': template_format.parse(remote_template),
            'timeout_mins': 60,
            'disable_rollback': True,
            'parameters': {'name': 'bar'},
            'files': self.files,
            'environment': env.user_env_as_dict(),
        }
        self.heat.stacks.update.assert_called_with(**fields)
        self.assertEqual(2, len(self.heat.stacks.get.call_args_list))
Example #18
0
 def test_item_to_remove_complex(self):
     env = {
         u'resource_registry': {
             u'OS::Food': u'fruity.yaml',
             u'resources': {
                 u'abc': {
                     u'OS::Food': u'nutty.yaml'
                 }
             }
         }
     }
     penv = environment.Environment(env)
     # the victim we want is the most specific one.
     victim = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertEqual(['resources', 'abc', 'OS::Food'], victim.path)
     cenv = environment.get_child_environment(penv,
                                              None,
                                              item_to_remove=victim)
     res = cenv.get_resource_info('OS::Food', resource_name='abc')
     self.assertEqual(['OS::Food'], res.path)
     rr = cenv.user_env_as_dict()['resource_registry']
     self.assertIn('OS::Food', rr)
     self.assertNotIn('OS::Food', rr['resources']['abc'])
     # make sure the parent env is uneffected
     innocent2 = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertEqual(['resources', 'abc', 'OS::Food'], innocent2.path)
Example #19
0
 def test_registry_merge_favor_child(self):
     env1 = {u'resource_registry': {u'OS::Food': u'carrots.yaml'}}
     env2 = {u'resource_registry': {u'OS::Food': u'apples.yaml'}}
     penv = environment.Environment(env=env1)
     cenv = environment.get_child_environment(penv, env2)
     res = cenv.get_resource_info('OS::Food')
     self.assertEqual('apples.yaml', res.value)
Example #20
0
    def update_with_template(self,
                             child_template,
                             user_params=None,
                             timeout_mins=None):
        """Update the nested stack with the new template."""
        if self.id is None:
            self._store()

        nested_stack = self.nested()
        if nested_stack is None:
            # if the create failed for some reason and the nested
            # stack was not created, we need to create an empty stack
            # here so that the update will work.
            def _check_for_completion(creator_fn):
                while not self.check_create_complete(creator_fn):
                    yield

            empty_temp = template_format.parse(
                "heat_template_version: '2013-05-23'")
            stack_creator = self.create_with_template(empty_temp, {})
            checker = scheduler.TaskRunner(_check_for_completion,
                                           stack_creator)
            checker(timeout=self.stack.timeout_secs())

            if stack_creator is not None:
                stack_creator.run_to_completion()
            nested_stack = self.nested()

        if timeout_mins is None:
            timeout_mins = self.stack.timeout_mins

        if user_params is None:
            user_params = self.child_params()

        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)
        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)

        cookie = {
            'previous': {
                'updated_at': nested_stack.updated_time,
                'state': nested_stack.state
            }
        }

        args = {rpc_api.PARAM_TIMEOUT: timeout_mins}
        try:
            self.rpc_client().update_stack(self.context,
                                           nested_stack.identifier(),
                                           parsed_template.t,
                                           child_env.user_env_as_dict(),
                                           parsed_template.files, args)
        except Exception as ex:
            LOG.exception(_LE('update_stack'))
            self.raise_local_exception(ex)
        return cookie
Example #21
0
 def test_params_normal(self):
     new_params = {"parameters": {"foo": "bar", "tester": "Yes"}}
     penv = environment.Environment()
     expected = {"parameter_defaults": {}, "encrypted_param_names": [], "resource_registry": {"resources": {}}}
     expected.update(new_params)
     cenv = environment.get_child_environment(penv, new_params)
     self.assertEqual(expected, cenv.user_env_as_dict())
Example #22
0
    def test_update(self):
        stacks = [
            get_stack(stack_status='UPDATE_IN_PROGRESS'),
            get_stack(stack_status='UPDATE_COMPLETE')
        ]

        rsrc = self.create_remote_stack()

        props = dict(rsrc.properties)
        props['parameters']['name'] = 'bar'
        update_snippet = rsrc_defn.ResourceDefinition(rsrc.name, rsrc.type(),
                                                      props)

        self.heat.stacks.get = mock.MagicMock(side_effect=stacks)
        scheduler.TaskRunner(rsrc.update, update_snippet)()

        self.assertEqual((rsrc.UPDATE, rsrc.COMPLETE), rsrc.state)
        self.assertEqual('bar', rsrc.properties.get('parameters')['name'])
        env = environment.get_child_environment(rsrc.stack.env,
                                                {'name': 'bar'})
        fields = {
            'stack_id': rsrc.resource_id,
            'template': template_format.parse(remote_template),
            'timeout_mins': 60,
            'disable_rollback': True,
            'parameters': {
                'name': 'bar'
            },
            'files': self.files,
            'environment': env.user_env_as_dict(),
        }
        self.heat.stacks.update.assert_called_with(**fields)
        self.assertEqual(2, len(self.heat.stacks.get.call_args_list))
Example #23
0
    def _parse_nested_stack(self, stack_name, child_template,
                            child_params, timeout_mins=None,
                            adopt_data=None):
        if timeout_mins is None:
            timeout_mins = self.stack.timeout_mins

        stack_user_project_id = self.stack.stack_user_project_id
        new_nested_depth = self._child_nested_depth()

        child_env = environment.get_child_environment(
            self.stack.env, child_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)

        # Note we disable rollback for nested stacks, since they
        # should be rolled back by the parent stack on failure
        nested = parser.Stack(self.context,
                              stack_name,
                              parsed_template,
                              timeout_mins=timeout_mins,
                              disable_rollback=True,
                              parent_resource=self.name,
                              owner_id=self.stack.id,
                              user_creds_id=self.stack.user_creds_id,
                              stack_user_project_id=stack_user_project_id,
                              adopt_stack_data=adopt_data,
                              nested_depth=new_nested_depth)
        nested.set_parent_stack(self.stack)
        return nested
Example #24
0
 def test_registry_merge_favor_child(self):
     env1 = {u"resource_registry": {u"OS::Food": u"carrots.yaml"}}
     env2 = {u"resource_registry": {u"OS::Food": u"apples.yaml"}}
     penv = environment.Environment(env=env1)
     cenv = environment.get_child_environment(penv, env2)
     res = cenv.get_resource_info("OS::Food")
     self.assertEqual("apples.yaml", res.value)
Example #25
0
 def test_item_to_remove_none(self):
     env = {u"resource_registry": {u"OS::Food": u"fruity.yaml"}}
     penv = environment.Environment(env)
     victim = penv.get_resource_info("OS::Food", resource_name="abc")
     self.assertIsNotNone(victim)
     cenv = environment.get_child_environment(penv, None)
     res = cenv.get_resource_info("OS::Food", resource_name="abc")
     self.assertIsNotNone(res)
Example #26
0
 def test_item_to_remove_none(self):
     env = {u'resource_registry': {u'OS::Food': u'fruity.yaml'}}
     penv = environment.Environment(env)
     victim = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(victim)
     cenv = environment.get_child_environment(penv, None)
     res = cenv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(res)
Example #27
0
 def test_registry_merge_simple(self):
     env1 = {u'resource_registry': {u'OS::Food': u'fruity.yaml'}}
     env2 = {u'resource_registry': {u'OS::Fruit': u'apples.yaml'}}
     penv = environment.Environment(env=env1)
     cenv = environment.get_child_environment(penv, env2)
     rr = cenv.user_env_as_dict()['resource_registry']
     self.assertIn('OS::Food', rr)
     self.assertIn('OS::Fruit', rr)
Example #28
0
 def test_item_to_remove_none(self):
     env = {u'resource_registry': {u'OS::Food': u'fruity.yaml'}}
     penv = environment.Environment(env)
     victim = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(victim)
     cenv = environment.get_child_environment(penv, None)
     res = cenv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(res)
Example #29
0
 def test_params_normal(self):
     new_params = {'parameters': {'foo': 'bar', 'tester': 'Yes'}}
     penv = environment.Environment()
     expected = {'parameter_defaults': {},
                 'resource_registry': {'resources': {}}}
     expected.update(new_params)
     cenv = environment.get_child_environment(penv, new_params)
     self.assertEqual(expected, cenv.user_env_as_dict())
Example #30
0
 def test_registry_merge_simple(self):
     env1 = {u"resource_registry": {u"OS::Food": u"fruity.yaml"}}
     env2 = {u"resource_registry": {u"OS::Fruit": u"apples.yaml"}}
     penv = environment.Environment(env=env1)
     cenv = environment.get_child_environment(penv, env2)
     rr = cenv.user_env_as_dict()["resource_registry"]
     self.assertIn("OS::Food", rr)
     self.assertIn("OS::Fruit", rr)
Example #31
0
 def test_registry_merge_simple(self):
     env1 = {u'resource_registry': {u'OS::Food': u'fruity.yaml'}}
     env2 = {u'resource_registry': {u'OS::Fruit': u'apples.yaml'}}
     penv = environment.Environment(env=env1)
     cenv = environment.get_child_environment(penv, env2)
     rr = cenv.user_env_as_dict()['resource_registry']
     self.assertIn('OS::Food', rr)
     self.assertIn('OS::Fruit', rr)
Example #32
0
 def test_params_flat(self):
     new_params = {'foo': 'bar', 'tester': 'Yes'}
     penv = environment.Environment()
     expected = {'parameters': new_params,
                 'encrypted_param_names': [],
                 'parameter_defaults': {},
                 'resource_registry': {'resources': {}}}
     cenv = environment.get_child_environment(penv, new_params)
     self.assertEqual(expected, cenv.user_env_as_dict())
Example #33
0
 def test_params_normal(self):
     new_params = {'parameters': {'foo': 'bar', 'tester': 'Yes'}}
     penv = environment.Environment()
     expected = {'parameter_defaults': {},
                 'encrypted_param_names': [],
                 'resource_registry': {'resources': {}}}
     expected.update(new_params)
     cenv = environment.get_child_environment(penv, new_params)
     self.assertEqual(expected, cenv.user_env_as_dict())
Example #34
0
    def update_with_template(self, child_template, user_params=None,
                             timeout_mins=None):
        """Update the nested stack with the new template."""
        if self.id is None:
            self._store()

        nested_stack = self.nested()
        if nested_stack is None:
            # if the create failed for some reason and the nested
            # stack was not created, we need to create an empty stack
            # here so that the update will work.
            def _check_for_completion(creator_fn):
                while not self.check_create_complete(creator_fn):
                    yield

            empty_temp = template_format.parse(
                "heat_template_version: '2013-05-23'")
            stack_creator = self.create_with_template(empty_temp, {})
            checker = scheduler.TaskRunner(_check_for_completion,
                                           stack_creator)
            checker(timeout=self.stack.timeout_secs())

            if stack_creator is not None:
                stack_creator.run_to_completion()
            nested_stack = self.nested()

        if timeout_mins is None:
            timeout_mins = self.stack.timeout_mins

        if user_params is None:
            user_params = self.child_params()

        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)
        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)

        cookie = {'previous': {
            'updated_at': nested_stack.updated_time,
            'state': nested_stack.state}}

        args = {rpc_api.PARAM_TIMEOUT: timeout_mins}
        try:
            self.rpc_client().update_stack(
                self.context,
                nested_stack.identifier(),
                parsed_template.t,
                child_env.user_env_as_dict(),
                parsed_template.files,
                args)
        except Exception as ex:
            LOG.exception(_LE('update_stack'))
            self.raise_local_exception(ex)
        return cookie
Example #35
0
    def create_with_template(self,
                             child_template,
                             user_params=None,
                             timeout_mins=None,
                             adopt_data=None):
        """Create the nested stack with the given template."""
        name = self.physical_resource_name()
        if timeout_mins is None:
            timeout_mins = self.stack.timeout_mins
        stack_user_project_id = self.stack.stack_user_project_id

        if user_params is None:
            user_params = self.child_params()
        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        new_nested_depth = self._child_nested_depth()
        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)

        adopt_data_str = None
        if adopt_data is not None:
            if 'environment' not in adopt_data:
                adopt_data['environment'] = child_env.user_env_as_dict()
            if 'template' not in adopt_data:
                if isinstance(child_template, template.Template):
                    adopt_data['template'] = child_template.t
                else:
                    adopt_data['template'] = child_template
            adopt_data_str = json.dumps(adopt_data)

        args = {
            rpc_api.PARAM_TIMEOUT: timeout_mins,
            rpc_api.PARAM_DISABLE_ROLLBACK: True,
            rpc_api.PARAM_ADOPT_STACK_DATA: adopt_data_str
        }
        try:
            result = self.rpc_client()._create_stack(
                self.context,
                name,
                parsed_template.t,
                child_env.user_env_as_dict(),
                parsed_template.files,
                args,
                owner_id=self.stack.id,
                user_creds_id=self.stack.user_creds_id,
                stack_user_project_id=stack_user_project_id,
                nested_depth=new_nested_depth,
                parent_resource_name=self.name)
        except Exception as ex:
            self.raise_local_exception(ex)

        self.resource_id_set(result['stack_id'])
Example #36
0
 def test_params_flat(self):
     new_params = {'foo': 'bar', 'tester': 'Yes'}
     penv = environment.Environment()
     expected = {'parameters': new_params,
                 'encrypted_param_names': [],
                 'parameter_defaults': {},
                 'event_sinks': [],
                 'resource_registry': {'resources': {}}}
     cenv = environment.get_child_environment(penv, new_params)
     self.assertEqual(expected, cenv.env_as_dict())
Example #37
0
 def test_params_parent_overwritten(self):
     new_params = {'parameters': {'foo': 'bar', 'tester': 'Yes'}}
     parent_params = {'parameters': {'gone': 'hopefully'}}
     penv = environment.Environment(env=parent_params)
     expected = {'parameter_defaults': {},
                 'encrypted_param_names': [],
                 'resource_registry': {'resources': {}}}
     expected.update(new_params)
     cenv = environment.get_child_environment(penv, new_params)
     self.assertEqual(expected, cenv.user_env_as_dict())
Example #38
0
 def test_params_parent_overwritten(self):
     new_params = {'parameters': {'foo': 'bar', 'tester': 'Yes'}}
     parent_params = {'parameters': {'gone': 'hopefully'}}
     penv = environment.Environment(env=parent_params)
     expected = {'parameter_defaults': {},
                 'encrypted_param_names': [],
                 'event_sinks': [],
                 'resource_registry': {'resources': {}}}
     expected.update(new_params)
     cenv = environment.get_child_environment(penv, new_params)
     self.assertEqual(expected, cenv.env_as_dict())
Example #39
0
 def test_item_to_remove_simple(self):
     env = {u"resource_registry": {u"OS::Food": u"fruity.yaml"}}
     penv = environment.Environment(env)
     victim = penv.get_resource_info("OS::Food", resource_name="abc")
     self.assertIsNotNone(victim)
     cenv = environment.get_child_environment(penv, None, item_to_remove=victim)
     self.assertRaises(exception.EntityNotFound, cenv.get_resource_info, "OS::Food", resource_name="abc")
     self.assertNotIn("OS::Food", cenv.user_env_as_dict()["resource_registry"])
     # make sure the parent env is unaffected
     innocent = penv.get_resource_info("OS::Food", resource_name="abc")
     self.assertIsNotNone(innocent)
    def create_with_template(self, child_template, user_params=None,
                             timeout_mins=None, adopt_data=None):
        """Create the nested stack with the given template."""
        name = self.physical_resource_name()
        if timeout_mins is None:
            timeout_mins = self.stack.timeout_mins
        stack_user_project_id = self.stack.stack_user_project_id

        if user_params is None:
            user_params = self.child_params()
        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        new_nested_depth = self._child_nested_depth()
        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)

        adopt_data_str = None
        if adopt_data is not None:
            if 'environment' not in adopt_data:
                adopt_data['environment'] = child_env.user_env_as_dict()
            if 'template' not in adopt_data:
                if isinstance(child_template, template.Template):
                    adopt_data['template'] = child_template.t
                else:
                    adopt_data['template'] = child_template
            adopt_data_str = json.dumps(adopt_data)

        args = {rpc_api.PARAM_TIMEOUT: timeout_mins,
                rpc_api.PARAM_DISABLE_ROLLBACK: True,
                rpc_api.PARAM_ADOPT_STACK_DATA: adopt_data_str}
        try:
            result = self.rpc_client()._create_stack(
                self.context,
                name,
                parsed_template.t,
                child_env.user_env_as_dict(),
                parsed_template.files,
                args,
                owner_id=self.stack.id,
                user_creds_id=self.stack.user_creds_id,
                stack_user_project_id=stack_user_project_id,
                nested_depth=new_nested_depth,
                parent_resource_name=self.name)
        except Exception as ex:
            self.raise_local_exception(ex)

        self.resource_id_set(result['stack_id'])
Example #41
0
 def test_item_to_remove_simple(self):
     env = {u'resource_registry': {u'OS::Food': u'fruity.yaml'}}
     penv = environment.Environment(env)
     victim = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(victim)
     cenv = environment.get_child_environment(penv, None,
                                              item_to_remove=victim)
     res = cenv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNone(res)
     self.assertNotIn('OS::Food',
                      cenv.user_env_as_dict()['resource_registry'])
     # make sure the parent env is uneffected
     innocent = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(innocent)
Example #42
0
 def test_item_to_remove_simple(self):
     env = {u'resource_registry': {u'OS::Food': u'fruity.yaml'}}
     penv = environment.Environment(env)
     victim = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(victim)
     cenv = environment.get_child_environment(penv, None,
                                              item_to_remove=victim)
     res = cenv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNone(res)
     self.assertNotIn('OS::Food',
                      cenv.user_env_as_dict()['resource_registry'])
     # make sure the parent env is uneffected
     innocent = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertIsNotNone(innocent)
Example #43
0
 def handle_create(self):
     params = self.properties[self.PARAMETERS]
     env = environment.get_child_environment(self.stack.env, params)
     tmpl = template_format.parse(self.properties[self.TEMPLATE])
     args = {
         'stack_name': self.physical_resource_name_or_FnGetRefId(),
         'template': tmpl,
         'timeout_mins': self.properties[self.TIMEOUT],
         'disable_rollback': True,
         'parameters': params,
         'files': self.stack.t.files,
         'environment': env.user_env_as_dict(),
     }
     remote_stack_id = self.heat().stacks.create(**args)['stack']['id']
     self.resource_id_set(remote_stack_id)
Example #44
0
    def _parse_nested_stack(self,
                            stack_name,
                            child_template,
                            child_params=None,
                            timeout_mins=None,
                            adopt_data=None):
        if self.stack.nested_depth >= cfg.CONF.max_nested_stack_depth:
            msg = _("Recursion depth exceeds %d."
                    ) % cfg.CONF.max_nested_stack_depth
            raise exception.RequestLimitExceeded(message=msg)

        parsed_template = self._parse_child_template(child_template)
        self._validate_nested_resources(parsed_template)

        # Don't overwrite the attributes_schema for subclasses that
        # define their own attributes_schema.
        if not hasattr(type(self), 'attributes_schema'):
            self.attributes = None
            self._outputs_to_attribs(parsed_template)

        if timeout_mins is None:
            timeout_mins = self.stack.timeout_mins

        stack_user_project_id = self.stack.stack_user_project_id
        new_nested_depth = self.stack.nested_depth + 1

        if child_params is None:
            child_params = self.child_params()
        child_env = environment.get_child_environment(self.stack.env,
                                                      child_params)

        # Note we disable rollback for nested stacks, since they
        # should be rolled back by the parent stack on failure
        nested = parser.Stack(self.context,
                              stack_name,
                              parsed_template,
                              env=child_env,
                              timeout_mins=timeout_mins,
                              disable_rollback=True,
                              parent_resource=self,
                              owner_id=self.stack.id,
                              user_creds_id=self.stack.user_creds_id,
                              stack_user_project_id=stack_user_project_id,
                              adopt_stack_data=adopt_data,
                              nested_depth=new_nested_depth)
        return nested
Example #45
0
 def test_item_to_remove_complex(self):
     env = {
         u"resource_registry": {u"OS::Food": u"fruity.yaml", u"resources": {u"abc": {u"OS::Food": u"nutty.yaml"}}}
     }
     penv = environment.Environment(env)
     # the victim we want is the most specific one.
     victim = penv.get_resource_info("OS::Food", resource_name="abc")
     self.assertEqual(["resources", "abc", "OS::Food"], victim.path)
     cenv = environment.get_child_environment(penv, None, item_to_remove=victim)
     res = cenv.get_resource_info("OS::Food", resource_name="abc")
     self.assertEqual(["OS::Food"], res.path)
     rr = cenv.user_env_as_dict()["resource_registry"]
     self.assertIn("OS::Food", rr)
     self.assertNotIn("OS::Food", rr["resources"]["abc"])
     # make sure the parent env is uneffected
     innocent2 = penv.get_resource_info("OS::Food", resource_name="abc")
     self.assertEqual(["resources", "abc", "OS::Food"], innocent2.path)
Example #46
0
 def test_drill_down_matching_wildcard(self):
     env = {
         u"resource_registry": {
             u"resources": {
                 u"nested": {u"c": {u"OS::Fruit": u"carrots.yaml", u"hooks": "pre-create"}},
                 u"nest*": {u"nested_res": {u"hooks": "pre-create"}},
             }
         }
     }
     penv = environment.Environment(env)
     cenv = environment.get_child_environment(penv, None, child_resource_name=u"nested")
     registry = cenv.user_env_as_dict()["resource_registry"]
     resources = registry["resources"]
     self.assertIn("c", resources)
     self.assertIn("nested_res", resources)
     res = cenv.get_resource_info("OS::Fruit", resource_name="c")
     self.assertIsNotNone(res)
     self.assertEqual(u"carrots.yaml", res.value)
Example #47
0
    def _create_template(
        self, num_instances, num_replace=0, template_version=("HeatTemplateFormatVersion", "2012-12-12")
    ):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self, include_failed=True)
        definitions = template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace, short_id.generate_id
        )

        child_env = environment.get_child_environment(
            self.stack.env, self.child_params(), item_to_remove=self.resource_info
        )

        return template.make_template(definitions, version=template_version, child_env=child_env)
Example #48
0
 def test_item_to_remove_complex(self):
     env = {u'resource_registry': {u'OS::Food': u'fruity.yaml',
                                   u'resources': {u'abc': {
                                       u'OS::Food': u'nutty.yaml'}}}}
     penv = environment.Environment(env)
     # the victim we want is the most specific one.
     victim = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertEqual(['resources', 'abc', 'OS::Food'], victim.path)
     cenv = environment.get_child_environment(penv, None,
                                              item_to_remove=victim)
     res = cenv.get_resource_info('OS::Food', resource_name='abc')
     self.assertEqual(['OS::Food'], res.path)
     rr = cenv.user_env_as_dict()['resource_registry']
     self.assertIn('OS::Food', rr)
     self.assertNotIn('OS::Food', rr['resources']['abc'])
     # make sure the parent env is uneffected
     innocent2 = penv.get_resource_info('OS::Food', resource_name='abc')
     self.assertEqual(['resources', 'abc', 'OS::Food'], innocent2.path)
Example #49
0
    def test_create(self):
        rsrc = self.create_remote_stack()

        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
        self.assertEqual('c8a19429-7fde-47ea-a42f-40045488226c',
                         rsrc.resource_id)
        env = environment.get_child_environment(rsrc.stack.env,
                                                {'name': 'foo'})
        args = {
            'stack_name': rsrc.physical_resource_name(),
            'template': template_format.parse(remote_template),
            'timeout_mins': 60,
            'disable_rollback': True,
            'parameters': {'name': 'foo'},
            'files': self.files,
            'environment': env.user_env_as_dict(),
        }
        self.heat.stacks.create.assert_called_with(**args)
        self.assertEqual(2, len(self.heat.stacks.get.call_args_list))
Example #50
0
    def _stack_kwargs(self, user_params, child_template):

        if user_params is None:
            user_params = self.child_params()
        if child_template is None:
            child_template = self.child_template()
        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)
        return {
            'template': parsed_template.t,
            'params': child_env.user_env_as_dict(),
            'files': parsed_template.files
        }
Example #51
0
    def test_create(self):
        rsrc = self.create_remote_stack()

        self.assertEqual((rsrc.CREATE, rsrc.COMPLETE), rsrc.state)
        self.assertEqual('c8a19429-7fde-47ea-a42f-40045488226c',
                         rsrc.resource_id)
        env = environment.get_child_environment(rsrc.stack.env,
                                                {'name': 'foo'})
        args = {
            'stack_name': rsrc.physical_resource_name(),
            'template': template_format.parse(remote_template),
            'timeout_mins': 60,
            'disable_rollback': True,
            'parameters': {'name': 'foo'},
            'files': self.files,
            'environment': env.user_env_as_dict(),
        }
        self.heat.stacks.create.assert_called_with(**args)
        self.assertEqual(2, len(self.heat.stacks.get.call_args_list))
Example #52
0
    def _create_template(self, num_instances, num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """
        Create a template to represent autoscaled instances.

        Also see heat.scaling.template.resource_templates.
        """
        instance_definition = self._get_instance_definition()
        old_resources = self._get_instance_templates()
        definitions = template.resource_templates(
            old_resources, instance_definition, num_instances, num_replace)

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(), item_to_remove=self.resource_info)

        return template.make_template(definitions, version=template_version,
                                      child_env=child_env)
    def _create_template(self, num_instances, num_replace=0,
                         template_version=('HeatTemplateFormatVersion',
                                           '2012-12-12')):
        """Create a template to represent autoscaled instances.

        Also see heat.scaling.template.member_definitions.
        """
        instance_definition = self._get_resource_definition()
        old_resources = grouputils.get_member_definitions(self,
                                                          include_failed=True)
        # WRS: Detect a scale down.  Issue a vote
        # If any vote is rejected, set new_resources to be same size as old
        existing = grouputils.get_members(self)
        if num_instances < len(existing):
            LOG.info("WRS downscale detected, vote initiated")
            for i in range(num_instances, len(existing)):
                if existing[i].wrs_vote() is False:
                    LOG.info("WRS downscale blocked by vote")
                    num_instances = len(existing)
                    break

        definitions = list(template.member_definitions(
            old_resources, instance_definition, num_instances, num_replace,
            short_id.generate_id, delete_oldest=False))

        child_env = environment.get_child_environment(
            self.stack.env,
            self.child_params(), item_to_remove=self.resource_info)

        tmpl = template.make_template(definitions, version=template_version,
                                      child_env=child_env)

        # Subclasses use HOT templates
        att_func = 'get_attr'
        if att_func not in tmpl.functions:
            att_func = 'Fn::GetAtt'
        get_attr = functools.partial(tmpl.functions[att_func], None, att_func)
        for odefn in self._nested_output_defns([k for k, d in definitions],
                                               get_attr):
            tmpl.add_output(odefn)

        return tmpl
Example #54
0
    def handle_update(self, json_snippet, tmpl_diff, prop_diff):
        if self.resource_id and prop_diff:
            snippet = json_snippet.get('Properties', {})
            self.properties = properties.Properties(self.properties_schema,
                                                    snippet, function.resolve,
                                                    self.name)

            params = self.properties[self.PARAMETERS]
            env = environment.get_child_environment(self.stack.env, params)
            tmpl = template_format.parse(self.properties[self.TEMPLATE])
            fields = {
                'stack_id': self.resource_id,
                'parameters': params,
                'template': tmpl,
                'timeout_mins': self.properties[self.TIMEOUT],
                'disable_rollback': self.stack.disable_rollback,
                'files': self.stack.t.files,
                'environment': env.user_env_as_dict(),
            }
            self.heat().stacks.update(**fields)
Example #55
0
    def handle_update(self, json_snippet, tmpl_diff, prop_diff):
        # Always issue an update to the remote stack and let the individual
        # resources in it decide if they need updating.
        if self.resource_id:
            self.properties = json_snippet.properties(self.properties_schema,
                                                      self.context)

            params = self.properties[self.PARAMETERS]
            env = environment.get_child_environment(self.stack.env, params)
            tmpl = template_format.parse(self.properties[self.TEMPLATE])
            fields = {
                'stack_id': self.resource_id,
                'parameters': params,
                'template': tmpl,
                'timeout_mins': self.properties[self.TIMEOUT],
                'disable_rollback': self.stack.disable_rollback,
                'files': self.stack.t.files,
                'environment': env.user_env_as_dict(),
            }
            self.heat().stacks.update(**fields)
Example #56
0
    def child_definition(self, child_template=None, user_params=None,
                         nested_identifier=None):
        if user_params is None:
            user_params = self.child_params()
        if child_template is None:
            child_template = self.child_template()
        if nested_identifier is None:
            nested_identifier = self.nested_identifier()

        child_env = environment.get_child_environment(
            self.stack.env,
            user_params,
            child_resource_name=self.name,
            item_to_remove=self.resource_info)

        parsed_template = self._child_parsed_template(child_template,
                                                      child_env)
        return stk_defn.StackDefinition(self.context, parsed_template,
                                        nested_identifier,
                                        None)
Example #57
0
    def validate(self):
        super(RemoteStack, self).validate()

        try:
            with TempCACertFile(self.cacert) as cacert_path:
                self.heat(cacert_path)
        except Exception as ex:
            if self._credential:
                location = "remote cloud"
            else:
                location = 'region "%s"' % self._region_name
            exc_info = dict(location=location, exc=six.text_type(ex))
            msg = _('Cannot establish connection to Heat endpoint at '
                    '%(location)s due to "%(exc)s"') % exc_info
            raise exception.StackValidationFailed(message=msg)

        try:
            params = self.properties[self.PARAMETERS]
            env = environment.get_child_environment(self.stack.env, params)
            tmpl = template_format.parse(self.properties[self.TEMPLATE])
            args = {
                'template': tmpl,
                'files': self.stack.t.files,
                'environment': env.user_env_as_dict(),
            }
            with TempCACertFile(self.cacert) as cacert_path:
                self.heat(cacert_path).stacks.validate(**args)
        except Exception as ex:
            if self._credential:
                location = "remote cloud"
            else:
                location = 'region "%s"' % self._region_name
            exc_info = dict(location=location, exc=six.text_type(ex))
            msg = _('Failed validating stack template using Heat endpoint at '
                    '%(location)s due to "%(exc)s"') % exc_info
            raise exception.StackValidationFailed(message=msg)