Extend addresses attribute of Zun container
The original 'addresses' field is a map from neutron network uuid to an address list. For example: {'ed5c1b52-01ab-4a89-8b99-00705d9066c6': [..]} This commit proposes to extend it to neutron network name. This allows the address list to be hashed from uuid or name of a network. {'ed5c1b52-01ab-4a89-8b99-00705d9066c6': [...], 'private': [...]} This improvement will make the format of addresses consistent between containers and VMs. In addition, it allows retrieving IP addresses through either network name or network id. For example: {get_attr: [my-container, addresses, private, 0, addr]} or {get_attr: [my-container, addresses, <uuid>, 0, addr]} The first form is more user-friendly and the latter is able to resolve ambiguity that two networks have the same name. Closes-Bug: #1709191 Change-Id: Ib319e3683529fe71ee1c8dbe3087c9f30f1f1116
This commit is contained in:
parent
4af7865038
commit
46c57e7ae0
|
@ -11,6 +11,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common.i18n import _
|
||||
from heat.engine import attributes
|
||||
|
@ -212,8 +214,32 @@ class Container(resource.Resource):
|
|||
except Exception as exc:
|
||||
self.client_plugin().ignore_not_found(exc)
|
||||
return ''
|
||||
|
||||
if name == self.ADDRESSES:
|
||||
return self._extend_addresses(container)
|
||||
|
||||
return getattr(container, name, '')
|
||||
|
||||
def _extend_addresses(self, container):
|
||||
"""Method adds network name to list of addresses.
|
||||
|
||||
This method is used only for resolving attributes.
|
||||
"""
|
||||
nets = self.neutron().list_networks()['networks']
|
||||
id_name_mapping_on_network = {net['id']: net['name']
|
||||
for net in nets}
|
||||
addresses = copy.deepcopy(container.addresses)
|
||||
for net_uuid in container.addresses or {}:
|
||||
addr_list = addresses[net_uuid]
|
||||
net_name = id_name_mapping_on_network.get(net_uuid)
|
||||
if not net_name:
|
||||
continue
|
||||
|
||||
addresses.setdefault(net_name, [])
|
||||
addresses[net_name] += addr_list
|
||||
|
||||
return addresses
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
return {
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
|
||||
import copy
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
import six
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from heat.common import exception
|
||||
from heat.common import template_format
|
||||
from heat.engine.resources.openstack.zun import container
|
||||
|
@ -67,16 +68,27 @@ class ZunContainerTest(common.HeatTestCase):
|
|||
'Name': 'on-failure'}
|
||||
self.fake_interactive = False
|
||||
self.fake_image_driver = 'docker'
|
||||
self.fake_network_id = '9c11d847-99ce-4a83-82da-9827362a68e8'
|
||||
self.fake_network_name = 'private'
|
||||
self.fake_networks = {
|
||||
'networks': [
|
||||
{
|
||||
'id': self.fake_network_id,
|
||||
'name': self.fake_network_name,
|
||||
}
|
||||
]
|
||||
}
|
||||
self.fake_address = {
|
||||
'version': 4,
|
||||
'addr': '10.0.0.12',
|
||||
'port': 'ab5c12d8-f414-48a3-b765-8ce34a6714d2'
|
||||
}
|
||||
self.fake_addresses = {
|
||||
'addresses': {
|
||||
'private': [
|
||||
{
|
||||
'version': 4,
|
||||
'addr': '10.0.0.12',
|
||||
'port': 'ab5c12d8-f414-48a3-b765-8ce34a6714d2'
|
||||
},
|
||||
],
|
||||
}
|
||||
self.fake_network_id: [self.fake_address]
|
||||
}
|
||||
self.fake_extended_addresses = {
|
||||
self.fake_network_id: [self.fake_address],
|
||||
self.fake_network_name: [self.fake_address],
|
||||
}
|
||||
|
||||
t = template_format.parse(zun_template)
|
||||
|
@ -86,6 +98,9 @@ class ZunContainerTest(common.HeatTestCase):
|
|||
self.client = mock.Mock()
|
||||
self.patchobject(container.Container, 'client',
|
||||
return_value=self.client)
|
||||
self.neutron_client = mock.Mock()
|
||||
self.patchobject(container.Container, 'neutron',
|
||||
return_value=self.neutron_client)
|
||||
|
||||
def _mock_get_client(self):
|
||||
value = mock.MagicMock()
|
||||
|
@ -242,6 +257,7 @@ class ZunContainerTest(common.HeatTestCase):
|
|||
}, reality)
|
||||
|
||||
def test_resolve_attributes(self):
|
||||
self.neutron_client.list_networks.return_value = self.fake_networks
|
||||
c = self._create_resource('container', self.rsrc_defn, self.stack)
|
||||
scheduler.TaskRunner(c.create)()
|
||||
self._mock_get_client()
|
||||
|
@ -249,5 +265,49 @@ class ZunContainerTest(common.HeatTestCase):
|
|||
self.fake_name,
|
||||
c._resolve_attribute(container.Container.NAME))
|
||||
self.assertEqual(
|
||||
self.fake_addresses,
|
||||
self.fake_extended_addresses,
|
||||
c._resolve_attribute(container.Container.ADDRESSES))
|
||||
|
||||
def test_resolve_attributes_duplicate_net_name(self):
|
||||
self.neutron_client.list_networks.return_value = {
|
||||
'networks': [
|
||||
{'id': 'fake_net_id', 'name': 'test'},
|
||||
{'id': 'fake_net_id2', 'name': 'test'},
|
||||
]
|
||||
}
|
||||
self.fake_addresses = {
|
||||
'fake_net_id': [{'addr': '10.0.0.12'}],
|
||||
'fake_net_id2': [{'addr': '10.100.0.12'}],
|
||||
}
|
||||
self.fake_extended_addresses = {
|
||||
'fake_net_id': [{'addr': '10.0.0.12'}],
|
||||
'fake_net_id2': [{'addr': '10.100.0.12'}],
|
||||
'test': [{'addr': '10.0.0.12'}, {'addr': '10.100.0.12'}],
|
||||
}
|
||||
c = self._create_resource('container', self.rsrc_defn, self.stack)
|
||||
scheduler.TaskRunner(c.create)()
|
||||
self._mock_get_client()
|
||||
self._assert_addresses(
|
||||
self.fake_extended_addresses,
|
||||
c._resolve_attribute(container.Container.ADDRESSES))
|
||||
|
||||
def _assert_addresses(self, expected, actual):
|
||||
matched = True
|
||||
if len(expected) != len(actual):
|
||||
matched = False
|
||||
for key in expected:
|
||||
if key not in actual:
|
||||
matched = False
|
||||
break
|
||||
list1 = expected[key]
|
||||
list1 = sorted(list1, key=lambda x: sorted(x.values()))
|
||||
list2 = actual[key]
|
||||
list2 = sorted(list2, key=lambda x: sorted(x.values()))
|
||||
if list1 != list2:
|
||||
matched = False
|
||||
break
|
||||
|
||||
if not matched:
|
||||
raise AssertionError(
|
||||
'Addresses is unmatched:\n reference = ' + str(expected) +
|
||||
'\nactual = ' + str(actual))
|
||||
|
|
Loading…
Reference in New Issue