Merge "Allow add security group by uuid"
This commit is contained in:
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
|
from oslo_utils import uuidutils
|
||||||
import pecan
|
import pecan
|
||||||
import six
|
import six
|
||||||
|
|
||||||
@@ -295,6 +296,34 @@ class ContainersController(base.Controller):
|
|||||||
pecan.response.status = 202
|
pecan.response.status = 202
|
||||||
return view.format_container(pecan.request.host_url, new_container)
|
return view.format_container(pecan.request.host_url, new_container)
|
||||||
|
|
||||||
|
def _check_security_group(self, context, security_group, container):
|
||||||
|
if security_group.get("uuid"):
|
||||||
|
security_group_id = security_group.get("uuid")
|
||||||
|
if not uuidutils.is_uuid_like(security_group_id):
|
||||||
|
raise exception.InvalidUUID(uuid=security_group_id)
|
||||||
|
if security_group_id in container.security_groups:
|
||||||
|
msg = _("security_group %s already present in container") % \
|
||||||
|
security_group_id
|
||||||
|
raise exception.InvalidValue(msg)
|
||||||
|
else:
|
||||||
|
security_group_ids = utils.get_security_group_ids(
|
||||||
|
context, [security_group['name']])
|
||||||
|
if len(security_group_ids) > len(security_group):
|
||||||
|
msg = _("Multiple security group matches "
|
||||||
|
"found for name %(name)s, use an ID "
|
||||||
|
"to be more specific. ") % security_group
|
||||||
|
raise exception.Conflict(msg)
|
||||||
|
else:
|
||||||
|
security_group_id = security_group_ids[0]
|
||||||
|
container_ports_detail = utils.list_ports(context, container)
|
||||||
|
|
||||||
|
for container_port_detail in container_ports_detail:
|
||||||
|
if security_group_id in container_port_detail['security_groups']:
|
||||||
|
msg = _("security_group %s already present in container") % \
|
||||||
|
list(security_group.values())[0]
|
||||||
|
raise exception.InvalidValue(msg)
|
||||||
|
return security_group_id
|
||||||
|
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
@exception.wrap_pecan_controller_exception
|
@exception.wrap_pecan_controller_exception
|
||||||
@validation.validated(schema.add_security_group)
|
@validation.validated(schema.add_security_group)
|
||||||
@@ -312,21 +341,10 @@ class ContainersController(base.Controller):
|
|||||||
# check if security group already presnt in container
|
# check if security group already presnt in container
|
||||||
context = pecan.request.context
|
context = pecan.request.context
|
||||||
compute_api = pecan.request.compute_api
|
compute_api = pecan.request.compute_api
|
||||||
if security_group['name'] in container.security_groups:
|
security_group_id = self._check_security_group(
|
||||||
msg = _("security_group %s already present in container") % \
|
context, security_group, container)
|
||||||
security_group['name']
|
|
||||||
raise exception.InvalidValue(msg)
|
|
||||||
security_group_id = utils.\
|
|
||||||
get_security_group_ids(context, [security_group['name']])[0]
|
|
||||||
container_ports_detail = utils.list_ports(context, container)
|
|
||||||
|
|
||||||
for container_port_detail in container_ports_detail:
|
|
||||||
if security_group_id in container_port_detail['security_groups']:
|
|
||||||
msg = _("security_group %s already present in container") % \
|
|
||||||
security_group['name']
|
|
||||||
raise exception.InvalidValue(msg)
|
|
||||||
compute_api.add_security_group(context, container,
|
compute_api.add_security_group(context, container,
|
||||||
security_group['name'])
|
security_group_id)
|
||||||
pecan.response.status = 202
|
pecan.response.status = 202
|
||||||
|
|
||||||
@pecan.expose('json')
|
@pecan.expose('json')
|
||||||
|
|||||||
@@ -158,8 +158,13 @@ add_security_group = {
|
|||||||
'type': 'string',
|
'type': 'string',
|
||||||
'minLength': 1,
|
'minLength': 1,
|
||||||
'maxLength': 255
|
'maxLength': 255
|
||||||
|
},
|
||||||
|
'uuid': {
|
||||||
|
'type': 'string',
|
||||||
|
'minLength': 2,
|
||||||
|
'maxLength': 255,
|
||||||
|
'pattern': '[a-zA-Z0-9][a-zA-Z0-9_.-]'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'required': ['name'],
|
|
||||||
'additionalProperties': False
|
'additionalProperties': False
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ def get_security_group_ids(context, security_groups, **kwargs):
|
|||||||
**search_opts).get('security_groups', [])
|
**search_opts).get('security_groups', [])
|
||||||
security_group_ids = [item['id'] for item in security_groups_list
|
security_group_ids = [item['id'] for item in security_groups_list
|
||||||
if item['name'] in security_groups]
|
if item['name'] in security_groups]
|
||||||
if len(security_group_ids) == len(security_groups):
|
if len(security_group_ids) >= len(security_groups):
|
||||||
return security_group_ids
|
return security_group_ids
|
||||||
else:
|
else:
|
||||||
raise exception.ZunException(_(
|
raise exception.ZunException(_(
|
||||||
|
|||||||
@@ -756,14 +756,12 @@ class DockerDriver(driver.ContainerDriver):
|
|||||||
return cpu_used
|
return cpu_used
|
||||||
|
|
||||||
def add_security_group(self, context, container, security_group):
|
def add_security_group(self, context, container, security_group):
|
||||||
security_group_ids = utils.get_security_group_ids(
|
|
||||||
context, [security_group])
|
|
||||||
|
|
||||||
with docker_utils.docker_client() as docker:
|
with docker_utils.docker_client() as docker:
|
||||||
network_api = zun_network.api(context=context,
|
network_api = zun_network.api(context=context,
|
||||||
docker_api=docker)
|
docker_api=docker)
|
||||||
network_api.add_security_groups_to_ports(container,
|
network_api.add_security_groups_to_ports(container,
|
||||||
security_group_ids)
|
[security_group])
|
||||||
|
|
||||||
def get_available_nodes(self):
|
def get_available_nodes(self):
|
||||||
return [self._host.get_hostname()]
|
return [self._host.get_hostname()]
|
||||||
|
|||||||
@@ -1398,6 +1398,51 @@ class TestContainerController(api_base.FunctionalTest):
|
|||||||
"security_group %s already present in container" %
|
"security_group %s already present in container" %
|
||||||
default_security_group, response.json['errors'][0]['detail'])
|
default_security_group, response.json['errors'][0]['detail'])
|
||||||
|
|
||||||
|
@mock.patch('zun.compute.api.API.add_security_group')
|
||||||
|
@mock.patch('zun.common.utils.list_ports')
|
||||||
|
@mock.patch('zun.api.utils.get_resource')
|
||||||
|
def test_add_security_group_by_uuid(self, mock_get_resource,
|
||||||
|
mock_list_ports,
|
||||||
|
mock_add_security_group):
|
||||||
|
test_container = utils.get_test_container()
|
||||||
|
test_container_obj = objects.Container(self.context, **test_container)
|
||||||
|
mock_get_resource.return_value = test_container_obj
|
||||||
|
mock_list_ports.return_value = \
|
||||||
|
[{'security_groups': ['fake_default_security_group_id']}]
|
||||||
|
container_name = test_container.get('name')
|
||||||
|
security_group_id_to_add = '5f7cf831-9a9c-4e2b-87b2-6081667f852b'
|
||||||
|
url = '/v1/containers/%s/%s?uuid=%s' % (container_name,
|
||||||
|
'add_security_group',
|
||||||
|
security_group_id_to_add)
|
||||||
|
response = self.app.post(url)
|
||||||
|
self.assertEqual(202, response.status_int)
|
||||||
|
self.assertEqual('application/json', response.content_type)
|
||||||
|
mock_add_security_group.assert_called_once_with(
|
||||||
|
mock.ANY, test_container_obj, security_group_id_to_add)
|
||||||
|
|
||||||
|
@mock.patch('zun.common.utils.get_security_group_ids')
|
||||||
|
@mock.patch('zun.common.utils.list_ports')
|
||||||
|
@mock.patch('zun.api.utils.get_resource')
|
||||||
|
def test_add_security_group_with_invalid_uuid(self, mock_get_resource,
|
||||||
|
mock_list_ports,
|
||||||
|
mock_get_security_group_ids):
|
||||||
|
test_container = utils.get_test_container()
|
||||||
|
test_container_obj = objects.Container(self.context, **test_container)
|
||||||
|
mock_get_resource.return_value = test_container_obj
|
||||||
|
mock_list_ports.return_value = \
|
||||||
|
[{'security_groups': test_container_obj.security_groups}]
|
||||||
|
container_name = test_container.get('name')
|
||||||
|
invalid_uuid = 'invalid_uuid'
|
||||||
|
url = '/v1/containers/%s/%s?uuid=%s' % (container_name,
|
||||||
|
'add_security_group',
|
||||||
|
invalid_uuid)
|
||||||
|
response = self.app.post(url, expect_errors=True)
|
||||||
|
self.assertEqual(400, response.status_int)
|
||||||
|
self.assertEqual('application/json', response.content_type)
|
||||||
|
self.assertEqual(
|
||||||
|
"Expected a uuid but received %(uuid)s." %
|
||||||
|
{'uuid': invalid_uuid}, response.json['errors'][0]['detail'])
|
||||||
|
|
||||||
|
|
||||||
class TestContainerEnforcement(api_base.FunctionalTest):
|
class TestContainerEnforcement(api_base.FunctionalTest):
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user