예제 #1
0
    def _get(key, raw):
        key = EtcdConfiguration._coalesce_dashes(key=key)

        # Unittests
        if hasattr(unittest, 'running_tests') and getattr(
                unittest, 'running_tests') is True:
            if key in ['', '/']:
                return
            stripped_key = key.strip('/')
            data = EtcdConfiguration._unittest_data
            for part in stripped_key.split('/')[:-1]:
                if part not in data:
                    raise etcd.EtcdKeyNotFound(
                        'Key not found : {0}'.format(key))
                data = data[part]
            last_part = stripped_key.split('/')[-1]
            if last_part not in data:
                raise etcd.EtcdKeyNotFound('Key not found : {0}'.format(key))
            data = data[last_part]
            if isinstance(data, dict):
                data = None
        else:
            # Real implementation
            client = EtcdConfiguration._get_client()
            data = client.read(key).value

        if raw is True:
            return data
        return json.loads(data)
예제 #2
0
    def _list(key):
        key = EtcdConfiguration._coalesce_dashes(key=key)

        # Unittests
        if hasattr(unittest, 'running_tests') and getattr(
                unittest, 'running_tests') is True:
            data = EtcdConfiguration._unittest_data
            ends_with_dash = key.endswith('/')
            starts_with_dash = key.startswith('/')
            stripped_key = key.strip('/')
            for part in stripped_key.split('/'):
                if part not in data:
                    raise etcd.EtcdKeyNotFound(
                        'Key not found: {0}'.format(key))
                data = data[part]
            if data:
                for sub_key in data:
                    if ends_with_dash is True:
                        yield '/{0}/{1}'.format(stripped_key, sub_key)
                    else:
                        yield sub_key if starts_with_dash is True else '/{0}'.format(
                            sub_key)
            elif starts_with_dash is False or ends_with_dash is True:
                yield '/{0}'.format(stripped_key)
            return

        # Real implementation
        client = EtcdConfiguration._get_client()
        for child in client.get(key).children:
            if child.key is not None and child.key != key:
                yield child.key.replace('{0}/'.format(key), '')
예제 #3
0
def test_get():
    """
    Test if it get a value from etcd, by direct path
    """
    with patch("etcd.Client") as mock:
        client = etcd_util.EtcdClient({})

        with patch.object(client, "read", autospec=True) as mock:
            mock.return_value = MagicMock(value="stack")
            assert client.get("salt") == "stack"
            mock.assert_called_with("salt", recursive=False)

            # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
            mock.side_effect = iter([etcd.EtcdKeyNotFound()])
            assert client.get("not-found") is None

            mock.side_effect = iter([etcd.EtcdConnectionFailed()])
            assert client.get("watching") is None

            # python 2.6 test
            mock.side_effect = ValueError
            assert client.get("not-found") is None

            mock.side_effect = Exception
            with pytest.raises(Exception):
                client.get("some-error")

        # Get with recurse now delegates to client.tree
        with patch.object(client, "tree", autospec=True) as tree_mock:
            tree_mock.return_value = {"salt": "stack"}
            assert client.get("salt", recurse=True) == {"salt": "stack"}
            tree_mock.assert_called_with("salt")
예제 #4
0
 def test_clean_up_endpoint_status_not_found(self):
     self.m_config.REPORT_ENDPOINT_STATUS = True
     self.m_client.read.side_effect = etcd.EtcdKeyNotFound()
     with patch.object(self.rep, "_mark_endpoint_dirty") as m_mark:
         self.rep.clean_up_endpoint_statuses(async=True)
         self.step_actor(self.rep)
         self.assertFalse(m_mark.called)
예제 #5
0
    def test_tree(self):
        """
        Test recursive gets
        """
        with patch("etcd.Client") as mock:
            client = etcd_util.EtcdClient({})

            with patch.object(client, "read", autospec=True) as mock:

                c1, c2 = MagicMock(), MagicMock()
                c1.__iter__.return_value = [
                    MagicMock(key="/x/a", value="1"),
                    MagicMock(key="/x/b", value="2"),
                    MagicMock(key="/x/c", dir=True),
                ]
                c2.__iter__.return_value = [MagicMock(key="/x/c/d", value="3")]
                mock.side_effect = iter(
                    [MagicMock(children=c1), MagicMock(children=c2)]
                )
                self.assertDictEqual(
                    client.tree("/x"), {"a": "1", "b": "2", "c": {"d": "3"}}
                )
                mock.assert_any_call("/x")
                mock.assert_any_call("/x/c")

                # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
                mock.side_effect = iter([etcd.EtcdKeyNotFound()])
                self.assertEqual(client.tree("not-found"), None)

                mock.side_effect = ValueError
                self.assertEqual(client.tree("/x"), None)

                mock.side_effect = Exception
                self.assertRaises(Exception, client.tree, "some-error")
예제 #6
0
    def test_cluster_host_membership(self):
        """
        Verify host membership in a cluster.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            # Verify member host returns the proper result
            _publish.return_value = [[
                MagicMock(value=self.etcd_cluster), None]]
            body = self.simulate_request(
                '/api/v0/cluster/development/hosts/10.2.0.2')
            self.assertEqual(falcon.HTTP_200, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))

            # Verify non-member host returns the proper result
            _publish.return_value = [[
                MagicMock(value=self.etcd_cluster), None]]
            body = self.simulate_request(
                '/api/v0/cluster/development/hosts/10.9.9.9')
            self.assertEqual(falcon.HTTP_404, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))

            # Verify bad cluster name returns the proper result
            _publish.return_value = [[
                [], etcd.EtcdKeyNotFound()]]
            body = self.simulate_request(
                '/api/v0/cluster/bogus/hosts/10.2.0.2')
            self.assertEqual(falcon.HTTP_404, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))
예제 #7
0
    def test_ls(self):
        with patch('etcd.Client') as mock:
            client = etcd_util.EtcdClient({})

            with patch.object(client, 'read', autospec=True) as mock:
                c1 = MagicMock()
                c1.__iter__.return_value = [
                    MagicMock(key='/x/a', value='1'),
                    MagicMock(key='/x/b', value='2'),
                    MagicMock(key='/x/c', dir=True)
                ]
                mock.return_value = MagicMock(children=c1)
                self.assertEqual(
                    client.ls('/x'),
                    {'/x': {
                        '/x/a': '1',
                        '/x/b': '2',
                        '/x/c/': {}
                    }})
                mock.assert_called_with('/x')

                # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
                mock.side_effect = iter([etcd.EtcdKeyNotFound()])
                self.assertEqual(client.ls('/not-found'), {})

                mock.side_effect = Exception
                self.assertRaises(Exception, client.tree, 'some-error')
예제 #8
0
    def test_get(self):
        """
        Test if it get a value from etcd, by direct path
        """
        with patch("etcd.Client") as mock:
            client = etcd_util.EtcdClient({})

            with patch.object(client, "read", autospec=True) as mock:
                mock.return_value = MagicMock(value="stack")
                self.assertEqual(client.get("salt"), "stack")
                mock.assert_called_with("salt", recursive=False)

                self.assertEqual(client.get("salt", recurse=True), "stack")
                mock.assert_called_with("salt", recursive=True)

                # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
                mock.side_effect = iter([etcd.EtcdKeyNotFound()])
                self.assertEqual(client.get("not-found"), None)

                mock.side_effect = iter([etcd.EtcdConnectionFailed()])
                self.assertEqual(client.get("watching"), None)

                # python 2.6 test
                mock.side_effect = ValueError
                self.assertEqual(client.get("not-found"), None)

                mock.side_effect = Exception
                self.assertRaises(Exception, client.get, "some-error")
예제 #9
0
    def test_cluster_retrieve(self):
        """
        Verify retrieving a cluster.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            # Verify if the cluster exists the data is returned
            child = {'value': self.etcd_host}
            hosts_return_value = MagicMock(
                etcd.EtcdResult, leaves=[child],
                value=child, _children=[child])

            _publish.side_effect = (
                [[MagicMock(value=self.etcd_cluster), None]],
                [[hosts_return_value, None]]
            )

            body = self.simulate_request('/api/v0/cluster/development')
            self.assertEqual(self.srmock.status, falcon.HTTP_200)
            self.assertEqual(
                json.loads(self.acluster),
                json.loads(body[0]))

            # Verify no cluster returns the proper result
            _publish.reset_mock()
            _publish.side_effect = None
            _publish.return_value = [[[], etcd.EtcdKeyNotFound()]]

            body = self.simulate_request('/api/v0/cluster/bogus')
            self.assertEqual(falcon.HTTP_404, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))
예제 #10
0
    def test_tree(self):
        '''
        Test recursive gets
        '''
        with patch('etcd.Client') as mock:
            client = etcd_util.EtcdClient({})

            with patch.object(client, 'read', autospec=True) as mock:

                c1, c2 = MagicMock(), MagicMock()
                c1.__iter__.return_value = [
                    MagicMock(key='/x/a', value='1'),
                    MagicMock(key='/x/b', value='2'),
                    MagicMock(key='/x/c', dir=True)]
                c2.__iter__.return_value = [
                    MagicMock(key='/x/c/d', value='3')
                ]
                mock.side_effect = iter([
                    MagicMock(children=c1),
                    MagicMock(children=c2)
                ])
                self.assertDictEqual(client.tree('/x'), {'a': '1', 'b': '2', 'c': {'d': '3'}})
                mock.assert_any_call('/x')
                mock.assert_any_call('/x/c')

                # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
                mock.side_effect = iter([etcd.EtcdKeyNotFound()])
                self.assertEqual(client.tree('not-found'), None)

                mock.side_effect = ValueError
                self.assertEqual(client.tree('/x'), None)

                mock.side_effect = Exception
                self.assertRaises(Exception, client.tree, 'some-error')
예제 #11
0
    def test_get(self):
        '''
        Test if it get a value from etcd, by direct path
        '''
        with patch('etcd.Client') as mock:
            client = etcd_util.EtcdClient({})

            with patch.object(client, 'read', autospec=True) as mock:
                mock.return_value = MagicMock(value='stack')
                self.assertEqual(client.get('salt'), 'stack')
                mock.assert_called_with('salt', recursive=False)

                self.assertEqual(client.get('salt', recurse=True), 'stack')
                mock.assert_called_with('salt', recursive=True)

                # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
                mock.side_effect = iter([etcd.EtcdKeyNotFound()])
                self.assertEqual(client.get('not-found'), None)

                mock.side_effect = iter([etcd.EtcdConnectionFailed()])
                self.assertEqual(client.get('watching'), None)

                # python 2.6 test
                mock.side_effect = ValueError
                self.assertEqual(client.get('not-found'), None)

                mock.side_effect = Exception
                self.assertRaises(Exception, client.get, 'some-error')
예제 #12
0
    def test_ls(self):
        with patch("etcd.Client") as mock:
            client = etcd_util.EtcdClient({})

            with patch.object(client, "read", autospec=True) as mock:
                c1 = MagicMock()
                c1.__iter__.return_value = [
                    MagicMock(key="/x/a", value="1"),
                    MagicMock(key="/x/b", value="2"),
                    MagicMock(key="/x/c", dir=True),
                ]
                mock.return_value = MagicMock(children=c1)
                self.assertEqual(
                    client.ls("/x"),
                    {"/x": {
                        "/x/a": "1",
                        "/x/b": "2",
                        "/x/c/": {}
                    }})
                mock.assert_called_with("/x")

                # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
                mock.side_effect = iter([etcd.EtcdKeyNotFound()])
                self.assertEqual(client.ls("/not-found"), {})

                mock.side_effect = Exception
                self.assertRaises(Exception, client.tree, "some-error")
    def test_load_with_non_key(self):
        """
        Verify load raises when the key does not exist in etcd.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            _publish.return_value = [[[], etcd.EtcdKeyNotFound()]]

            self.assertRaises(etcd.EtcdKeyNotFound,
                              httpauthbyetcd.HTTPBasicAuthByEtcd)
예제 #14
0
 def test_delete_empty_parents_not_found(self):
     m_client = Mock()
     m_client.delete = Mock()
     m_client.delete.side_effect = [None, etcd.EtcdKeyNotFound(), None]
     delete_empty_parents(m_client, "/foo/bar/baz/biff", "/foo")
     self.assertEqual(m_client.delete.mock_calls, [
         call("foo/bar/baz/biff", dir=True, timeout=5),
         call("foo/bar/baz", dir=True, timeout=5),
         call("foo/bar", dir=True, timeout=5),
     ])
예제 #15
0
 def test_hosts_listing_with_no_etcd_result(self):
     """
     Verify listing hosts handles no etcd result properly.
     """
     with mock.patch('cherrypy.engine.publish') as _publish:
         _publish.return_value = [[[], etcd.EtcdKeyNotFound()]]
         body = self.simulate_request('/api/v0/hosts')
         # datasource's get should have been called once
         self.assertEqual(self.srmock.status, falcon.HTTP_404)
         self.assertEqual('{}', body[0])
예제 #16
0
    def test_clusters_listing_with_no_etcd_result(self):
        """
        Verify listing Clusters handles no etcd result properly.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            _publish.return_value = [[[], etcd.EtcdKeyNotFound()]]

            body = self.simulate_request('/api/v0/clusters')
            self.assertEqual(self.srmock.status, falcon.HTTP_404)
            self.assertEqual('{}', body[0])
예제 #17
0
def test_save(patch_etcd_utils_refresh, patch_etcd_utils_write,
              patch_etcd_utils_read, patch_get_node_id, patch_write,
              patch_read, patch_client):
    setattr(__builtin__, "NS", maps.NamedDict())
    NS.node_context = maps.NamedDict()
    NS.node_context.node_id = 1
    patch_get_node_id.return_value = 1
    patch_client.return_value = etcd.Client()
    setattr(NS, "_int", maps.NamedDict())
    NS._int.etcd_kwargs = {'port': 1, 'host': 2, 'allow_reconnect': True}
    NS._int.client = etcd.Client(**NS._int.etcd_kwargs)
    NS["config"] = maps.NamedDict()
    NS.config["data"] = maps.NamedDict()
    NS.config.data['tags'] = "test"
    NS._int.watchers = dict()
    patch_etcd_utils_read.return_value = maps.NamedDict(
        value='{"status": "UP",'
        '"pkey": "tendrl-node-test",'
        '"node_id": "test_node_id",'
        '"ipv4_addr": "test_ip",'
        '"tags": "[\\"my_tag\\"]",'
        '"sync_status": "done",'
        '"locked_by": "fd",'
        '"fqdn": "tendrl-node-test",'
        '"last_sync": "date"}')
    patch_etcd_utils_write.return_value = maps.NamedDict(
        value='{"status": "UP",'
        '"pkey": "tendrl-node-test",'
        '"node_id": "test_node_id",'
        '"ipv4_addr": "test_ip",'
        '"tags": "[\\"my_tag\\"]",'
        '"sync_status": "done",'
        '"locked_by": "fd",'
        '"fqdn": "tendrl-node-test",'
        '"last_sync": "date"}')
    patch_etcd_utils_refresh.return_value = maps.NamedDict(
        value='{"status": "UP",'
        '"pkey": "tendrl-node-test",'
        '"node_id": "test_node_id",'
        '"ipv4_addr": "test_ip",'
        '"tags": "[\\"my_tag\\"]",'
        '"sync_status": "done",'
        '"locked_by": "fd",'
        '"fqdn": "tendrl-node-test",'
        '"last_sync": "date"}')
    with patch.object(etcd.Client, "read", return_value=etcd.Client()):
        node_context = NodeContext()
        node_context.render()
        node_context.save()
        node_context.save(ttl="test")
    with patch.object(etcd_utils,
                      "refresh",
                      side_effect=etcd.EtcdKeyNotFound()):
        node_context = NodeContext()
        node_context.save(False, "2")
예제 #18
0
 def test_load_with_non_key(self):
     """
     Verify load raises when the key does not exist in etcd.
     """
     self.ds.get.side_effect = etcd.EtcdKeyNotFound()
     return_value = mock.MagicMock(etcd.EtcdResult)
     return_value.value = None
     self.ds.get.return_value = return_value
     self.assertRaises(etcd.EtcdKeyNotFound,
                       self.http_basic_auth_by_etcd.load)
     self.assertEquals(1, self.ds.get.call_count)
예제 #19
0
    def test_implicit_host_create(self):
        """
        Verify creation of a Host with an implied address.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            _publish.side_effect = ([[[], etcd.EtcdKeyNotFound]], [[
                MagicMock(value=self.etcd_host), None
            ]], [[MagicMock(value=self.etcd_host),
                  None]], [[MagicMock(value=self.etcd_cluster),
                            None]], [[MagicMock(value=self.etcd_host), None]])

            data = ('{"ssh_priv_key": "dGVzdAo=",' ' "cluster": "testing"}')
            body = self.simulate_request('/api/v0/host',
                                         method='PUT',
                                         body=data)
            self.assertEqual(self.srmock.status, falcon.HTTP_201)
            self.assertEqual(json.loads(self.ahost), json.loads(body[0]))

            # Make sure creation fails if the cluster doesn't exist
            _publish.side_effect = ([[MagicMock(value=self.etcd_host),
                                      None]], [[[], etcd.EtcdKeyNotFound()]])
            body = self.simulate_request('/api/v0/host',
                                         method='PUT',
                                         body=data)
            self.assertEqual(self.srmock.status, falcon.HTTP_409)
            self.assertEqual({}, json.loads(body[0]))

            # Make sure creation is idempotent if the request parameters
            # agree with an existing host.
            _publish.side_effect = (
                [[MagicMock(value=self.etcd_host), None]],
                [[MagicMock(value=self.etcd_cluster_with_host), None]],
            )

            body = self.simulate_request('/api/v0/host',
                                         method='PUT',
                                         body=data)
            self.assertEqual(self.srmock.status, falcon.HTTP_200)
            self.assertEqual(json.loads(self.ahost), json.loads(body[0]))

            # Make sure creation fails if the request parameters conflict
            # with an existing host.
            _publish.side_effect = (
                [[MagicMock(value=self.etcd_host), None]],
                [[MagicMock(value=self.etcd_host), None]],
            )
            bad_data = '{"ssh_priv_key": "boguskey"}'
            body = self.simulate_request('/api/v0/host',
                                         method='PUT',
                                         body=bad_data)
            self.assertEqual(self.srmock.status, falcon.HTTP_409)
            self.assertEqual({}, json.loads(body[0]))
예제 #20
0
    def test_load_initial_dump(self):
        m_response = Mock(spec=etcd.EtcdResult)
        m_response.etcd_index = 10000
        self.m_client.read.side_effect = [etcd.EtcdKeyNotFound(), m_response]
        with patch("time.sleep") as m_sleep:
            self.assertEqual(self.watcher.load_initial_dump(), m_response)

        m_sleep.assert_called_once_with(1)
        self.m_client.read.assert_has_calls([
            call("/calico", recursive=True),
            call("/calico", recursive=True),
        ])
        self.assertEqual(self.watcher.next_etcd_index, 10001)
예제 #21
0
    def test_cluster_hosts_overwrite(self):
        """
        Verify overwriting a cluster host list.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            # Verify setting host list works with a proper request
            _publish.return_value = [[MagicMock(
                value=self.etcd_cluster), None]]
            # self.datasource.get.return_value = MagicMock(
            #    value=self.etcd_cluster)
            body = self.simulate_request(
                '/api/v0/cluster/development/hosts', method='PUT',
                body='{"old": ["10.2.0.2"], "new": ["10.2.0.2", "10.2.0.3"]}')
            self.assertEqual(falcon.HTTP_200, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))

            # Verify bad request (KeyError) returns the proper result
            _publish.return_value = [[[], KeyError()]]
            body = self.simulate_request(
                '/api/v0/cluster/development/hosts', method='PUT',
                body='{"new": ["10.2.0.2", "10.2.0.3"]}')
            self.assertEqual(falcon.HTTP_400, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))

            # Verify bad request (TypeError) returns the proper result
            _publish.return_value = [[[], TypeError()]]
            body = self.simulate_request(
                '/api/v0/cluster/development/hosts', method='PUT',
                body='["10.2.0.2", "10.2.0.3"]')
            self.assertEqual(falcon.HTTP_400, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))

            # Verify bad cluster name returns the proper result
            _publish.return_value = [[[], etcd.EtcdKeyNotFound()]]
            body = self.simulate_request(
                '/api/v0/cluster/bogus/hosts', method='PUT',
                body='{"old": ["10.2.0.2"], "new": ["10.2.0.2", "10.2.0.3"]}')
            self.assertEqual(falcon.HTTP_404, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))

            # Verify host list conflict returns the proper result
            _publish.return_value = [[
                MagicMock(value=self.etcd_cluster), None]]
            body = self.simulate_request(
                '/api/v0/cluster/development/hosts', method='PUT',
                body='{"old": [], "new": ["10.2.0.2", "10.2.0.3"]}')
            self.assertEqual(falcon.HTTP_409, self.srmock.status)
            self.assertEqual({}, json.loads(body[0]))
예제 #22
0
    def test_cluster_restart_retrieve(self):
        """
        Verify retrieving a cluster restart.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            # Verify if the cluster restart exists the data is returned
            _publish.return_value = [[MagicMock(value=self.arestart), None]]
            body = self.simulate_request('/api/v0/cluster/development/restart')
            self.assertEqual(falcon.HTTP_200, self.srmock.status)
            self.assertEqual(json.loads(self.arestart), json.loads(body[0]))

            # Verify no cluster restart returns the proper result
            _publish.side_effect = (
                [[MagicMock(value=self.arestart), None]],
                [[[], etcd.EtcdKeyNotFound()]])
            body = self.simulate_request('/api/v0/cluster/development/restart')
            self.assertEqual(falcon.HTTP_204, self.srmock.status)
            self.assertEqual([], body)  # Empty data
예제 #23
0
def test_tree(use_v2, client_name):
    """
    Test recursive gets
    """
    with patch(client_name, autospec=True):
        client = etcd_util.get_conn(
            {"etcd.require_v2": use_v2, "etcd.encode_values": False}
        )

        if use_v2:
            with patch.object(client, "read", autospec=True) as mock:
                c1, c2 = MagicMock(), MagicMock()
                c1.__iter__.return_value = [
                    MagicMock(key="/x/a", value="1"),
                    MagicMock(key="/x/b", value="2"),
                    MagicMock(key="/x/c", dir=True),
                ]
                c2.__iter__.return_value = [MagicMock(key="/x/c/d", value="3")]
                mock.side_effect = iter(
                    [MagicMock(children=c1), MagicMock(children=c2)]
                )
                assert client.tree("/x") == {"a": "1", "b": "2", "c": {"d": "3"}}
                mock.assert_any_call("/x")
                mock.assert_any_call("/x/c")

                # iter(list(Exception)) works correctly with both mock<1.1 and mock>=1.1
                mock.side_effect = iter([etcd.EtcdKeyNotFound()])
                assert client.tree("not-found") is None

                mock.side_effect = ValueError
                assert client.tree("/x") is None

                mock.side_effect = Exception
                with pytest.raises(Exception):
                    client.tree("some-error")
        else:
            with patch.object(client, "read", autospec=True) as mock:
                mock.return_value = [
                    MagicMock(key="/x/a", value="1"),
                    MagicMock(key="/x/b", value="2"),
                    MagicMock(key="/x/c/d", value="3"),
                ]
                assert client.tree("/x") == {"a": "1", "b": "2", "c": {"d": "3"}}
                mock.assert_called_with("/x", recurse=True)
예제 #24
0
    def test_cluster_delete(self):
        """
        Verify deleting a cluster.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            # Verify with proper deletion
            _publish.return_value = [[MagicMock(), None]]
            body = self.simulate_request(
                '/api/v0/cluster/development', method='DELETE')
            # Get is called to verify cluster exists
            self.assertEquals(falcon.HTTP_200, self.srmock.status)
            self.assertEquals('{}', body[0])

            # Verify when key doesn't exist
            _publish.return_value = [[[], etcd.EtcdKeyNotFound()]]
            body = self.simulate_request(
                '/api/v0/cluster/development', method='DELETE')
            # Get is called to verify cluster exists
            self.assertEquals(falcon.HTTP_404, self.srmock.status)
            self.assertEquals('{}', body[0])
예제 #25
0
    def _delete(key, recursive):
        key = EtcdConfiguration._coalesce_dashes(key=key)

        # Unittests
        if hasattr(unittest, 'running_tests') and getattr(
                unittest, 'running_tests') is True:
            stripped_key = key.strip('/')
            data = EtcdConfiguration._unittest_data
            for part in stripped_key.split('/')[:-1]:
                if part not in data:
                    raise etcd.EtcdKeyNotFound(
                        'Key not found : {0}'.format(key))
                data = data[part]
            key_to_remove = stripped_key.split('/')[-1]
            if key_to_remove in data:
                del data[key_to_remove]
            return

        # Real implementation
        client = EtcdConfiguration._get_client()
        client.delete(key, recursive=recursive)
예제 #26
0
    def test_host_retrieve(self):
        """
        Verify retrieving a Host.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            # Verify if the host exists the data is returned
            self.return_value.value = self.etcd_host
            _publish.return_value = [[self.return_value, None]]

            body = self.simulate_request('/api/v0/host/10.2.0.2')
            # datasource's get should have been called once
            self.assertEqual(self.srmock.status, falcon.HTTP_200)
            self.assertEqual(json.loads(self.ahost), json.loads(body[0]))

            # Verify no host returns the proper result
            _publish.reset_mock()
            _publish.return_value = [[[], etcd.EtcdKeyNotFound()]]

            body = self.simulate_request('/api/v0/host/10.9.9.9')
            self.assertEqual(self.srmock.status, falcon.HTTP_404)
            self.assertEqual({}, json.loads(body[0]))
예제 #27
0
    def test_cluster_upgrade_retrieve(self):
        """
        Verify retrieving a cluster upgrade.
        """
        with mock.patch('cherrypy.engine.publish') as _publish:
            # Verify if the cluster upgrade exists the data is returned
            self.datasource.get.return_value = MagicMock(
                'etcd.EtcdResult', value=self.etcd_cluster)
            _publish.return_value = [[MagicMock(value=self.aupgrade), None]]
            body = self.simulate_request('/api/v0/cluster/development/upgrade')
            self.assertEqual(falcon.HTTP_200, self.srmock.status)
            self.assertEqual(json.loads(self.aupgrade), json.loads(body[0]))

            # Verify no cluster upgrade returns the proper result
            _publish.reset_mock()
            _publish.side_effect = (
                [[MagicMock(
                    'etcd.EtcdResult', value=self.etcd_cluster), None]],
                [[[], etcd.EtcdKeyNotFound()]])

            body = self.simulate_request('/api/v0/cluster/development/upgrade')
            self.assertEqual(falcon.HTTP_204, self.srmock.status)
            self.assertEqual([], body)  # Empty data
예제 #28
0
    def calculate_new_subnets(self, ports, current_subnets):
        """Calculate and return subnets needed for PORTS.

        Given a current set of PORTS that we need to provide DHCP for,
        calculate all the subnets that we need for those, and get their data
        either from CURRENT_SUBNETS or from reading etcd.

        If the new set of subnets is equivalent to what we already had in
        CURRENT_SUBNETS, return None.  Otherwise return the new set of
        subnets.
        """

        # Gather required subnet IDs.
        subnet_ids = set()
        for port in ports:
            for fixed_ip in port['fixed_ips']:
                subnet_ids.add(fixed_ip['subnet_id'])
        LOG.debug("Needed subnet IDs: %s", subnet_ids)

        # Compare against the existing set of IDs.
        existing_ids = set([s.id for s in current_subnets])
        LOG.debug("Existing subnet IDs: %s", existing_ids)
        if subnet_ids == existing_ids:
            LOG.debug("Subnets unchanged")
            return None

        # Prepare required new subnet data.
        new_subnets = []
        for subnet_id in subnet_ids:
            # Check if we already have this subnet.
            existing = [s for s in current_subnets if s.id == subnet_id]
            if existing:
                # We do.  Assume subnet data hasn't changed.
                new_subnets.extend(existing)
            else:
                LOG.debug("Read subnet %s from etcd", subnet_id)

                # Read the data for this subnet.
                subnet_key = key_for_subnet(subnet_id)
                try:
                    response = self.client.read(subnet_key, consistent=True)
                    data = safe_decode_json(response.value, 'subnet')
                    LOG.debug("Subnet data: %s", data)
                    if not (isinstance(data, dict) and 'cidr' in data
                            and 'gateway_ip' in data):
                        # Subnet data was invalid.
                        LOG.warning("Invalid subnet data: %s => %s",
                                    response.value, data)
                        raise etcd.EtcdKeyNotFound()

                    # Convert to form expected by NetModel.
                    ip_version = 6 if ':' in data['cidr'] else 4
                    subnet = {
                        'enable_dhcp': True,
                        'ip_version': ip_version,
                        'cidr': data['cidr'],
                        'dns_nameservers': data.get('dns_servers') or [],
                        'id': subnet_id,
                        'gateway_ip': data['gateway_ip'],
                        'host_routes': []
                    }
                    if ip_version == 6:
                        subnet['ipv6_address_mode'] = constants.DHCPV6_STATEFUL
                        subnet['ipv6_ra_mode'] = constants.DHCPV6_STATEFUL

                    # Add this to the set to be returned.
                    new_subnets.append(subnet)
                except etcd.EtcdKeyNotFound:
                    LOG.warning("No data for subnet %s", subnet_id)

        return new_subnets
예제 #29
0
 def test_clean_up_endpoint_status_not_found(self):
     self.m_config.REPORT_ENDPOINT_STATUS = True
     self.client.read.side_effect = etcd.EtcdKeyNotFound()
     self.watcher.clean_up_endpoint_statuses(set())
     self.assertFalse(self.m_status_rep.mark_endpoint_dirty.called)
예제 #30
0
 def test_not_in(self):
     """ Can check if key is not in client """
     client = etcd.Client()
     client.get = mock.Mock(side_effect=etcd.EtcdKeyNotFound())
     result = '/testkey' not in client
     self.assertEquals(True, result)