Merge "Always send versioned paths to manifests/repos"
This commit is contained in:
commit
bf9ddb9f9d
|
@ -35,6 +35,7 @@ class ReleaseValidator(BasicValidator):
|
||||||
"Invalid network data: {0}".format(network),
|
"Invalid network data: {0}".format(network),
|
||||||
log_message=True
|
log_message=True
|
||||||
)
|
)
|
||||||
|
|
||||||
if "orchestrator_data" in d:
|
if "orchestrator_data" in d:
|
||||||
if not isinstance(d["orchestrator_data"], dict):
|
if not isinstance(d["orchestrator_data"], dict):
|
||||||
raise errors.InvalidData(
|
raise errors.InvalidData(
|
||||||
|
@ -68,6 +69,11 @@ class ReleaseValidator(BasicValidator):
|
||||||
"No release operating system specified",
|
"No release operating system specified",
|
||||||
log_message=True
|
log_message=True
|
||||||
)
|
)
|
||||||
|
if "orchestrator_data" not in d:
|
||||||
|
raise errors.InvalidData(
|
||||||
|
'No orchestrator_data specified', log_message=True
|
||||||
|
)
|
||||||
|
|
||||||
if db().query(Release).filter_by(
|
if db().query(Release).filter_by(
|
||||||
name=d["name"],
|
name=d["name"],
|
||||||
version=d["version"]
|
version=d["version"]
|
||||||
|
|
|
@ -106,8 +106,20 @@ def upload_fixture(fileobj, loader=None):
|
||||||
except Exception:
|
except Exception:
|
||||||
break
|
break
|
||||||
|
|
||||||
new_obj = obj['model']()
|
# NOTE(ikalnitsly):
|
||||||
|
# In order to add a release to Nailgun we have to fill two tables:
|
||||||
|
# releases and release_orchestrator_data. By using former fixture
|
||||||
|
# approach we can't do it, since the fixture is bond to only one
|
||||||
|
# database model and can't deal with additional logic. Therefore
|
||||||
|
# we need to use Nailgun's objects which know how to handle it.
|
||||||
|
#
|
||||||
|
# TODO(ikalnitsky):
|
||||||
|
# Rewrite fixture logic - it must be simple and obvious.
|
||||||
|
if obj['model'] is objects.Release.model:
|
||||||
|
objects.Release.create(obj['fields'])
|
||||||
|
continue
|
||||||
|
|
||||||
|
new_obj = obj['model']()
|
||||||
fk_fields = {}
|
fk_fields = {}
|
||||||
for field, value in obj["fields"].iteritems():
|
for field, value in obj["fields"].iteritems():
|
||||||
f = getattr(obj['model'], field)
|
f = getattr(obj['model'], field)
|
||||||
|
|
|
@ -1234,6 +1234,11 @@
|
||||||
uri: "http://{{settings.MASTER_IP}}:8080/targetimages/centos_65_x86_64-boot.img.gz"
|
uri: "http://{{settings.MASTER_IP}}:8080/targetimages/centos_65_x86_64-boot.img.gz"
|
||||||
format: "ext2"
|
format: "ext2"
|
||||||
container: "gzip"
|
container: "gzip"
|
||||||
|
orchestrator_data:
|
||||||
|
puppet_manifests_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/manifests/"
|
||||||
|
puppet_modules_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/modules/"
|
||||||
|
repo_metadata:
|
||||||
|
"{OPENSTACK_VERSION}": "http://{MASTER_IP}:8080/{OPENSTACK_VERSION}/centos/x86_64"
|
||||||
- pk: 2
|
- pk: 2
|
||||||
extend: *base_release
|
extend: *base_release
|
||||||
fields:
|
fields:
|
||||||
|
@ -1257,3 +1262,8 @@
|
||||||
uri: "http://{{settings.MASTER_IP}}:8080/targetimages/ubuntu_1204_amd64-boot.img.gz"
|
uri: "http://{{settings.MASTER_IP}}:8080/targetimages/ubuntu_1204_amd64-boot.img.gz"
|
||||||
format: "ext2"
|
format: "ext2"
|
||||||
container: "gzip"
|
container: "gzip"
|
||||||
|
orchestrator_data:
|
||||||
|
puppet_manifests_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/manifests/"
|
||||||
|
puppet_modules_source: "rsync://{MASTER_IP}:/puppet/{OPENSTACK_VERSION}/modules/"
|
||||||
|
repo_metadata:
|
||||||
|
"{OPENSTACK_VERSION}": "http://{MASTER_IP}:8080/{OPENSTACK_VERSION}/ubuntu/x86_64 precise main"
|
||||||
|
|
|
@ -24,7 +24,7 @@ from sqlalchemy import not_
|
||||||
|
|
||||||
from nailgun import consts
|
from nailgun import consts
|
||||||
|
|
||||||
from nailgun.objects.serializers.release import ReleaseSerializer
|
from nailgun.objects.serializers import release as release_serializer
|
||||||
|
|
||||||
from nailgun.db import db
|
from nailgun.db import db
|
||||||
|
|
||||||
|
@ -43,6 +43,9 @@ class ReleaseOrchestratorData(NailgunObject):
|
||||||
#: SQLAlchemy model
|
#: SQLAlchemy model
|
||||||
model = models.ReleaseOrchestratorData
|
model = models.ReleaseOrchestratorData
|
||||||
|
|
||||||
|
#: Serializer for ReleaseOrchestratorData
|
||||||
|
serializer = release_serializer.ReleaseOrchestratorDataSerializer
|
||||||
|
|
||||||
#: JSON schema
|
#: JSON schema
|
||||||
schema = {
|
schema = {
|
||||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
@ -84,13 +87,14 @@ class ReleaseOrchestratorData(NailgunObject):
|
||||||
release = Release.get_by_uid(rendered_data['release_id'])
|
release = Release.get_by_uid(rendered_data['release_id'])
|
||||||
context = {
|
context = {
|
||||||
'MASTER_IP': settings.MASTER_IP,
|
'MASTER_IP': settings.MASTER_IP,
|
||||||
'OPENSTACK_VERSION': release.version,
|
'OPENSTACK_VERSION': release.version}
|
||||||
}
|
|
||||||
|
|
||||||
# render all the paths
|
# render all the paths
|
||||||
|
repo_metadata = {}
|
||||||
for key, value in six.iteritems(rendered_data['repo_metadata']):
|
for key, value in six.iteritems(rendered_data['repo_metadata']):
|
||||||
rendered_data['repo_metadata'][key] = \
|
formatted_key = cls.render_path(key, context)
|
||||||
cls.render_path(value, context)
|
repo_metadata[formatted_key] = cls.render_path(value, context)
|
||||||
|
rendered_data['repo_metadata'] = repo_metadata
|
||||||
|
|
||||||
rendered_data['puppet_manifests_source'] = \
|
rendered_data['puppet_manifests_source'] = \
|
||||||
cls.render_path(rendered_data.get(
|
cls.render_path(rendered_data.get(
|
||||||
|
@ -115,7 +119,7 @@ class Release(NailgunObject):
|
||||||
model = models.Release
|
model = models.Release
|
||||||
|
|
||||||
#: Serializer for Release
|
#: Serializer for Release
|
||||||
serializer = ReleaseSerializer
|
serializer = release_serializer.ReleaseSerializer
|
||||||
|
|
||||||
#: Release JSON schema
|
#: Release JSON schema
|
||||||
schema = {
|
schema = {
|
||||||
|
@ -220,41 +224,16 @@ class Release(NailgunObject):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_orchestrator_data(cls, instance, orchestrator_data):
|
def update_orchestrator_data(cls, instance, orchestrator_data):
|
||||||
for k in ["id", "release_id"]:
|
orchestrator_data.pop("id", None)
|
||||||
orchestrator_data.pop(k, None)
|
orchestrator_data["release_id"] = instance.id
|
||||||
if orchestrator_data:
|
|
||||||
if instance.orchestrator_data:
|
ReleaseOrchestratorData.update(
|
||||||
ReleaseOrchestratorData.update(
|
instance.orchestrator_data, orchestrator_data)
|
||||||
instance.orchestrator_data, orchestrator_data)
|
|
||||||
else:
|
|
||||||
orchestrator_data["release_id"] = instance.id
|
|
||||||
ReleaseOrchestratorData.create(orchestrator_data)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_orchestrator_data_dict(cls, instance):
|
def get_orchestrator_data_dict(cls, instance):
|
||||||
os = instance.operating_system.lower()
|
data = instance.orchestrator_data
|
||||||
default_orchestrator_data = {
|
return ReleaseOrchestratorData.serializer.serialize(data)
|
||||||
"repo_metadata": {
|
|
||||||
"nailgun":
|
|
||||||
settings.DEFAULT_REPO[os].format(
|
|
||||||
MASTER_IP=settings.MASTER_IP),
|
|
||||||
},
|
|
||||||
"puppet_modules_source":
|
|
||||||
settings.DEFAULT_PUPPET['modules'].format(
|
|
||||||
MASTER_IP=settings.MASTER_IP),
|
|
||||||
"puppet_manifests_source":
|
|
||||||
settings.DEFAULT_PUPPET['manifests'].format(
|
|
||||||
MASTER_IP=settings.MASTER_IP),
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"repo_metadata":
|
|
||||||
instance.orchestrator_data.repo_metadata,
|
|
||||||
"puppet_modules_source":
|
|
||||||
instance.orchestrator_data.puppet_modules_source,
|
|
||||||
"puppet_manifests_source":
|
|
||||||
instance.orchestrator_data.puppet_manifests_source
|
|
||||||
} if instance.orchestrator_data else default_orchestrator_data
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_deployable(cls, instance):
|
def is_deployable(cls, instance):
|
||||||
|
|
|
@ -62,13 +62,6 @@ RABBITMQ:
|
||||||
fake: "0"
|
fake: "0"
|
||||||
hostname: "127.0.0.1"
|
hostname: "127.0.0.1"
|
||||||
|
|
||||||
DEFAULT_PUPPET:
|
|
||||||
modules: "rsync://{MASTER_IP}:/puppet/modules/"
|
|
||||||
manifests: "rsync://{MASTER_IP}:/puppet/manifests/"
|
|
||||||
DEFAULT_REPO:
|
|
||||||
centos: "http://{MASTER_IP}:8080/centos/x86_64"
|
|
||||||
ubuntu: "http://{MASTER_IP}:8080/ubuntu/x86_64 precise main"
|
|
||||||
|
|
||||||
PLUGINS_PATH: '/var/www/nailgun/plugins'
|
PLUGINS_PATH: '/var/www/nailgun/plugins'
|
||||||
PLUGINS_SLAVES_SCRIPTS_PATH: '/etc/fuel/plugins/{plugin_name}/'
|
PLUGINS_SLAVES_SCRIPTS_PATH: '/etc/fuel/plugins/{plugin_name}/'
|
||||||
PLUGINS_REPO_URL: 'http://{master_ip}:8080/plugins/{plugin_name}/'
|
PLUGINS_REPO_URL: 'http://{master_ip}:8080/plugins/{plugin_name}/'
|
||||||
|
|
|
@ -134,6 +134,7 @@ class Environment(object):
|
||||||
'attributes_metadata': self.get_default_attributes_metadata(),
|
'attributes_metadata': self.get_default_attributes_metadata(),
|
||||||
'volumes_metadata': self.get_default_volumes_metadata(),
|
'volumes_metadata': self.get_default_volumes_metadata(),
|
||||||
'roles_metadata': self.get_default_roles_metadata(),
|
'roles_metadata': self.get_default_roles_metadata(),
|
||||||
|
'orchestrator_data': self.get_default_orchestrator_data(),
|
||||||
}
|
}
|
||||||
if kwargs:
|
if kwargs:
|
||||||
release_data.update(kwargs)
|
release_data.update(kwargs)
|
||||||
|
@ -469,6 +470,21 @@ class Environment(object):
|
||||||
sample_plugin.update(kwargs)
|
sample_plugin.update(kwargs)
|
||||||
return sample_plugin
|
return sample_plugin
|
||||||
|
|
||||||
|
def get_default_orchestrator_data(self, **kwargs):
|
||||||
|
orchestrator_data = {
|
||||||
|
'puppet_manifests_source':
|
||||||
|
'rsync://127.0.0.1:/puppet/2014.2-6.0/manifests/',
|
||||||
|
|
||||||
|
'puppet_modules_source':
|
||||||
|
'rsync://127.0.0.1:/puppet/2014.2-6.0/modules/',
|
||||||
|
|
||||||
|
'repo_metadata': {
|
||||||
|
'2014.2-6.0': 'http://127.0.0.1:8080/2014.2-6.0/centos/x86_64'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orchestrator_data.update(kwargs)
|
||||||
|
return orchestrator_data
|
||||||
|
|
||||||
def upload_fixtures(self, fxtr_names):
|
def upload_fixtures(self, fxtr_names):
|
||||||
for fxtr_path in self.fxtr_paths_by_names(fxtr_names):
|
for fxtr_path in self.fxtr_paths_by_names(fxtr_names):
|
||||||
with open(fxtr_path, "r") as fxtr_file:
|
with open(fxtr_path, "r") as fxtr_file:
|
||||||
|
|
|
@ -1529,16 +1529,16 @@ class TestRepoAndPuppetDataSerialization(OrchestratorSerializerTestBase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fact['repo_metadata'],
|
fact['repo_metadata'],
|
||||||
{
|
{
|
||||||
'nailgun': 'http://127.0.0.1:8080/centos/x86_64'
|
'2014.2-6.0': 'http://127.0.0.1:8080/2014.2-6.0/centos/x86_64'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fact['puppet_modules_source'],
|
fact['puppet_modules_source'],
|
||||||
'rsync://127.0.0.1:/puppet/modules/'
|
'rsync://127.0.0.1:/puppet/2014.2-6.0/modules/'
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
fact['puppet_manifests_source'],
|
fact['puppet_manifests_source'],
|
||||||
'rsync://127.0.0.1:/puppet/manifests/'
|
'rsync://127.0.0.1:/puppet/2014.2-6.0/manifests/'
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_orch_data_w_replaced_deployment_info(self):
|
def test_orch_data_w_replaced_deployment_info(self):
|
||||||
|
|
|
@ -33,8 +33,10 @@ class TestPlugin(base.BaseTestCase):
|
||||||
self.plugin = Plugin.create(self.plugin_metadata)
|
self.plugin = Plugin.create(self.plugin_metadata)
|
||||||
self.env.create(
|
self.env.create(
|
||||||
cluster_kwargs={'mode': 'multinode'},
|
cluster_kwargs={'mode': 'multinode'},
|
||||||
release_kwargs={'version': '2014.2-6.0',
|
release_kwargs={
|
||||||
'operating_system': 'Ubuntu'})
|
'version': '2014.2-6.0',
|
||||||
|
'operating_system': 'Ubuntu',
|
||||||
|
'orchestrator_data': self.env.get_default_orchestrator_data()})
|
||||||
self.cluster = self.env.clusters[0]
|
self.cluster = self.env.clusters[0]
|
||||||
self.attr_plugin = attr_plugin.ClusterAttributesPlugin(self.plugin)
|
self.attr_plugin = attr_plugin.ClusterAttributesPlugin(self.plugin)
|
||||||
self.env_config = self.env.get_default_plugin_env_config()
|
self.env_config = self.env.get_default_plugin_env_config()
|
||||||
|
|
|
@ -687,7 +687,8 @@ class TestReleaseOrchestratorData(BaseIntegrationTest):
|
||||||
self.data = {
|
self.data = {
|
||||||
'release_id': self.release.id,
|
'release_id': self.release.id,
|
||||||
'repo_metadata': {
|
'repo_metadata': {
|
||||||
'5': 'http://10.20.0.2:8080/{OPENSTACK_VERSION}/centos/x86_64',
|
'{OPENSTACK_VERSION}':
|
||||||
|
'http://10.20.0.2:8080/{OPENSTACK_VERSION}/centos/x86_64',
|
||||||
},
|
},
|
||||||
'puppet_manifests_source': 'rsync://10.20.0.2:/puppet/modules/',
|
'puppet_manifests_source': 'rsync://10.20.0.2:/puppet/modules/',
|
||||||
'puppet_modules_source': 'rsync://10.20.0.2:/puppet/manifests/',
|
'puppet_modules_source': 'rsync://10.20.0.2:/puppet/manifests/',
|
||||||
|
@ -695,7 +696,8 @@ class TestReleaseOrchestratorData(BaseIntegrationTest):
|
||||||
instance = objects.ReleaseOrchestratorData.create(self.data)
|
instance = objects.ReleaseOrchestratorData.create(self.data)
|
||||||
|
|
||||||
self.assertEqual(instance.repo_metadata, {
|
self.assertEqual(instance.repo_metadata, {
|
||||||
'5': 'http://10.20.0.2:8080/{0}/centos/x86_64'.format(
|
self.release.version:
|
||||||
|
'http://10.20.0.2:8080/{0}/centos/x86_64'.format(
|
||||||
self.release.version)})
|
self.release.version)})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
instance.puppet_manifests_source,
|
instance.puppet_manifests_source,
|
||||||
|
|
|
@ -36,7 +36,9 @@ class TestHandlers(BaseIntegrationTest):
|
||||||
params=jsonutils.dumps({
|
params=jsonutils.dumps({
|
||||||
'name': 'Another test release',
|
'name': 'Another test release',
|
||||||
'version': '1.0',
|
'version': '1.0',
|
||||||
'operating_system': 'CentOS'
|
'operating_system': 'CentOS',
|
||||||
|
'orchestrator_data':
|
||||||
|
self.env.get_default_orchestrator_data(),
|
||||||
}),
|
}),
|
||||||
headers=self.default_headers
|
headers=self.default_headers
|
||||||
)
|
)
|
||||||
|
@ -80,7 +82,9 @@ class TestHandlers(BaseIntegrationTest):
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
'orchestrator_data':
|
||||||
|
self.env.get_default_orchestrator_data(),
|
||||||
}),
|
}),
|
||||||
headers=self.default_headers
|
headers=self.default_headers
|
||||||
)
|
)
|
||||||
|
@ -109,7 +113,9 @@ class TestHandlers(BaseIntegrationTest):
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
'orchestrator_data':
|
||||||
|
self.env.get_default_orchestrator_data()
|
||||||
}),
|
}),
|
||||||
headers=self.default_headers,
|
headers=self.default_headers,
|
||||||
expect_errors=True
|
expect_errors=True
|
||||||
|
@ -161,7 +167,9 @@ class TestHandlers(BaseIntegrationTest):
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
'orchestrator_data':
|
||||||
|
self.env.get_default_orchestrator_data()
|
||||||
}),
|
}),
|
||||||
headers=self.default_headers
|
headers=self.default_headers
|
||||||
)
|
)
|
||||||
|
@ -190,7 +198,9 @@ class TestHandlers(BaseIntegrationTest):
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
'orchestrator_data':
|
||||||
|
self.env.get_default_orchestrator_data(),
|
||||||
}),
|
}),
|
||||||
headers=self.default_headers,
|
headers=self.default_headers,
|
||||||
expect_errors=True
|
expect_errors=True
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Copyright 2014 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 nailgun.openstack.common import jsonutils
|
||||||
|
|
||||||
|
from nailgun.api.v1.validators.release import ReleaseValidator
|
||||||
|
from nailgun.errors import errors
|
||||||
|
from nailgun.test.base import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestReleaseValidator(BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestReleaseValidator, self).setUp()
|
||||||
|
|
||||||
|
self.release = {
|
||||||
|
'name': 'Test Release',
|
||||||
|
'version': '2014.2-6.0',
|
||||||
|
'operating_system': 'CentOS',
|
||||||
|
'orchestrator_data': {
|
||||||
|
'puppet_manifests_source': 'path/to/manifests',
|
||||||
|
'puppet_modules_source': 'path/to/modules',
|
||||||
|
|
||||||
|
'repo_metadata': {
|
||||||
|
'repo': 'path/to/repo', }}}
|
||||||
|
self.validator = ReleaseValidator
|
||||||
|
|
||||||
|
def get_release(self, release):
|
||||||
|
return jsonutils.dumps(release)
|
||||||
|
|
||||||
|
def test_name_is_mandatory(self):
|
||||||
|
self.release.pop('name')
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
errors.InvalidData,
|
||||||
|
'No release name specified',
|
||||||
|
self.validator.validate,
|
||||||
|
self.get_release(self.release))
|
||||||
|
|
||||||
|
def test_version_is_mandatory(self):
|
||||||
|
self.release.pop('version')
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
errors.InvalidData,
|
||||||
|
'No release version specified',
|
||||||
|
self.validator.validate,
|
||||||
|
self.get_release(self.release))
|
||||||
|
|
||||||
|
def test_operating_system_is_mandatory(self):
|
||||||
|
self.release.pop('operating_system')
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
errors.InvalidData,
|
||||||
|
'No release operating system specified',
|
||||||
|
self.validator.validate,
|
||||||
|
self.get_release(self.release))
|
||||||
|
|
||||||
|
def test_orchestrator_data_is_mandatory(self):
|
||||||
|
self.release.pop('orchestrator_data')
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
errors.InvalidData,
|
||||||
|
'No orchestrator_data specified',
|
||||||
|
self.validator.validate,
|
||||||
|
self.get_release(self.release))
|
||||||
|
|
||||||
|
def test_orchestrator_data_must_be_a_dict(self):
|
||||||
|
self.release['orchestrator_data'] = None
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
errors.InvalidData,
|
||||||
|
"'orchestrator_data' field must be a dict",
|
||||||
|
self.validator.validate,
|
||||||
|
self.get_release(self.release))
|
||||||
|
|
||||||
|
def test_orchestrator_data_required_keys(self):
|
||||||
|
self.release['orchestrator_data'] = {}
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(
|
||||||
|
errors.InvalidData,
|
||||||
|
"'orchestrator_data' doesn't have all required keys",
|
||||||
|
self.validator.validate,
|
||||||
|
self.get_release(self.release))
|
||||||
|
|
||||||
|
def test_default_are_good(self):
|
||||||
|
self.validator.validate(self.get_release(self.release))
|
Loading…
Reference in New Issue