コード例 #1
0
    def _gen_relation_ctx(self):
        _target = MockCloudifyContext('target',
                                      properties={},
                                      runtime_properties={})
        _source = MockCloudifyContext('source',
                                      properties={},
                                      runtime_properties={})

        _ctx = MockCloudifyContext(target=_target, source=_source)

        _ctx._source.instance._runtime_properties = DirtyTrackingDict({})
        _ctx._source.node.properties["connection_config"] = {
            "username": "******",
            "password": "******",
            "host": "vcenter_ip",
            "port": 443,
            "datacenter_name": "vcenter_datacenter",
            "resource_pool_name": "vcenter_resource_pool",
            "auto_placement": "vsphere_auto_placement",
            "allow_insecure": True
        }
        _ctx._target.instance._runtime_properties = DirtyTrackingDict({})
        _ctx._target.node.properties["connection_config"] = {
            "username": "******",
            "password": "******",
            "host": "vcenter_ip",
            "port": 443,
            "datacenter_name": "vcenter_datacenter",
            "resource_pool_name": "vcenter_resource_pool",
            "auto_placement": "vsphere_auto_placement",
            "allow_insecure": True
        }
        current_ctx.set(_ctx)
        return _ctx
コード例 #2
0
    def test_throw_cloudify_exceptions(self):

        # create without error
        fake_ctx = MockCloudifyContext(
            'node_name',
            properties={},
        )
        fake_ctx._operation = Mock()
        fake_ctx.operation._operation_retry = None
        current_ctx.set(fake_ctx)
        fake_ctx.instance._runtime_properties = DirtyTrackingDict({"c": "d"})

        @utils.throw_cloudify_exceptions
        def test(*argc, **kwargs):
            return argc, kwargs

        fake_ctx._operation.name = "cloudify.interfaces.lifecycle.create"
        self.assertEqual(test(ctx=fake_ctx), ((), {'ctx': fake_ctx}))
        self.assertEqual(fake_ctx.instance._runtime_properties, {"c": "d"})

        # delete without error
        fake_ctx.instance._runtime_properties = DirtyTrackingDict({"a": "b"})
        fake_ctx._operation.name = "cloudify.interfaces.lifecycle.delete"
        self.assertEqual(test(ctx=fake_ctx), ((), {'ctx': fake_ctx}))
        self.assertFalse(fake_ctx.instance._runtime_properties)

        # delete postponed by gcp
        fake_ctx.instance._runtime_properties = DirtyTrackingDict(
            {"_operation": "b"})
        fake_ctx._operation.name = "cloudify.interfaces.lifecycle.delete"
        self.assertEqual(test(ctx=fake_ctx), ((), {'ctx': fake_ctx}))
        self.assertEqual(fake_ctx.instance._runtime_properties,
                         {"_operation": "b"})

        # postponed by cloudify
        @utils.throw_cloudify_exceptions
        def test(ctx, *argc, **kwargs):
            ctx.operation._operation_retry = 'Should be retried'
            return argc, kwargs

        fake_ctx.instance._runtime_properties = DirtyTrackingDict({"a": "b"})
        fake_ctx._operation.name = "cloudify.interfaces.lifecycle.delete"
        self.assertEqual(test(ctx=fake_ctx), ((), {}))
        self.assertEqual(fake_ctx.instance._runtime_properties, {"a": "b"})

        # postponed by exeption
        @utils.throw_cloudify_exceptions
        def test(ctx, *argc, **kwargs):
            raise Exception('Should be retried')

        fake_ctx.instance._runtime_properties = DirtyTrackingDict({"a": "b"})
        fake_ctx._operation.name = "cloudify.interfaces.lifecycle.delete"
        with self.assertRaises(NonRecoverableError):
            test(ctx=fake_ctx)

        self.assertEqual(fake_ctx.instance._runtime_properties, {"a": "b"})
コード例 #3
0
    def get_mock_ctx(self,
                     test_name,
                     test_properties=NODE_PROPS,
                     runtime_properties=RUNTIME_PROPS,
                     node_type=DEPLOYMENT_PROXY_TYPE,
                     retry_number=0,
                     operation_name=""):

        operation = {'retry_number': retry_number}

        ctx = MockCloudifyContext(
            node_id=test_name,
            deployment_id=test_name,
            operation=operation,
            properties=test_properties,
        )
        ctx.instance._runtime_properties = DirtyTrackingDict(
            runtime_properties)

        ctx.operation._operation_context = {'name': operation_name}
        ctx.node.type_hierarchy = ['cloudify.nodes.Root', node_type]
        ctx.get_resource_and_render = mock.Mock(
            return_value="resource_and_render")
        ctx.get_resource = mock.Mock(return_value="get_resource")
        try:
            ctx.node.type = node_type
        except AttributeError:
            ctx.logger.error('Failed to set node type attribute.')

        current_ctx.set(ctx)
        return ctx
コード例 #4
0
    def test_execute_jinja_block_parse(self):
        _ctx = MockCloudifyContext('node_name',
                                   properties={
                                       'hosts': ['test123.test'],
                                       'port': -1,
                                       'ssl': False,
                                       'verify': False
                                   })
        _ctx.instance._runtime_properties = DirtyTrackingDict({})
        __location__ = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
        with open(os.path.join(__location__, 'template6.yaml'), 'r') as f:
            template = f.read()
        _ctx.get_resource = MagicMock(return_value=template.encode("utf-8"))
        _ctx.logger.setLevel(logging.DEBUG)
        current_ctx.set(_ctx)
        custom_list = [{
            'key1': 'val1'
        }, {
            'key2': 'val2'
        }, ['element1', 'element2']]
        params = {'custom_list': custom_list}

        with requests_mock.mock(real_http=True) as m:

            m.post('http://test123.test:80/v1/post_jinja_block', text="resp")

            tasks.execute(params=params, template_file='mock_param')
            parsed_list = _ctx.instance.runtime_properties.get('calls')[0].get(
                'payload').get('jinja_block')
            self.assertListEqual(parsed_list, custom_list)
コード例 #5
0
    def test_execute_http_xml(self):
        _ctx = MockCloudifyContext('node_name',
                                   properties={
                                       'hosts': ['test123.test'],
                                       'port': -1,
                                       'ssl': False,
                                       'verify': False
                                   })
        _ctx.instance._runtime_properties = DirtyTrackingDict({})
        __location__ = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
        with open(os.path.join(__location__, 'template5.yaml'), 'r') as f:
            template = f.read()
        _ctx.get_resource = MagicMock(return_value=template.encode("utf-8"))
        _ctx.logger.setLevel(logging.DEBUG)
        current_ctx.set(_ctx)
        with requests_mock.mock() as m:
            with open(os.path.join(__location__, 'get_response5.xml'),
                      'r') as f:
                m.get('http://test123.test:80/v1/get_response5',
                      text=f.read(),
                      status_code=200)

            tasks.execute(params={}, template_file='mock_param')
            # _ctx = current_ctx.get_ctx()
            self.assertDictEqual(
                _ctx.instance.runtime_properties.get('result_properties'), {
                    'UUID': '111111111111111111111111111111',
                    'CPUID': 'ABS:FFF222777'
                })
コード例 #6
0
 def test_execute_nonrecoverable_response(self):
     _ctx = MockCloudifyContext('node_name',
                                properties={
                                    'hosts': ['test123.test'],
                                    'port': 12345,
                                    'ssl': 'true',
                                    'verify': True
                                })
     _ctx.instance._runtime_properties = DirtyTrackingDict({})
     __location__ = os.path.realpath(
         os.path.join(os.getcwd(), os.path.dirname(__file__)))
     with open(os.path.join(__location__, 'template4.yaml'), 'r') as f:
         template = f.read()
     _ctx.get_resource = MagicMock(return_value=template.encode("utf-8"))
     _ctx.logger.setLevel(logging.DEBUG)
     current_ctx.set(_ctx)
     with requests_mock.mock() as m:
         with open(os.path.join(__location__, 'get_response1.json'),
                   'r') as f:
             m.get('https://test123.test:12345/v1/get_response1',
                   json=json.load(f),
                   status_code=200)
         with self.assertRaises(NonRecoverableError) as context:
             tasks.execute(params={}, template_file='mock_param')
         self.assertSequenceEqual(
             'Giving up... \n'
             "Response value: active matches "
             "regexp:active from nonrecoverable_response. ",
             str(context.exception))
コード例 #7
0
 def test_execute_overwrite_host_response_expecation(self):
     _ctx = MockCloudifyContext('node_name',
                                properties={
                                    'hosts': ['test123.test'],
                                    'port': 12345,
                                    'ssl': 'true',
                                    'verify': True
                                })
     _ctx.instance._runtime_properties = DirtyTrackingDict({})
     __location__ = os.path.realpath(
         os.path.join(os.getcwd(), os.path.dirname(__file__)))
     with open(os.path.join(__location__, 'template3.yaml'), 'r') as f:
         template = f.read()
     _ctx.get_resource = MagicMock(return_value=template.encode('utf-8'))
     _ctx.logger.setLevel(logging.DEBUG)
     current_ctx.set(_ctx)
     with requests_mock.mock() as m:
         with open(os.path.join(__location__, 'put_response3.json'),
                   'r') as f:
             m.put(
                 'https://hostfrom_template.test:12345/v1/put_%20response3',
                 json=json.load(f),
                 status_code=200)
         with self.assertRaises(RecoverableError) as context:
             tasks.execute(params={}, template_file='mock_param')
         self.assertSequenceEqual(
             'Trying one more time...\n'
             "Response value:wrong_value "
             "does not match regexp: proper_value|good"
             " from response_expectation", str(context.exception))
コード例 #8
0
 def _to_DirtyTrackingDict(self, origin):
     if not origin:
         origin = {}
     dirty_dict = DirtyTrackingDict()
     for k in origin:
         dirty_dict[k] = copy.deepcopy(origin[k])
     return dirty_dict
コード例 #9
0
 def _get_relationship_context(self, subnet_group):
     _test_name = 'test_lambda'
     _test_node_properties = {
         'use_external_resource': False,
         'resource_id': 'target'
     }
     _test_runtime_properties = {'resource_config': 'resource',
                                 '_set_changed': True}
     source = self.get_mock_ctx("source_node", _test_node_properties,
                                DirtyTrackingDict(_test_runtime_properties),
                                SUBNET_GROUP_I)
     target = self.get_mock_ctx("target_node", _test_node_properties,
                                DirtyTrackingDict(_test_runtime_properties),
                                subnet_group)
     return self.get_mock_relationship_ctx(_test_name,
                                           _test_node_properties,
                                           _test_runtime_properties,
                                           source,
                                           target)
コード例 #10
0
    def _prepare_master_node(self,
                             api_mapping=None,
                             external=False,
                             create=False):
        node = MagicMock()
        node.properties = {
            'configuration': {
                'blueprint_file_name': 'kubernetes.conf'
            }
        }

        managed_master_node = MagicMock()
        managed_master_node.type = RELATIONSHIP_TYPE_MANAGED_BY_MASTER
        managed_master_node.target.node = node

        properties = {
            'use_external_resource': external,
            'validate_resource_status': True,
            'definition': {
                'apiVersion': 'v1',
                'metadata': 'c',
                'spec': 'd'
            },
            'options': {
                'first': 'second'
            }
        }

        if api_mapping:
            properties['api_mapping'] = api_mapping

        _ctx = MockCloudifyContext(
            node_id="test_id",
            node_name="test_name",
            deployment_id="test_name",
            properties=properties,
            runtime_properties=DirtyTrackingDict(
                {} if create else
                {'kubernetes': {
                    'metadata': {
                        'name': "kubernetes_id"
                    }
                }}),
            relationships=[managed_master_node],
            operation={'retry_number': 0})

        _ctx.node.type_hierarchy = \
            ['cloudify.nodes.Root',
             'cloudify.kubernetes.resources.ResourceBase',
             'cloudify.kubernetes.resources.BlueprintDefinedResource',
             'cloudify.kubernetes.resources.Pod']

        current_ctx.set(_ctx)
        return managed_master_node, _ctx
コード例 #11
0
 def setUp(self):
     super(VsphereStorageTest, self).setUp()
     self.mock_ctx = MockCloudifyContext(
         'node_name',
         properties={},
         runtime_properties={}
     )
     self.mock_ctx.instance._runtime_properties = DirtyTrackingDict({})
     self.mock_ctx._operation = Mock()
     self.mock_ctx._capabilities = Mock()
     current_ctx.set(self.mock_ctx)
コード例 #12
0
    def _gen_ctx(self):
        _ctx = MockCloudifyContext(
            'node_name',
            properties={},
        )

        _ctx._execution_id = "execution_id"
        _ctx.instance.host_ip = None
        _ctx.instance._runtime_properties = DirtyTrackingDict({})
        _ctx.get_resource = mock.Mock(return_value=TEMPLATE.encode("utf-8"))
        current_ctx.set(_ctx)
        return _ctx
コード例 #13
0
    def _gen_ctx(self):
        _ctx = MockCloudifyContext(
            'node_name',
            properties={},
        )

        _ctx._execution_id = "execution_id"
        _ctx.instance.host_ip = None
        _ctx.instance._runtime_properties = DirtyTrackingDict({})

        current_ctx.set(_ctx)
        return _ctx
コード例 #14
0
    def mock_ctx(self, test_name, use_secret_store=False,
                 use_secrets_if_exist=False):

        key_path = tempfile.mkdtemp()

        test_node_id = test_name

        if use_secret_store or use_secrets_if_exist:
            test_properties = {
                'use_secret_store': use_secret_store,
                'use_secrets_if_exist':
                    use_secrets_if_exist,
                'key_name': test_name,
                'resource_config': {
                    'public_key_path': '{0}/{1}.pem.pub'.format(
                        key_path,
                        test_name),
                    'openssh_format': True,
                    'algorithm': 'RSA',
                    'bits': 2048
                }
            }
        else:
            test_properties = {
                'use_secret_store': use_secret_store,
                'resource_config': {
                    'private_key_path': '{0}/{1}'.format(
                        key_path,
                        test_name),
                    'public_key_path': '{0}/{1}.pub'.format(
                        key_path,
                        test_name),
                    'openssh_format': True,
                    'algorithm': 'RSA',
                    'bits': 2048
                },
            }

        ctx = MockCloudifyContext(
            node_id=test_node_id,
            properties=test_properties
        )

        ctx.instance._runtime_properties = DirtyTrackingDict({})
        ctx._operation = mock.Mock()

        return ctx
コード例 #15
0
    def _prepare_context(self,
                         with_api_mapping=False,
                         with_definition=True,
                         kind=None):

        properties = {
            'allow_node_redefinition': True,
            'options': {
                'first': 'second'
            }
        }

        if with_definition:
            properties['definition'] = {
                'apiVersion': 'v1',
                'metadata': 'c',
                'spec': 'd'
            }

        if kind:
            properties['definition']['kind'] = kind

        if with_api_mapping:
            properties['api_mapping'] = self._prepare_mapping()

        _ctx = MockCloudifyContext(node_id="test_id",
                                   node_name="test_name",
                                   deployment_id="test_name",
                                   properties=properties,
                                   runtime_properties=DirtyTrackingDict({
                                       'kubernetes': {
                                           'metadata': {
                                               'name': "kubernetes_id"
                                           }
                                       }
                                   }),
                                   relationships=[],
                                   operation={'retry_number': 0})

        _ctx.node.type_hierarchy = \
            ['cloudify.nodes.Root',
             'cloudify.kubernetes.resources.BlueprintDefinedResource',
             'cloudify.kubernetes.resources.Pod']

        current_ctx.set(_ctx)
        return _ctx
コード例 #16
0
 def _create_ctx(self):
     _ctx = MockCloudifyContext('node_name',
                                properties={
                                    'params': {
                                        'a': "b",
                                        'c': 'g'
                                    },
                                    'libvirt_auth': {
                                        'a': 'c'
                                    }
                                },
                                runtime_properties=DirtyTrackingDict({
                                    'params': {
                                        'c': "d",
                                        'e': 'g'
                                    },
                                    'libvirt_auth': {
                                        'a': 'd'
                                    }
                                }))
     current_ctx.set(_ctx)
     return _ctx
コード例 #17
0
def ctx_mock():
    ctx = Mock()
    ctx.node.name = 'name'
    ctx.node.id = 'id'
    ctx.node.properties = {
        'agent_config': {
            'install_method': 'none'
        },
        'gcp_config': {
            'auth': {
                'type': 'service_account',
                'client_email': 'nobody@invalid',
                'private_key_id': "This isn't even an ID!",
                'private_key': 'nope!'
            },
            'zone': 'a very fake zone',
            'network': 'not a real network',
            'project': 'not really a project',
        },
    }
    ctx.instance.runtime_properties = DirtyTrackingDict()
    ctx.instance.relationships = []
    return ctx
コード例 #18
0
 def test_execute_https_port_reco(self):
     _ctx = MockCloudifyContext('node_name',
                                properties={
                                    'host': 'test123.test',
                                    'port': 12345,
                                    'ssl': 'true',
                                    'verify': True
                                })
     _ctx.instance._runtime_properties = DirtyTrackingDict({})
     __location__ = os.path.realpath(
         os.path.join(os.getcwd(), os.path.dirname(__file__)))
     with open(os.path.join(__location__, 'template2.yaml'), 'r') as f:
         template = f.read()
     _ctx.get_resource = MagicMock(return_value=template.encode('utf-8'))
     current_ctx.set(_ctx)
     with requests_mock.mock() as m:
         m.delete('https://test123.test:12345/v1/delete',
                  text='resp',
                  status_code=477)
         with self.assertRaises(RecoverableError) as context:
             tasks.execute(params={}, template_file='mock_param')
         self.assertTrue('Response code 477 '
                         'defined as recoverable' in str(context.exception))
コード例 #19
0
 def setUp(self):
     super(TestInstanceGroup, self).setUp()
     self.ctxmock.source.instance.runtime_properties = DirtyTrackingDict()
コード例 #20
0
    def test_execute_mock_sdk(self):
        _ctx = MockCloudifyContext('node_name',
                                   properties={
                                       'hosts':
                                       ['--fake.cake--', 'test123.test'],
                                       'port': -1,
                                       'ssl': False,
                                       'verify': False,
                                       'params': {
                                           'f': 'e'
                                       }
                                   })
        _ctx.instance._runtime_properties = DirtyTrackingDict(
            {'b': {
                'c': 'd'
            }})
        __location__ = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
        with open(os.path.join(__location__, 'template1.yaml'), 'r') as f:
            template = f.read()
        _ctx.get_resource = MagicMock(return_value=template.encode('utf-8'))
        _ctx.logger.setLevel(logging.DEBUG)
        current_ctx.set(_ctx)

        check_mock = MagicMock(return_value={})
        with patch("cloudify_rest.tasks.utility.process", check_mock):
            tasks.bunch_execute(templates=[{
                'params': {
                    'USER': '******'
                },
                'template_file': 'mock_param',
                'save_to': 'saved_params',
                'params_attributes': {
                    'a': ['b', 'c']
                }
            }])
        check_mock.assert_called_with(
            {
                'f': 'e',
                'ctx': _ctx,
                'a': 'd',
                'USER': '******'
            },
            template, {
                'params': {
                    'f': 'e'
                },
                'verify': False,
                'ssl': False,
                'port': -1,
                'hosts': ['--fake.cake--', 'test123.test']
            },
            prerender=None,
            resource_callback=_ctx.get_resource)

        # overwrite hosts
        _ctx.instance._runtime_properties = DirtyTrackingDict(
            {'b': {
                'c': 'd'
            }})
        check_mock = MagicMock(return_value={})
        with patch("cloudify_rest.tasks.utility.process", check_mock):
            tasks.bunch_execute(
                templates=[{
                    'params': {
                        'USER': '******'
                    },
                    'template_file': 'mock_param',
                    'save_to': 'saved_params',
                    'params_attributes': {
                        'a': ['b', 'c']
                    }
                }],
                # new hosts
                auth={'hosts': ['over_write']})
        check_mock.assert_called_with(
            {
                'f': 'e',
                'ctx': _ctx,
                'a': 'd',
                'USER': '******'
            },
            template, {
                'params': {
                    'f': 'e'
                },
                'verify': False,
                'ssl': False,
                'port': -1,
                'hosts': ['over_write']
            },
            prerender=None,
            resource_callback=_ctx.get_resource)
コード例 #21
0
    def test_update_network_list(self):
        _ctx = self._create_ctx()
        domain = mock.Mock()
        domain.name = mock.Mock(return_value="domain_name")

        # info from leases
        _ctx.instance.runtime_properties['ip'] = '127.0.0.1'
        domain.interfaceAddresses = mock.Mock(return_value={})
        domain_tasks._update_network_list(domain)
        domain.interfaceAddresses.assert_called_with(
            libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)

        # info from agent
        _ctx.instance.runtime_properties['ip'] = None
        domain.interfaceAddresses = mock.Mock(return_value={})
        domain_tasks._update_network_list(domain, False)
        domain.interfaceAddresses.assert_called_with(
            libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT)

        # insert new
        _ctx.instance._runtime_properties = DirtyTrackingDict({})
        domain.interfaceAddresses = mock.Mock(
            return_value={
                'vnet0': {
                    'hwaddr': '52:54:00:09:ba:97',
                    'addrs': [{
                        'prefix': 24,
                        'type': 0,
                        'addr': '192.168.142.148'
                    }]
                }
            })
        domain_tasks._update_network_list(domain, True)
        self.assertEqual(
            _ctx.instance.runtime_properties['params']["networks"],
            [{
                'addrs': [{
                    'prefix': 24,
                    'addr': '192.168.142.148',
                    'type': 0
                }],
                'mac': '52:54:00:09:ba:97',
                'dev': 'vnet0'
            }])

        # update
        _ctx.instance.runtime_properties['params']["networks"] = [{
            'network':
            'common_network',
            'dev':
            'vnet0',
            'mac':
            '52:54:00:09:ba:97'
        }]
        domain.interfaceAddresses = mock.Mock(
            return_value={
                'vnet0': {
                    'hwaddr': '52:54:00:09:ba:97',
                    'addrs': [{
                        'prefix': 24,
                        'type': 0,
                        'addr': '192.168.142.149'
                    }]
                }
            })
        domain_tasks._update_network_list(domain, True)
        self.assertEqual(
            _ctx.instance.runtime_properties['params']["networks"],
            [{
                'network': 'common_network',
                'mac': '52:54:00:09:ba:97',
                'dev': 'vnet0',
                'addrs': [{
                    'prefix': 24,
                    'type': 0,
                    'addr': '192.168.142.149'
                }],
            }])
コード例 #22
0
    def test_execute_http_no_exception(self):
        _ctx = MockCloudifyContext('node_name',
                                   properties={
                                       'hosts':
                                       ['--fake.cake--', 'test123.test'],
                                       'port': -1,
                                       'ssl': False,
                                       'verify': False
                                   })
        _ctx.instance._runtime_properties = DirtyTrackingDict({})
        __location__ = os.path.realpath(
            os.path.join(os.getcwd(), os.path.dirname(__file__)))
        with open(os.path.join(__location__, 'template1.yaml'), 'r') as f:
            template = f.read()
        _ctx.get_resource = MagicMock(return_value=template.encode('utf-8'))
        _ctx.logger.setLevel(logging.DEBUG)
        current_ctx.set(_ctx)
        params = {'USER': '******'}
        with requests_mock.mock(
                real_http=True) as m:  # real_http to check fake uri and get ex
            # call 1
            with open(os.path.join(__location__, 'get_response1.json'),
                      'r') as f:
                m.get('http://test123.test:80/testuser/test_rest/get',
                      json=json.load(f),
                      status_code=200)

            def _match_request_text(request):
                return '101' in (request.text or '')

            # call 2
            m.post('http://test123.test:80/test_rest/posts',
                   additional_matcher=_match_request_text,
                   request_headers={'Content-type': 'test/type'},
                   text='resp')

            # call 1
            with open(os.path.join(__location__, 'get_response2.json'),
                      'r') as f:
                m.get('http://test123.test:80/get',
                      json=json.load(f),
                      headers={'Content-Type': 'application/json'},
                      status_code=200)

            tasks.execute(params=params, template_file='mock_param')
            # _ctx = current_ctx.get_ctx()
            self.assertDictEqual(
                _ctx.instance.runtime_properties.get('result_properties'), {
                    'nested_key0': u'nested_value1',
                    'nested_key1': u'nested_value2',
                    'id0': u'1',
                    'id1': u'101',
                    'owner1': {
                        'id': 'Bob'
                    },
                    'owner2': {
                        'colour': 'red',
                        'name': 'bed',
                        'id': 'Carol'
                    },
                    'owner0': {
                        'colour': 'black',
                        'name': 'book'
                    }
                })