Ejemplo n.º 1
0
    def result(self):
        template = function.resolve(self._string)
        mapping = function.resolve(self._mapping)

        if not isinstance(template, six.string_types):
            raise TypeError(_('"%s" template must be a string') % self.fn_name)

        if not isinstance(mapping, collections.Mapping):
            raise TypeError(_('"%s" params must be a map') % self.fn_name)

        def replace(string, change):
            placeholder, value = change

            if not isinstance(placeholder, six.string_types):
                raise TypeError(
                    _('"%s" param placeholders must be strings') %
                    self.fn_name)

            if value is None:
                value = ''

            if not isinstance(
                    value, (six.string_types, six.integer_types, float, bool)):
                raise TypeError(
                    _('"%s" params must be strings or numbers') % self.fn_name)

            return string.replace(placeholder, six.text_type(value))

        mapping = collections.OrderedDict(
            sorted(mapping.items(), key=lambda t: len(t[0]), reverse=True))
        return six.moves.reduce(replace, six.iteritems(mapping), template)
Ejemplo n.º 2
0
    def result(self):
        attr = function.resolve(self.args)

        if attr == self.METADATA:
            return self.stack.parent_resource.metadata_get()
        elif attr == self.UPDATE_POLICY:
            up = self.stack.parent_resource.t.get('UpdatePolicy', {})
            return function.resolve(up)
        elif attr == self.DELETION_POLICY:
            dp = self.stack.parent_resource.t.deletion_policy()
            return function.resolve(dp)
Ejemplo n.º 3
0
    def result(self):
        path_components = function.resolve(self._path_components)
        attribute = function.resolve(self._attribute)

        r = self._resource()
        if (r.status in (r.IN_PROGRESS, r.COMPLETE) and
                r.action in (r.CREATE, r.ADOPT, r.SUSPEND, r.RESUME,
                             r.UPDATE, r.CHECK, r.SNAPSHOT)):
            return r.FnGetAtt(attribute, *path_components)
        else:
            return None
Ejemplo n.º 4
0
    def result(self):
        for_each = function.resolve(self._for_each)
        if not all(self._valid_list(l) for l in for_each.values()):
            raise TypeError(_('The values of the "for_each" argument to '
                              '"%s" must be lists') % self.fn_name)

        template = function.resolve(self._template)

        keys, lists = six.moves.zip(*for_each.items())
        return [self._do_replacement(keys, replacements, template)
                for replacements in itertools.product(*lists)]
Ejemplo n.º 5
0
 def dep_attrs(self, resource_name):
     if self._resource().name == resource_name:
         path = function.resolve(self._path_components)
         attr = [function.resolve(self._attribute)]
         if path:
             attrs = [tuple(attr + path)]
         else:
             attrs = attr
     else:
         attrs = []
     return itertools.chain(function.dep_attrs(self.args, resource_name),
                            attrs)
Ejemplo n.º 6
0
        def rsrc_defn_item(name, snippet):
            data = self.parse(stack, snippet)

            depends = data.get(RES_DEPENDS_ON)
            if isinstance(depends, six.string_types):
                depends = [depends]

            deletion_policy = function.resolve(data.get(RES_DELETION_POLICY))
            if deletion_policy is not None:
                if deletion_policy not in six.iterkeys(self.deletion_policies):
                    msg = _('Invalid deletion policy "%s"') % deletion_policy
                    raise exception.StackValidationFailed(message=msg)
                else:
                    deletion_policy = self.deletion_policies[deletion_policy]

            kwargs = {
                'resource_type': data.get(RES_TYPE),
                'properties': data.get(RES_PROPERTIES),
                'metadata': data.get(RES_METADATA),
                'depends': depends,
                'deletion_policy': deletion_policy,
                'update_policy': data.get(RES_UPDATE_POLICY),
                'description': data.get(RES_DESCRIPTION) or ''
            }

            defn = rsrc_defn.ResourceDefinition(name, **kwargs)
            return name, defn
Ejemplo n.º 7
0
    def result(self):
        attribute = super(GetAttThenSelect, self).result()
        if attribute is None:
            return None

        path_components = function.resolve(self._path_components)
        return attributes.select_from_attribute(attribute, path_components)
Ejemplo n.º 8
0
    def result(self):
        args = function.resolve(self.args)

        try:
            delim = args.pop(0)
            str_to_split = args.pop(0)
        except (AttributeError, IndexError):
            raise ValueError(_('Incorrect arguments to "%(fn_name)s" '
                               'should be: %(example)s') % self.fmt_data)

        if str_to_split is None:
            return None

        split_list = str_to_split.split(delim)

        # Optionally allow an index to be specified
        if args:
            try:
                index = int(args.pop(0))
            except ValueError:
                raise ValueError(_('Incorrect index to "%(fn_name)s" '
                                   'should be: %(example)s') % self.fmt_data)
            else:
                try:
                    res = split_list[index]
                except IndexError:
                    raise ValueError(_('Incorrect index to "%(fn_name)s" '
                                       'should be between 0 and '
                                       '%(max_index)s')
                                     % {'fn_name': self.fn_name,
                                        'max_index': len(split_list) - 1})
        else:
            res = split_list
        return res
Ejemplo n.º 9
0
        def rsrc_defn_item(name, snippet):
            data = self.parse(stack, snippet)

            depends = data.get(RES_DEPENDS_ON)
            if isinstance(depends, six.string_types):
                depends = [depends]

            deletion_policy = function.resolve(data.get(RES_DELETION_POLICY))
            if deletion_policy is not None:
                if deletion_policy not in six.iterkeys(
                        self.deletion_policies):
                    msg = _('Invalid deletion policy "%s"') % deletion_policy
                    raise exception.StackValidationFailed(message=msg)
                else:
                    deletion_policy = self.deletion_policies[deletion_policy]

            kwargs = {
                'resource_type': data.get(RES_TYPE),
                'properties': data.get(RES_PROPERTIES),
                'metadata': data.get(RES_METADATA),
                'depends': depends,
                'deletion_policy': deletion_policy,
                'update_policy': data.get(RES_UPDATE_POLICY),
                'description': data.get(RES_DESCRIPTION) or ''
            }

            defn = rsrc_defn.ResourceDefinition(name, **kwargs)
            return name, defn
Ejemplo n.º 10
0
 def dep_attrs(self, resource_name):
     if self._resource().name == resource_name:
         attrs = [function.resolve(self._attribute)]
     else:
         attrs = []
     return itertools.chain(
         super(GetAtt, self).dep_attrs(resource_name), attrs)
Ejemplo n.º 11
0
    def result(self):
        param_name = function.resolve(self.args)

        try:
            return self.parameters[param_name]
        except KeyError:
            raise exception.InvalidTemplateReference(resource=param_name,
                                                     key='unknown')
Ejemplo n.º 12
0
    def _resource(self, path='unknown'):
        resource_name = function.resolve(self._resource_name)

        try:
            return self.stack[resource_name]
        except KeyError:
            raise exception.InvalidTemplateReference(resource=resource_name,
                                                     key=path)
Ejemplo n.º 13
0
    def result(self):
        index = function.resolve(self._lookup)

        strings = function.resolve(self._strings)

        if strings == '':
            # an empty string is a common response from other
            # functions when result is not currently available.
            # Handle by returning an empty string
            return ''

        if isinstance(strings, six.string_types):
            # might be serialized json.
            try:
                strings = jsonutils.loads(strings)
            except ValueError as json_ex:
                fmt_data = {'fn_name': self.fn_name, 'err': json_ex}
                raise ValueError(_('"%(fn_name)s": %(err)s') % fmt_data)

        if isinstance(strings, collections.Mapping):
            if not isinstance(index, six.string_types):
                raise TypeError(
                    _('Index to "%s" must be a string') % self.fn_name)
            return strings.get(index, '')

        try:
            index = int(index)
        except (ValueError, TypeError):
            pass

        if (isinstance(strings, collections.Sequence)
                and not isinstance(strings, six.string_types)):
            if not isinstance(index, six.integer_types):
                raise TypeError(
                    _('Index to "%s" must be an integer') % self.fn_name)

            try:
                return strings[index]
            except IndexError:
                return ''

        if strings is None:
            return ''

        raise TypeError(_('Arguments to %s not fully resolved') % self.fn_name)
Ejemplo n.º 14
0
    def result(self):
        template = function.resolve(self._string)
        mapping = function.resolve(self._mapping)

        if not isinstance(template, six.string_types):
            raise TypeError(_('"%s" template must be a string') % self.fn_name)

        if not isinstance(mapping, collections.Mapping):
            raise TypeError(_('"%s" params must be a map') % self.fn_name)

        def replace(string, change):
            placeholder, value = change

            if not isinstance(placeholder, six.string_types):
                raise TypeError(_('"%s" param placeholders must be strings') %
                                self.fn_name)

            if value is None:
                value = ''

            if not isinstance(value,
                              (six.string_types, six.integer_types,
                               float, bool)):
                if isinstance(value,
                              (collections.Mapping, collections.Sequence)):
                    try:
                        value = jsonutils.dumps(value, default=None)
                    except TypeError:
                        raise TypeError(_('"%(name)s" params must be strings, '
                                          'numbers, list or map. '
                                          'Failed to json serialize %(value)s'
                                          ) % {'name': self.fn_name,
                                               'value': value})
                else:
                    raise TypeError(_('"%s" params must be strings, numbers, '
                                      'list or map.') % self.fn_name)

            return string.replace(placeholder, six.text_type(value))

        mapping = collections.OrderedDict(sorted(mapping.items(),
                                                 key=lambda t: len(t[0]),
                                                 reverse=True))
        return six.moves.reduce(replace, six.iteritems(mapping), template)
Ejemplo n.º 15
0
        def arg_item(attr_name):
            name = attr_name.lstrip('_')
            if name in overrides:
                value = overrides[name]
                if not value and getattr(self, attr_name) is None:
                    value = None
            else:
                value = function.resolve(getattr(self, attr_name))

            return name, value
Ejemplo n.º 16
0
    def result(self):
        strings = function.resolve(self._strings)

        if not isinstance(self._delim, six.string_types):
            raise TypeError(
                _("Delimiter for %s must be string") % self.fn_name)
        if not isinstance(strings, six.string_types):
            raise TypeError(
                _("String to split must be string; got %s") % type(strings))

        return strings.split(self._delim)
Ejemplo n.º 17
0
 def resolve_and_find(translation_data, translation_value):
     if isinstance(translation_value, cfn_funcs.ResourceRef):
         return
     if isinstance(translation_value, function.Function):
         translation_value = function.resolve(translation_value)
     if translation_value:
         finder = getattr(self.client_plugin, self.finder)
         if self.entity:
             value = finder(self.entity, translation_value)
         else:
             value = finder(translation_value)
         translation_data[translation_key] = value
Ejemplo n.º 18
0
 def resolve_and_find(translation_data, translation_value):
     if isinstance(translation_value, cfn_funcs.ResourceRef):
         return
     if isinstance(translation_value, function.Function):
         translation_value = function.resolve(translation_value)
     if translation_value:
         finder = getattr(self.client_plugin, self.finder)
         if self.entity:
             value = finder(self.entity, translation_value)
         else:
             value = finder(translation_value)
         translation_data[translation_key] = value
Ejemplo n.º 19
0
    def _get_conf_properties(self):
        conf_refid = self.properties[self.LAUNCH_CONFIGURATION_NAME]
        conf = self.stack.resource_by_refid(conf_refid)
        props = function.resolve(conf.properties.data)
        if 'InstanceId' in props:
            props = conf.rebuild_lc_properties(props['InstanceId'])

        props['Tags'] = self._tags()
        # if the launch configuration is created from an existing instance.
        # delete the 'InstanceId' property
        props.pop('InstanceId', None)

        return conf, props
Ejemplo n.º 20
0
    def result(self):
        args = function.resolve(self.args)
        if not (isinstance(args, six.string_types)):
            raise TypeError(_('Argument to "%s" must be a string') %
                            self.fn_name)

        f = self.files.get(args)
        if f is None:
            fmt_data = {'fn_name': self.fn_name,
                        'file_key': args}
            raise ValueError(_('No content found in the "files" section for '
                               '%(fn_name)s path: %(file_key)s') % fmt_data)
        return f
Ejemplo n.º 21
0
    def _get_conf_properties(self):
        conf_refid = self.properties[self.LAUNCH_CONFIGURATION_NAME]
        conf = self.stack.resource_by_refid(conf_refid)
        props = function.resolve(conf.properties.data)
        if 'InstanceId' in props:
            props = conf.rebuild_lc_properties(props['InstanceId'])

        props['Tags'] = self._tags()
        # if the launch configuration is created from an existing instance.
        # delete the 'InstanceId' property
        props.pop('InstanceId', None)

        return conf, props
Ejemplo n.º 22
0
    def handle_restore(self, defn, restore_data):
        snapshot_id = restore_data['resource_data']['snapshot_id']
        snapshot = self.heat().stacks.snapshot_show(self.resource_id,
                                                    snapshot_id)
        s_data = snapshot['snapshot']['data']
        env = environment.Environment(s_data['environment'])
        files = s_data['files']
        tmpl = template.Template(s_data['template'], env=env, files=files)
        props = function.resolve(self.properties.data)
        props[self.TEMPLATE] = jsonutils.dumps(tmpl.t)
        props[self.PARAMETERS] = env.params

        return defn.freeze(properties=props)
Ejemplo n.º 23
0
    def handle_restore(self, defn, restore_data):
        snapshot_id = restore_data['resource_data']['snapshot_id']
        snapshot = self.heat().stacks.snapshot_show(self.resource_id,
                                                    snapshot_id)
        s_data = snapshot['snapshot']['data']
        env = environment.Environment(s_data['environment'])
        files = s_data['files']
        tmpl = template.Template(s_data['template'], env=env, files=files)
        props = function.resolve(self.properties.data)
        props[self.TEMPLATE] = jsonutils.dumps(tmpl.t)
        props[self.PARAMETERS] = env.params

        return defn.freeze(properties=props)
Ejemplo n.º 24
0
    def result(self):
        attribute = function.resolve(self._attribute)

        r = self._resource()
        if r.action in (r.CREATE, r.ADOPT, r.SUSPEND, r.RESUME, r.UPDATE,
                        r.ROLLBACK, r.SNAPSHOT, r.CHECK):
            return r.FnGetAtt(attribute)
        # NOTE(sirushtim): Add r.INIT to states above once convergence
        # is the default.
        elif r.stack.has_cache_data(r.name) and r.action == r.INIT:
            return r.FnGetAtt(attribute)
        else:
            return None
Ejemplo n.º 25
0
    def result(self):
        args = function.resolve(self.args)

        if not args:
            raise ValueError(_('Function "%s" must have arguments') %
                             self.fn_name)

        if isinstance(args, six.string_types):
            param_name = args
            path_components = []
        elif isinstance(args, collections.Sequence):
            param_name = args[0]
            path_components = args[1:]
        else:
            raise TypeError(_('Argument to "%s" must be string or list') %
                            self.fn_name)

        if not isinstance(param_name, six.string_types):
            raise TypeError(_('Parameter name in "%s" must be string') %
                            self.fn_name)

        try:
            parameter = self.parameters[param_name]
        except KeyError:
            raise exception.UserParameterMissing(key=param_name)

        def get_path_component(collection, key):
            if not isinstance(collection, (collections.Mapping,
                                           collections.Sequence)):
                raise TypeError(_('"%s" can\'t traverse path') % self.fn_name)

            if not isinstance(key, (six.string_types, int)):
                raise TypeError(_('Path components in "%s" '
                                  'must be strings') % self.fn_name)

            if isinstance(collection, collections.Sequence
                          ) and isinstance(key, six.string_types):
                try:
                    key = int(key)
                except ValueError:
                    raise TypeError(_("Path components in '%s' "
                                      "must be a string that can be "
                                      "parsed into an "
                                      "integer.") % self.fn_name)
            return collection[key]

        try:
            return six.moves.reduce(get_path_component, path_components,
                                    parameter)
        except (KeyError, IndexError, TypeError):
            return ''
Ejemplo n.º 26
0
    def result(self):
        strings = function.resolve(self._strings)
        if strings is None:
            strings = []
        if (isinstance(strings, six.string_types)
                or not isinstance(strings, collections.Sequence)):
            raise TypeError(_('"%s" must operate on a list') % self.fn_name)

        delim = function.resolve(self._delim)
        if not isinstance(delim, six.string_types):
            raise TypeError(
                _('"%s" delimiter must be a string') % self.fn_name)

        def ensure_string(s):
            if s is None:
                return ''
            if not isinstance(s, six.string_types):
                raise TypeError(
                    _('Items to join must be strings not %s') %
                    (repr(s)[:200]))
            return s

        return delim.join(ensure_string(s) for s in strings)
Ejemplo n.º 27
0
    def result(self):
        r_joinlists = function.resolve(self._joinlists)

        strings = []
        for jl in r_joinlists:
            if jl:
                if (isinstance(jl, six.string_types) or
                        not isinstance(jl, collections.Sequence)):
                    raise TypeError(_('"%s" must operate on '
                                      'a list') % self.fn_name)

                strings += jl

        delim = function.resolve(self._delim)
        if not isinstance(delim, six.string_types):
            raise TypeError(_('"%s" delimiter must be a string') %
                            self.fn_name)

        def ensure_string(s):
            msg = _('Items to join must be string, map or list not %s'
                    ) % (repr(s)[:200])
            if s is None:
                return ''
            elif isinstance(s, six.string_types):
                return s
            elif isinstance(s, (collections.Mapping, collections.Sequence)):
                try:
                    return jsonutils.dumps(s, default=None)
                except TypeError:
                    msg = _('Items to join must be string, map or list. '
                            '%s failed json serialization'
                            ) % (repr(s)[:200])

            raise TypeError(msg)

        return delim.join(ensure_string(s) for s in strings)
Ejemplo n.º 28
0
    def _get_instance_definition(self):
        conf_refid = self.properties[self.LAUNCH_CONFIGURATION_NAME]
        conf = self.stack.resource_by_refid(conf_refid)

        props = function.resolve(conf.properties.data)
        props['Tags'] = self._tags()
        vpc_zone_ids = self.properties.get(AutoScalingGroup.VPCZONE_IDENTIFIER)
        if vpc_zone_ids:
            props['SubnetId'] = vpc_zone_ids[0]

        azs = self.properties.get(self.AVAILABILITY_ZONES)
        if azs:
            props['AvailabilityZone'] = azs[0]

        return rsrc_defn.ResourceDefinition(None, SCALED_RESOURCE_TYPE, props,
                                            conf.t.metadata())
Ejemplo n.º 29
0
    def result(self):
        member_list = function.resolve(self._list)

        if not isinstance(member_list, collections.Iterable):
            raise TypeError(_('Member list must be a list'))

        def item(s):
            if not isinstance(s, six.string_types):
                raise TypeError(_("Member list items must be strings"))
            return s.split('=', 1)

        partials = dict(item(s) for s in member_list)
        return extract_param_pairs(partials,
                                   prefix='',
                                   keyname=self._keyname,
                                   valuename=self._valuename)
Ejemplo n.º 30
0
    def rebuild_lc_properties(self, instance_id):
        server = self.client_plugin('nova').get_server(instance_id)
        instance_props = {
            self.IMAGE_ID: server.image['id'],
            self.INSTANCE_TYPE: server.flavor['id'],
            self.KEY_NAME: server.key_name,
            self.SECURITY_GROUPS:
            [sg['name'] for sg in server.security_groups]
        }
        lc_props = function.resolve(self.properties.data)
        for key, value in six.iteritems(instance_props):
            # the properties which are specified in launch configuration,
            # will override the attributes from the instance
            lc_props.setdefault(key, value)

        return lc_props
Ejemplo n.º 31
0
    def validate(self):
        super(GetAtt, self).validate()
        res = self._resource()

        if self._allow_without_attribute_name():
            # if allow without attribute_name, then don't check
            # when attribute_name is None
            if self._attribute is None:
                return

        attr = function.resolve(self._attribute)
        from conveyor.conveyorheat.engine import resource
        if (type(res).get_attribute == resource.Resource.get_attribute
                and attr not in six.iterkeys(res.attributes_schema)):
            raise exception.InvalidTemplateAttribute(
                resource=self._resource_name, key=attr)
Ejemplo n.º 32
0
    def _get_instance_definition(self):
        conf_refid = self.properties[self.LAUNCH_CONFIGURATION_NAME]
        conf = self.stack.resource_by_refid(conf_refid)

        props = function.resolve(conf.properties.data)
        props['Tags'] = self._tags()
        vpc_zone_ids = self.properties.get(AutoScalingGroup.VPCZONE_IDENTIFIER)
        if vpc_zone_ids:
            props['SubnetId'] = vpc_zone_ids[0]

        azs = self.properties.get(self.AVAILABILITY_ZONES)
        if azs:
            props['AvailabilityZone'] = azs[0]

        return rsrc_defn.ResourceDefinition(None,
                                            SCALED_RESOURCE_TYPE,
                                            props,
                                            conf.t.metadata())
Ejemplo n.º 33
0
 def resolve_param(param):
     """Check whether if given item is param and resolve, if it is."""
     # NOTE(prazumovsky): If property uses removed in HOT function,
     # we should not translate it for correct validating and raising
     # validation error.
     if isinstance(param, hot_funcs.Removed):
         raise AttributeError(_('Property uses removed function.'))
     if isinstance(param, (hot_funcs.GetParam, cfn_funcs.ParamRef)):
         try:
             return function.resolve(param)
         except exception.UserParameterMissing as ex:
             # We can't resolve parameter now. Abort translation.
             err_msg = encodeutils.exception_to_unicode(ex)
             raise AttributeError(
                 _('Can not resolve parameter '
                   'due to: %s') % err_msg)
     elif isinstance(param, list):
         return [resolve_param(param_item) for param_item in param]
     else:
         return param
Ejemplo n.º 34
0
    def result(self):
        args = function.resolve(self.args)

        if not isinstance(args, collections.Sequence):
            raise TypeError(_('Incorrect arguments to "%(fn_name)s" '
                              'should be: %(example)s') % self.fmt_data)

        def ensure_map(m):
            if m is None:
                return {}
            elif isinstance(m, collections.Mapping):
                return m
            else:
                msg = _('Incorrect arguments: Items to merge must be maps.')
                raise TypeError(msg)

        ret_map = {}
        for m in args:
            ret_map.update(ensure_map(m))
        return ret_map
Ejemplo n.º 35
0
 def resolve_param(param):
     """Check whether if given item is param and resolve, if it is."""
     # NOTE(prazumovsky): If property uses removed in HOT function,
     # we should not translate it for correct validating and raising
     # validation error.
     if isinstance(param, hot_funcs.Removed):
         raise AttributeError(_('Property uses removed function.'))
     if isinstance(param, (hot_funcs.GetParam, cfn_funcs.ParamRef)):
         try:
             return function.resolve(param)
         except exception.UserParameterMissing as ex:
             # We can't resolve parameter now. Abort translation.
             err_msg = encodeutils.exception_to_unicode(ex)
             raise AttributeError(
                 _('Can not resolve parameter '
                   'due to: %s') % err_msg)
     elif isinstance(param, list):
         return [resolve_param(param_item) for param_item in param]
     else:
         return param
Ejemplo n.º 36
0
    def _get_conf_properties(self):
        instance_id = self.properties.get(self.INSTANCE_ID)
        if instance_id:
            server = self.client_plugin('nova').get_server(instance_id)
            instance_props = {
                'ImageId': server.image['id'],
                'InstanceType': server.flavor['id'],
                'KeyName': server.key_name,
                'SecurityGroups':
                [sg['name'] for sg in server.security_groups]
            }
            conf = self._make_launch_config_resource(self.name, instance_props)
            props = function.resolve(conf.properties.data)
        else:
            conf, props = super(AutoScalingGroup, self)._get_conf_properties()

        vpc_zone_ids = self.properties.get(self.VPCZONE_IDENTIFIER)
        if vpc_zone_ids:
            props['SubnetId'] = vpc_zone_ids[0]

        return conf, props
Ejemplo n.º 37
0
    def _get_conf_properties(self):
        instance_id = self.properties.get(self.INSTANCE_ID)
        if instance_id:
            server = self.client_plugin('nova').get_server(instance_id)
            instance_props = {
                'ImageId': server.image['id'],
                'InstanceType': server.flavor['id'],
                'KeyName': server.key_name,
                'SecurityGroups': [sg['name']
                                   for sg in server.security_groups]
            }
            conf = self._make_launch_config_resource(self.name,
                                                     instance_props)
            props = function.resolve(conf.properties.data)
        else:
            conf, props = super(AutoScalingGroup, self)._get_conf_properties()

        vpc_zone_ids = self.properties.get(self.VPCZONE_IDENTIFIER)
        if vpc_zone_ids:
            props['SubnetId'] = vpc_zone_ids[0]

        return conf, props
Ejemplo n.º 38
0
    def deletion_policy(self):
        """Return the deletion policy for the resource.

        The policy will be one of those listed in DELETION_POLICIES.
        """
        return function.resolve(self._deletion_policy) or self.DELETE
Ejemplo n.º 39
0
 def metadata(self):
     """Return the resource metadata."""
     return function.resolve(self._metadata) or {}