From f7387cbcf65709b567e26f0718c08a88863da4da Mon Sep 17 00:00:00 2001 From: idanaroz Date: Wed, 30 May 2018 07:39:09 -0600 Subject: [PATCH 1/2] 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 813d496..58b19d5 100644 --- a/glare/engine.py +++ b/glare/engine.py @@ -239,6 +239,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() From f48bec1426479bb9009ef1c884863bfb15b1f55a Mon Sep 17 00:00:00 2001 From: Andreas Jaeger Date: Sat, 25 Aug 2018 18:52:17 +0200 Subject: [PATCH 2/2] Import legacy-glare-dsvm Import legacy-glare-dsvm job and rename to glare-devstack following naming policy. Change-Id: I74aa695df50887d99ccf2b0348f1912a90e94725 --- .zuul.yaml | 18 +++++++ playbooks/glare-devstack/post.yaml | 80 ++++++++++++++++++++++++++++++ playbooks/glare-devstack/run.yaml | 65 ++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 .zuul.yaml create mode 100644 playbooks/glare-devstack/post.yaml create mode 100644 playbooks/glare-devstack/run.yaml diff --git a/.zuul.yaml b/.zuul.yaml new file mode 100644 index 0000000..dde9e59 --- /dev/null +++ b/.zuul.yaml @@ -0,0 +1,18 @@ +- job: + name: glare-devstack + parent: legacy-dsvm-base + run: playbooks/glare-devstack/run.yaml + post-run: playbooks/glare-devstack/post.yaml + timeout: 7800 + required-projects: + - openstack-infra/devstack-gate + - openstack/glare + - openstack/python-glareclient + +- project: + check: + jobs: + - glare-devstack + gate: + jobs: + - glare-devstack diff --git a/playbooks/glare-devstack/post.yaml b/playbooks/glare-devstack/post.yaml new file mode 100644 index 0000000..dac8753 --- /dev/null +++ b/playbooks/glare-devstack/post.yaml @@ -0,0 +1,80 @@ +- hosts: primary + tasks: + + - name: Copy files from {{ ansible_user_dir }}/workspace/ on node + synchronize: + src: '{{ ansible_user_dir }}/workspace/' + dest: '{{ zuul.executor.log_root }}' + mode: pull + copy_links: true + verify_host: true + rsync_opts: + - --include=**/*nose_results.html + - --include=*/ + - --exclude=* + - --prune-empty-dirs + + - name: Copy files from {{ ansible_user_dir }}/workspace/ on node + synchronize: + src: '{{ ansible_user_dir }}/workspace/' + dest: '{{ zuul.executor.log_root }}' + mode: pull + copy_links: true + verify_host: true + rsync_opts: + - --include=**/*testr_results.html.gz + - --include=*/ + - --exclude=* + - --prune-empty-dirs + + - name: Copy files from {{ ansible_user_dir }}/workspace/ on node + synchronize: + src: '{{ ansible_user_dir }}/workspace/' + dest: '{{ zuul.executor.log_root }}' + mode: pull + copy_links: true + verify_host: true + rsync_opts: + - --include=/.testrepository/tmp* + - --include=*/ + - --exclude=* + - --prune-empty-dirs + + - name: Copy files from {{ ansible_user_dir }}/workspace/ on node + synchronize: + src: '{{ ansible_user_dir }}/workspace/' + dest: '{{ zuul.executor.log_root }}' + mode: pull + copy_links: true + verify_host: true + rsync_opts: + - --include=**/*testrepository.subunit.gz + - --include=*/ + - --exclude=* + - --prune-empty-dirs + + - name: Copy files from {{ ansible_user_dir }}/workspace/ on node + synchronize: + src: '{{ ansible_user_dir }}/workspace/' + dest: '{{ zuul.executor.log_root }}/tox' + mode: pull + copy_links: true + verify_host: true + rsync_opts: + - --include=/.tox/*/log/* + - --include=*/ + - --exclude=* + - --prune-empty-dirs + + - name: Copy files from {{ ansible_user_dir }}/workspace/ on node + synchronize: + src: '{{ ansible_user_dir }}/workspace/' + dest: '{{ zuul.executor.log_root }}' + mode: pull + copy_links: true + verify_host: true + rsync_opts: + - --include=/logs/** + - --include=*/ + - --exclude=* + - --prune-empty-dirs diff --git a/playbooks/glare-devstack/run.yaml b/playbooks/glare-devstack/run.yaml new file mode 100644 index 0000000..6d6eea1 --- /dev/null +++ b/playbooks/glare-devstack/run.yaml @@ -0,0 +1,65 @@ +- hosts: all + name: Autoconverted job legacy-glare-dsvm from old job gate-glare-dsvm-ubuntu-xenial + tasks: + + - name: Ensure legacy workspace directory + file: + path: '{{ ansible_user_dir }}/workspace' + state: directory + + - shell: + cmd: | + set -e + set -x + cat > clonemap.yaml << EOF + clonemap: + - name: openstack-infra/devstack-gate + dest: devstack-gate + EOF + /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml --cache-dir /opt/git \ + git://git.openstack.org \ + openstack-infra/devstack-gate + executable: /bin/bash + chdir: '{{ ansible_user_dir }}/workspace' + environment: '{{ zuul | zuul_legacy_vars }}' + + - shell: + cmd: | + set -e + set -x + cat << 'EOF' >>"/tmp/dg-local.conf" + [[local|localrc]] + enable_plugin glare git://git.openstack.org/openstack/glare + + EOF + executable: /bin/bash + chdir: '{{ ansible_user_dir }}/workspace' + environment: '{{ zuul | zuul_legacy_vars }}' + + - shell: + cmd: | + set -e + set -x + export PYTHONUNBUFFERED=true + export PROJECTS="openstack/python-glareclient $PROJECTS" + export PROJECTS="openstack/glare $PROJECTS" + export ENABLED_SERVICES=tempest + export GLARE_CUSTOM_MODULES=glare.tests.sample_artifact + export GLARE_ENABLED_TYPES=heat_templates,heat_environments,murano_packages,tosca_templates,images,sample_artifact + function pre_test_hook { + source $BASE/new/glare/glare_tempest_plugin/contrib/pre_test_hook.sh + } + export -f pre_test_hook + function gate_hook { + source $BASE/new/glare/glare_tempest_plugin/contrib/gate_hook.sh + } + export -f gate_hook + function post_test_hook { + source $BASE/new/glare/glare_tempest_plugin/contrib/post_test_hook.sh + } + export -f post_test_hook + cp devstack-gate/devstack-vm-gate-wrap.sh ./safe-devstack-vm-gate-wrap.sh + ./safe-devstack-vm-gate-wrap.sh + executable: /bin/bash + chdir: '{{ ansible_user_dir }}/workspace' + environment: '{{ zuul | zuul_legacy_vars }}'