def prepare_stack_launch_config(group_id, stack_config): """ Prepare a stack config (the stack part of the Group's launch config) with any necessary dynamic data. :param str group_id: The group ID :param PMap stack_config: The stack part of the Group's launch config, as per :obj:`otter.json_schema.group_schemas.stack`. """ # Set stack name and tag to the same thing stack_config = set_in(stack_config, ('stack_name',), get_stack_tag_for_group(group_id)) stack_config = set_in(stack_config, ('tags',), get_stack_tag_for_group(group_id)) return stack_config
def test_returns_new_pmap_given_pmap(self): """ If a PMap is passed in, a new PMap is returned, and even the new value that was passed in gets frozen. """ self.assertEquals(set_in(pmap({1: 2}), (1,), {1: 3}), pmap({1: pmap({1: 3})}))
def append_stack_uuid(stack_config, uuid): """ Append the given uuid to the `stack_name` value in `stack_config`. """ name_key = ('stack_name',) name = get_in(name_key, stack_config) return set_in(stack_config, name_key, name + '_%s' % uuid)
def test_returns_new_pmap_given_pmap(self): """ If a PMap is passed in, a new PMap is returned, and even the new value that was passed in gets frozen. """ self.assertEquals(set_in(pmap({1: 2}), (1, ), {1: 3}), pmap({1: pmap({1: 3})}))
def test_returns_new_pmap_given_dict(self): """ If a dictionary is passed in, a new PMap is returned and the old dictionary is unaffected. """ a = {1: 2} self.assertEquals(set_in(a, (1, ), {1: 3}), pmap({1: pmap({1: 3})})) self.assertEquals(a, {1: 2})
def test_returns_new_pmap_given_dict(self): """ If a dictionary is passed in, a new PMap is returned and the old dictionary is unaffected. """ a = {1: 2} self.assertEquals(set_in(a, (1,), {1: 3}), pmap({1: pmap({1: 3})})) self.assertEquals(a, {1: 2})
def iMock(*ifaces, **kwargs): """ Creates a mock object that provides a particular interface. :param iface: the interface to provide :type iface: :class:``zope.interface.Interface`` :returns: a mock object that is specced to have the attributes and methods as a provider of the interface :rtype: :class:``mock.MagicMock`` """ all_names = [name for iface in ifaces for name in iface.names()] attribute_kwargs = pmap() for k, v in list(kwargs.iteritems()): result = k.split('.', 1) if result[0] in all_names: attribute_kwargs = set_in(attribute_kwargs, result, v) kwargs.pop(k) kwargs.pop('spec', None) imock = mock.MagicMock(spec=all_names, **kwargs) directlyProvides(imock, *ifaces) # autospec all the methods on the interface, and set attributes to None # (just something not callable) for iface in ifaces: for attr in iface: if isinstance(iface[attr], interface.Method): # We need to create a fake function for mock to autospec, # since mock does some magic with introspecting function # signatures - can't a full function signature to a mock # constructor (eg. positional args, defaults, etc.) - so # just using a lambda here. So sorry. fake_func = eval("lambda {0}: None".format( iface[attr].getSignatureString().strip('()'))) wraps(iface[attr])(fake_func) fmock = mock.create_autospec( fake_func, **dict(attribute_kwargs.get(attr, {}))) setattr(imock, attr, fmock) elif isinstance(iface[attr], interface.Attribute): setattr(imock, attr, attribute_kwargs.get(attr, None)) return imock
def set_server_name(server_config_args, name_suffix): """ Append the given name_suffix to the name of the server in the server config. :param server_config_args: The server configuration args. :param name_suffix: the suffix to append to the server name. If no name was specified, it will be used as the name. """ name = server_config_args['server'].get('name') if name is not None: name = '{0}-{1}'.format(name, name_suffix) else: name = name_suffix return set_in(server_config_args, ('server', 'name'), name)
def prepare_server_launch_config(group_id, server_config, lb_descriptions): """ Prepare a server config (the server part of the Group's launch config) with any necessary dynamic data. :param str group_id: The group ID :param PMap server_config: The server part of the Group's launch config, as per :obj:`otter.json_schema.group_schemas.server` except as the value of a one-element PMap with key "server". :param iterable lb_descriptions: iterable of :class:`ILBDescription` providers """ updated_metadata = merge( get_in(('server', 'metadata'), server_config, {}), generate_metadata(group_id, lb_descriptions)) return set_in(server_config, ('server', 'metadata'), updated_metadata)
def validate_launch_stack_config(log, region, service_catalog, auth_token, launch_config): """Validates a launch_stack config using Heat's stack-preview endpoint.""" stack_args = launch_config['stack'] heat_endpoint = get_heat_endpoint(service_catalog, region) url = append_segments(heat_endpoint, 'stacks', 'preview') new_args = thaw(set_in(stack_args, ('stack_name',), 'as_%s' % uuid4())) def catch_error(error): error.trap(APIError) if error.value.code in [400, 404, 409]: raise InvalidLaunchConfiguration(error.value.body) d = treq.post( url, json.dumps(new_args), headers=headers(auth_token), log=log) d.addCallback(check_success, [200]) d.addCallback(treq.json_content) d.addErrback(catch_error) return d
def validate_launch_stack_config(log, region, service_catalog, auth_token, launch_config): """Validates a launch_stack config using Heat's stack-preview endpoint.""" stack_args = launch_config['stack'] heat_endpoint = get_heat_endpoint(service_catalog, region) url = append_segments(heat_endpoint, 'stacks', 'preview') new_args = thaw(set_in(stack_args, ('stack_name', ), 'as_%s' % uuid4())) def catch_error(error): error.trap(APIError) if error.value.code in [400, 404, 409]: raise InvalidLaunchConfiguration(error.value.body) d = treq.post(url, json.dumps(new_args), headers=headers(auth_token), log=log) d.addCallback(check_success, [200]) d.addCallback(treq.json_content) d.addErrback(catch_error) return d
def get_service_metadata(service_name, metadata): """ Obtain all the metadata associated with a particular service from Nova metadata (expecting the schema: `rax:<service_name>:k1:k2:k3...`). :return: the metadata values as a dictionary - in the example above, the dictionary would look like `{k1: {k2: {k3: val}}}` """ as_metadata = pmap() if isinstance(metadata, dict): key_pattern = re.compile( "^rax:{service}(?P<subkeys>(:[A-Za-z0-9\-_]+)+)$".format( service=service_name)) for k, v in metadata.iteritems(): m = key_pattern.match(k) if m: subkeys = m.groupdict()['subkeys'] as_metadata = set_in(as_metadata, [sk for sk in subkeys.split(':') if sk], v) return as_metadata
def get_service_metadata(service_name, metadata): """ Obtain all the metadata associated with a particular service from Nova metadata (expecting the schema: `rax:<service_name>:k1:k2:k3...`). :return: the metadata values as a dictionary - in the example above, the dictionary would look like `{k1: {k2: {k3: val}}}` """ as_metadata = pmap() if isinstance(metadata, dict): key_pattern = re.compile( "^rax:{service}(?P<subkeys>(:[A-Za-z0-9\-_]+)+)$" .format(service=service_name)) for k, v in metadata.iteritems(): m = key_pattern.match(k) if m: subkeys = m.groupdict()['subkeys'] as_metadata = set_in( as_metadata, [sk for sk in subkeys.split(':') if sk], v) return as_metadata
def test_creates_dictionaries(self): """ Create dictionaries as needed, if the old dict didn't have them. """ self.assertEquals(set_in({}, (1, 2, 3), 4), pmap({1: pmap({2: pmap({3: 4})})}))