From 0ae722e3ae374af7290285bdd42b673ffc11de89 Mon Sep 17 00:00:00 2001 From: idanaroz Date: Wed, 30 May 2018 07:39:09 -0600 Subject: [PATCH] Fix artifact init case. In case artifact's field is defined to be nullable=false and also doesn't have any default, we had a problem: While creating new artifact of this type with a value for this field we got: "BadRequest field: . value: [None]. Exception. That happened although a field value was provided. This kind of error is expected if the field does not get any value at creation, but not expected if value is provided. The following patch suggest a fix for that. closes-bug: #1775502 Change-Id: I642249f067ab853b4b7d56a8da4db5809ee414c6 --- glare/engine.py | 3 ++ glare/tests/non_nullable_fields_artifact.py | 56 +++++++++++++++++++++ glare/tests/unit/api/test_create.py | 12 +++++ glare/tests/unit/base.py | 6 ++- glare/tests/unit/test_multistore.py | 3 +- 5 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 glare/tests/non_nullable_fields_artifact.py diff --git a/glare/engine.py b/glare/engine.py index ad2b6ec..993cf29 100644 --- a/glare/engine.py +++ b/glare/engine.py @@ -242,6 +242,9 @@ class Engine(object): 'created_at': timeutils.utcnow(), 'updated_at': timeutils.utcnow() } + for k, v in values.items(): + init_values[k] = v + af = artifact_type.init_artifact(context, init_values) # acquire scoped lock and execute artifact create with self._create_scoped_lock(context, type_name, af.name, diff --git a/glare/tests/non_nullable_fields_artifact.py b/glare/tests/non_nullable_fields_artifact.py new file mode 100644 index 0000000..63fed08 --- /dev/null +++ b/glare/tests/non_nullable_fields_artifact.py @@ -0,0 +1,56 @@ +# Copyright (c) 2016 Mirantis, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from oslo_versionedobjects import fields + +from glare.objects import base as base_artifact +from glare.objects.meta import wrappers + +Field = wrappers.Field.init +Dict = wrappers.DictField.init +List = wrappers.ListField.init +Blob = wrappers.BlobField.init +Folder = wrappers.FolderField.init + + +class NonNullableFieldsArtifact(base_artifact.BaseArtifact): + """For testing purposes: check the case of creating artifact that + has nullable=false field without any default + """ + + fields = { + 'int_not_nullable_with_default': Field(fields.IntegerField, + nullable=False, default=0, + required_on_activate=False), + 'int_not_nullable_without_default': Field(fields.IntegerField, + nullable=False) + } + + @classmethod + def get_type_name(cls): + return "non_nullable_fields_artifact" + + @classmethod + def get_display_type_name(cls): + return "not Nullable Fields Artifact" + + def to_dict(self): + res = self.obj_to_primitive()['versioned_object.data'] + res['__some_meta_information__'] = res['name'].upper() + return res + + @classmethod + def format_all(cls, values): + values['__some_meta_information__'] = values['name'].upper() + return values diff --git a/glare/tests/unit/api/test_create.py b/glare/tests/unit/api/test_create.py index 36b230c..4eec571 100644 --- a/glare/tests/unit/api/test_create.py +++ b/glare/tests/unit/api/test_create.py @@ -150,6 +150,18 @@ class TestArtifactCreate(base.BaseTestArtifactAPI): self.assertRaises(exc.BadRequest, self.controller.create, self.req, 'sample_artifact', values) + def test_create_artifact_with_nullable_false_field(self): + values = {'name': 'art1', 'int_not_nullable_without_default': 1} + + res = self.controller.create(self.req, + 'non_nullable_fields_artifact', values) + self.assertEqual(1, res['int_not_nullable_without_default']) + self.assertEqual(0, res['int_not_nullable_with_default']) + + values = {'name': 'art2'} + self.assertRaises(exc.BadRequest, self.controller.create, + self.req, 'non_nullable_fields_artifact', values) + def test_create_artifact_blob(self): values = {'name': 'test', 'blob': 'DATA'} self.assertRaises(exc.BadRequest, self.controller.create, diff --git a/glare/tests/unit/base.py b/glare/tests/unit/base.py index 1b0c7eb..30bf94a 100644 --- a/glare/tests/unit/base.py +++ b/glare/tests/unit/base.py @@ -80,10 +80,12 @@ class BaseTestCase(testtools.TestCase): custom_artifact_types_modules=[ 'glare.tests.sample_artifact', 'glare.tests.hooks_artifact', - 'glare.tests.unpacking_artifact' + 'glare.tests.unpacking_artifact', + 'glare.tests.non_nullable_fields_artifact' ], enabled_artifact_types=[ - 'unpacking_artifact', 'hooks_artifact', 'sample_artifact', + 'non_nullable_fields_artifact', 'unpacking_artifact', + 'hooks_artifact', 'sample_artifact', 'images', 'heat_templates', 'heat_environments', 'murano_packages', 'tosca_templates'] ) diff --git a/glare/tests/unit/test_multistore.py b/glare/tests/unit/test_multistore.py index 89e4c77..fc4da6b 100644 --- a/glare/tests/unit/test_multistore.py +++ b/glare/tests/unit/test_multistore.py @@ -27,7 +27,8 @@ class TestMultistore(base.BaseTestCase): 'murano_packages': 'vsphere', 'sample_artifact': 'database', 'hooks_artifact': 'database', - 'unpacking_artifact': 'database'} + 'unpacking_artifact': 'database', + 'non_nullable_fields_artifact': 'database'} # create engine and register new artifact types engine.Engine()