diff --git a/zun/api/controllers/v1/capsules.py b/zun/api/controllers/v1/capsules.py index e083032ce..f7f4e6c1f 100644 --- a/zun/api/controllers/v1/capsules.py +++ b/zun/api/controllers/v1/capsules.py @@ -13,6 +13,7 @@ # under the License. from oslo_log import log as logging +from oslo_serialization import jsonutils import pecan import six @@ -33,6 +34,7 @@ import zun.conf from zun import objects from zun.volume import cinder_api as cinder + CONF = zun.conf.CONF LOG = logging.getLogger(__name__) @@ -51,6 +53,36 @@ def check_policy_on_capsule(capsule, action): policy.enforce(context, action, capsule, action=action) +def check_capsule_template(tpl): + # TODO(kevinz): add volume spec check + tpl_json = tpl + if isinstance(tpl, six.string_types): + try: + tpl_json = jsonutils.loads(tpl) + except Exception as e: + raise exception.FailedParseStringToJson(e) + + kind_field = tpl_json.get('kind') + if kind_field not in ['capsule', 'Capsule']: + raise exception.InvalidCapsuleTemplate("kind fields need to be " + "set as capsule or Capsule") + + spec_field = tpl_json.get('spec') + if spec_field is None: + raise exception.InvalidCapsuleTemplate("No Spec found") + # Align the Capsule restartPolicy with container restart_policy + # Also change the template filed name from Kubernetes type to OpenStack + # type. + if 'restartPolicy' in spec_field.keys(): + spec_field['restartPolicy'] = \ + utils.VALID_CAPSULE_RESTART_POLICY[spec_field['restartPolicy']] + spec_field[utils.VALID_CAPSULE_FIELD['restartPolicy']] = \ + spec_field.pop('restartPolicy') + if spec_field.get('containers') is None: + raise exception.InvalidCapsuleTemplate("No valid containers field") + return spec_field, tpl_json + + class CapsuleCollection(collection.Collection): """API representation of a collection of Capsules.""" @@ -161,7 +193,7 @@ class CapsuleController(base.Controller): capsules_template = capsule_dict.get('template') spec_content, template_json = \ - utils.check_capsule_template(capsules_template) + check_capsule_template(capsules_template) containers_spec, init_containers_spec = \ utils.capsule_get_container_spec(spec_content) diff --git a/zun/common/utils.py b/zun/common/utils.py index 083e58c44..bcf8ba5ae 100644 --- a/zun/common/utils.py +++ b/zun/common/utils.py @@ -27,7 +27,6 @@ from oslo_concurrency import lockutils from oslo_concurrency import processutils from oslo_context import context as common_context from oslo_log import log as logging -from oslo_serialization import jsonutils from oslo_utils import excutils from oslo_utils import strutils import pecan @@ -364,36 +363,6 @@ def execute(*cmd, **kwargs): return custom_execute(*cmd, **kwargs) -def check_capsule_template(tpl): - # TODO(kevinz): add volume spec check - tpl_json = tpl - if isinstance(tpl, six.string_types): - try: - tpl_json = jsonutils.loads(tpl) - except Exception as e: - raise exception.FailedParseStringToJson(e) - - kind_field = tpl_json.get('kind') - if kind_field not in ['capsule', 'Capsule']: - raise exception.InvalidCapsuleTemplate("kind fields need to be " - "set as capsule or Capsule") - - spec_field = tpl_json.get('spec') - if spec_field is None: - raise exception.InvalidCapsuleTemplate("No Spec found") - # Align the Capsule restartPolicy with container restart_policy - # Also change the template filed name from Kubernetes type to OpenStack - # type. - if 'restartPolicy' in spec_field.keys(): - spec_field['restartPolicy'] = \ - VALID_CAPSULE_RESTART_POLICY[spec_field['restartPolicy']] - spec_field[VALID_CAPSULE_FIELD['restartPolicy']] = \ - spec_field.pop('restartPolicy') - if spec_field.get('containers') is None: - raise exception.InvalidCapsuleTemplate("No valid containers field") - return spec_field, tpl_json - - def capsule_get_container_spec(spec_field): containers_spec = spec_field.get('containers') containers_num = len(containers_spec) diff --git a/zun/tests/unit/api/controllers/v1/test_capsules.py b/zun/tests/unit/api/controllers/v1/test_capsules.py index 1e2362a03..07f15a6ad 100644 --- a/zun/tests/unit/api/controllers/v1/test_capsules.py +++ b/zun/tests/unit/api/controllers/v1/test_capsules.py @@ -14,12 +14,64 @@ import mock from mock import patch from oslo_utils import uuidutils from webtest.app import AppError + +from zun.api.controllers.v1 import capsules from zun.common import exception from zun import objects from zun.tests.unit.api import base as api_base from zun.tests.unit.db import utils +class TestCheckCapsuleTemplate(api_base.FunctionalTest): + def test_check_capsule_template(self): + with self.assertRaisesRegex( + exception.InvalidCapsuleTemplate, "kind fields need to " + "be set as capsule or Capsule"): + params = ({"kind": "test", "spec": {"containers": []}}) + capsules.check_capsule_template(params) + + with self.assertRaisesRegex( + exception.InvalidCapsuleTemplate, "No Spec found"): + params = ({"kind": "capsule"}) + capsules.check_capsule_template(params) + + with self.assertRaisesRegex( + exception.InvalidCapsuleTemplate, + "No valid containers field"): + params = ({"kind": "capsule", "spec": {}}) + capsules.check_capsule_template(params) + + params = ({"kind": "capsule", "spec": { + "containers": [{"image": "test1"}], "restartPolicy": "Always", + }}) + spec_content, tpl_json = capsules.check_capsule_template(params) + self.assertEqual(spec_content["restart_policy"], "always") + + def test_check_capsule_template_unicode(self): + with self.assertRaisesRegex( + exception.InvalidCapsuleTemplate, "kind fields need to " + "be set as capsule or Capsule"): + params = (u'{"kind": "test", "spec": {"containers": []}}') + capsules.check_capsule_template(params) + + with self.assertRaisesRegex( + exception.InvalidCapsuleTemplate, "No Spec found"): + params = (u'{"kind": "capsule"}') + capsules.check_capsule_template(params) + + with self.assertRaisesRegex( + exception.InvalidCapsuleTemplate, + "No valid containers field"): + params = (u'{"kind": "capsule", "spec": {}}') + capsules.check_capsule_template(params) + + params = (u'{"kind": "capsule", "spec": {' + u'"containers": [{"image": "test1"}],' + u'"restartPolicy": "Always"}}') + spec_content, tpl_json = capsules.check_capsule_template(params) + self.assertEqual(spec_content["restart_policy"], "always") + + class TestCapsuleController(api_base.FunctionalTest): @patch('zun.compute.api.API.container_create') @patch('zun.network.neutron.NeutronAPI.get_available_network') @@ -93,7 +145,7 @@ class TestCapsuleController(api_base.FunctionalTest): self.assertTrue(mock_neutron_get_network.called) @patch('zun.compute.api.API.container_create') - @patch('zun.common.utils.check_capsule_template') + @patch('zun.api.controllers.v1.capsules.check_capsule_template') def test_create_capsule_wrong_kind_set(self, mock_check_template, mock_capsule_create): params = ('{"template": {"kind": "test",' @@ -110,7 +162,7 @@ class TestCapsuleController(api_base.FunctionalTest): self.assertFalse(mock_capsule_create.called) @patch('zun.compute.api.API.container_create') - @patch('zun.common.utils.check_capsule_template') + @patch('zun.api.controllers.v1.capsules.check_capsule_template') def test_create_capsule_less_than_one_container(self, mock_check_template, mock_capsule_create): params = ('{"template": {"kind": "capsule",' @@ -124,7 +176,7 @@ class TestCapsuleController(api_base.FunctionalTest): self.assertFalse(mock_capsule_create.called) @patch('zun.compute.api.API.container_create') - @patch('zun.common.utils.check_capsule_template') + @patch('zun.api.controllers.v1.capsules.check_capsule_template') def test_create_capsule_no_container_field(self, mock_check_template, mock_capsule_create): params = ('{"template": {"kind": "capsule",' @@ -138,7 +190,7 @@ class TestCapsuleController(api_base.FunctionalTest): self.assertFalse(mock_capsule_create.called) @patch('zun.compute.api.API.container_create') - @patch('zun.common.utils.check_capsule_template') + @patch('zun.api.controllers.v1.capsules.check_capsule_template') def test_create_capsule_no_container_image(self, mock_check_template, mock_capsule_create): params = ('{"template": {"kind": "capsule",' diff --git a/zun/tests/unit/common/test_utils.py b/zun/tests/unit/common/test_utils.py index 52917506d..66f287cbf 100644 --- a/zun/tests/unit/common/test_utils.py +++ b/zun/tests/unit/common/test_utils.py @@ -150,54 +150,6 @@ class TestUtils(base.TestCase): self.assertRaises(exception.ZunException, utils.get_security_group_ids, self.context, security_groups) - def test_check_capsule_template(self): - with self.assertRaisesRegex( - exception.InvalidCapsuleTemplate, "kind fields need to " - "be set as capsule or Capsule"): - params = ({"kind": "test", "spec": {"containers": []}}) - utils.check_capsule_template(params) - - with self.assertRaisesRegex( - exception.InvalidCapsuleTemplate, "No Spec found"): - params = ({"kind": "capsule"}) - utils.check_capsule_template(params) - - with self.assertRaisesRegex( - exception.InvalidCapsuleTemplate, - "No valid containers field"): - params = ({"kind": "capsule", "spec": {}}) - utils.check_capsule_template(params) - - params = ({"kind": "capsule", "spec": { - "containers": [{"image": "test1"}], "restartPolicy": "Always", - }}) - spec_content, tpl_json = utils.check_capsule_template(params) - self.assertEqual(spec_content["restart_policy"], "always") - - def test_check_capsule_template_unicode(self): - with self.assertRaisesRegex( - exception.InvalidCapsuleTemplate, "kind fields need to " - "be set as capsule or Capsule"): - params = (u'{"kind": "test", "spec": {"containers": []}}') - utils.check_capsule_template(params) - - with self.assertRaisesRegex( - exception.InvalidCapsuleTemplate, "No Spec found"): - params = (u'{"kind": "capsule"}') - utils.check_capsule_template(params) - - with self.assertRaisesRegex( - exception.InvalidCapsuleTemplate, - "No valid containers field"): - params = (u'{"kind": "capsule", "spec": {}}') - utils.check_capsule_template(params) - - params = (u'{"kind": "capsule", "spec": {' - u'"containers": [{"image": "test1"}],' - u'"restartPolicy": "Always"}}') - spec_content, tpl_json = utils.check_capsule_template(params) - self.assertEqual(spec_content["restart_policy"], "always") - def test_capsule_get_container_spec(self): with self.assertRaisesRegex( exception.InvalidCapsuleTemplate,