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)
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), '')
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")
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)
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")
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]))
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_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")
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]))
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')
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')
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)
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), ])
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])
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])
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")
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)
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]))
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)
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]))
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
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)
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])
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)
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]))
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
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
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)
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)