Removes unused code

This patch removes the code previously committed for the API
implementation we abandoned in favor of Mistral workflows.

Change-Id: I34ece26dced3b4b07c030b7689f2b408925f86d6
This commit is contained in:
Ryan Brady 2016-05-24 17:34:22 -04:00
parent 61a164c8dd
commit 65821cc7cf
19 changed files with 72 additions and 1546 deletions

View File

@ -17,8 +17,8 @@ import logging
import yaml
from tripleo_common.actions import base
from tripleo_common.core import constants
from tripleo_common.core import exception
from tripleo_common import constants
from tripleo_common import exception
LOG = logging.getLogger(__name__)

View File

@ -31,3 +31,11 @@ DEFAULT_CONTAINER_NAME = 'overcloud'
#: The path to the tripleo heat templates installed on the undercloud
DEFAULT_TEMPLATES_PATH = '/usr/share/openstack-tripleo-heat-templates/'
# TRIPLEO_META_USAGE_KEY is inserted into metadata for containers created in
# Swift via SwiftPlanStorageBackend to identify them from other containers
TRIPLEO_META_USAGE_KEY = 'x-container-meta-usage-tripleo'
# OBJECT_META_KEY_PREFIX is used to prefix Swift metadata keys per object
# in SwiftPlanStorageBackend
OBJECT_META_KEY_PREFIX = 'x-object-meta-'

View File

@ -1,28 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
# TRIPLEO_META_USAGE_KEY is inserted into metadata for containers created in
# Swift via SwiftPlanStorageBackend to identify them from other containers
TRIPLEO_META_USAGE_KEY = 'x-container-meta-usage-tripleo'
# OBJECT_META_KEY_PREFIX is used to prefix Swift metadata keys per object
# in SwiftPlanStorageBackend
OBJECT_META_KEY_PREFIX = 'x-object-meta-'
# The following keys are used when identifying metadata from the capabilities
# map file
ROOT_TEMPLATE_META = {'file-type': 'root-template'}
ROOT_ENVIRONMENT_META = {'file-type': 'root-environment', 'enabled': 'True'}
ENVIRONMENT_META = {'file-type': 'environment'}

View File

@ -1,96 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import logging
import six
from six import reraise as raise_
import sys
from tripleo_common.core.i18n import _
from tripleo_common.core.i18n import _LE
_FATAL_EXCEPTION_FORMAT_ERRORS = False
LOG = logging.getLogger(__name__)
@six.python_2_unicode_compatible
class TripleoCommonException(Exception):
"""Base Tripleo-Common Exception.
To correctly use this class, inherit from it and define a 'msg_fmt'
property. That msg_fmt will get printf'd with the keyword arguments
provided to the constructor.
"""
message = _("An unknown exception occurred.")
def __init__(self, **kwargs):
self.kwargs = kwargs
try:
self.message = self.msg_fmt % kwargs
except KeyError:
exc_info = sys.exc_info()
# kwargs doesn't match a variable in the message
# log the issue and the kwargs
LOG.exception(_LE('Exception in string format operation'))
for name, value in six.iteritems(kwargs):
LOG.error(_LE("%(name)s: %(value)s"),
{'name': name, 'value': value}) # noqa
if _FATAL_EXCEPTION_FORMAT_ERRORS:
raise_(exc_info[0], exc_info[1], exc_info[2])
def __str__(self):
return self.message
def __deepcopy__(self, memo):
return self.__class__(**self.kwargs)
class StackInUseError(TripleoCommonException):
msg_fmt = _("Cannot delete a plan that has an associated stack.")
class PlanDoesNotExistError(TripleoCommonException):
msg_fmt = _("A plan with the name %(name)s does not exist.")
class FileDoesNotExistError(TripleoCommonException):
msg_fmt = _("A file with the name %(name)s does not exist.")
class ContainerAlreadyExistsError(TripleoCommonException):
msg_fmt = _("A container with the name %(name)s already exists.")
class TooManyRootTemplatesError(TripleoCommonException):
msg_fmt = _("There can only be up to one root template in a given plan.")
class HeatValidationFailedError(TripleoCommonException):
msg_fmt = _("The plan failed to validate via the Heat service. %(msg)s")
class MappingFileNotFoundError(TripleoCommonException):
msg_fmt = _("The capabilities_map.yaml file was not found in the root"
" of the plan.")
class TooManyCapabilitiesMapFilesError(TripleoCommonException):
msg_fmt = _("There cannot be more than one root template in a given plan.")
class ServiceEndpointNotFoundError(TripleoCommonException):
msg_fmt = _("No endpoints found for [%(service_name)s, %(service_type)s].")

View File

@ -1,42 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import datetime
import yaml
class BaseModel(object):
def __repr__(self, *args, **kwargs):
repr_ = {self.__class__.__name__: self.__dict__}
return yaml.safe_dump(repr_, default_flow_style=True)
def __eq__(self, other):
if not (isinstance(other, self.__class__) or
isinstance(self, other.__class__)):
return False
return self.__dict__ == getattr(other, '__dict__')
class Plan(BaseModel):
def __init__(self, name):
self.name = name
self.files = {}
self.metadata = {}
def created_date(self):
return datetime.datetime.fromtimestamp(
float(self.metadata['x-timestamp']))

View File

@ -1,272 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import logging
import yaml
from heatclient import exc as heatexceptions
import six
from swiftclient import exceptions as swiftexceptions
from tripleo_common.core import exception
from tripleo_common.utils import meta
from tripleo_common.utils import templates
LOG = logging.getLogger(__name__)
class PlanManager(object):
def __init__(self, plan_storage_backend, heatclient):
# TODO(rbrady) add code to create a storage backend based on config
# so the API can send a string representing a backend type and any
# client objects needed by the backend type
self.plan_store = plan_storage_backend
self.heatclient = heatclient
def create_plan(self, plan_name, plan_files):
"""Creates a plan to store templates
Creates a plan by creating a container matching plan_name, and
import given plan_files into it. The plan files is a dictionary
where the keys are filenames and the values are file contents.
:param plan_name: The name of the plan to use as the container name
:type plan_name: str
:param plan_files: The files to import into the container.
:type plan_files: dict
"""
# create container with versioning
try:
self.plan_store.create(plan_name)
except Exception:
LOG.exception("Error creating plan.")
raise
plan_files = meta.add_file_metadata(plan_files)
return self.update_plan(plan_name, plan_files)
def delete_plan(self, plan_name):
"""Deletes a plan and associated files
Deletes a plan by deleting the container matching plan_name. It
will not delete the plan if a stack exists with the same name.
Raises StackInUseError if a stack with the same name as plan_name
exists.
:param plan_name: The name of the container to delete
:type plan_name: str
"""
# heat throws HTTPNotFound if the stack is not found
try:
stack = self.heatclient.stacks.get(plan_name)
if stack is not None:
raise exception.StackInUseError(name=plan_name)
except heatexceptions.HTTPNotFound:
try:
self.plan_store.delete(plan_name)
except swiftexceptions.ClientException as ce:
LOG.exception("Swift error deleting plan.")
if ce.http_status == 404:
six.raise_from(exception.PlanDoesNotExistError(
name=plan_name), ce)
except Exception:
LOG.exception("Error deleting plan.")
raise
def delete_file(self, plan_name, filename):
"""Deletes file in a plan container
:param plan_name: The name of the plan to use as the container name
:type plan_name: str
:param filename: The file to delete from the container.
:type filename: str
"""
try:
self.plan_store.delete_file(plan_name, filename)
except swiftexceptions.ClientException as ce:
LOG.exception("Swift error deleting file.")
if ce.http_status == 404:
six.raise_from(exception.FileDoesNotExistError(
name=filename), ce)
except Exception:
LOG.exception("Error deleting file from plan.")
raise
def delete_temporary_environment(self, plan_name):
"""Deletes the temporary environment files
The temporary environment is the combination of deployment parameters
and selected environment information
:param plan_name: The name of the plan to use as the container name
:type plan_name: str
"""
plan = self.get_plan(plan_name)
for item in {k: v for (k, v) in plan.files.items() if
v.get('meta', {}).get('file-type') == 'temp-environment'}:
self.plan_store.delete_file(plan_name, item)
def get_plan(self, plan_name):
"""Retrieves the Heat templates and environment file
Retrieves the files from the container matching plan_name.
:param plan_name: The name of the plan to retrieve files for.
:type plan_name: str
:rtype dict
"""
try:
return self.plan_store.get(plan_name)
except swiftexceptions.ClientException as ce:
LOG.exception("Swift error retrieving plan.")
if ce.http_status == 404:
six.raise_from(exception.PlanDoesNotExistError(
name=plan_name), ce)
except Exception:
LOG.exception("Error retrieving plan.")
raise
def get_plan_list(self):
"""Gets a list of containers that store plans
Gets a list of containers that contain metadata with the key of
X-Container-Meta-Usage-Tripleo and value or 'plan'.
:return: a list of strings containing plan names
"""
try:
return self.plan_store.list()
except Exception:
LOG.exception("Error retrieving plan list.")
raise
def get_deployment_parameters(self, plan_name):
"""Determine available deployment parameters
:param plan_name: The name of the plan and container name
"""
plan = self.get_plan(plan_name)
template, environment, files = templates.process_plan_data(plan.files)
try:
params = self.heatclient.stacks.validate(
template=template,
files=files,
environment=environment,
show_nested=True)
except heatexceptions.HTTPBadRequest as exc:
six.raise_from(exception.HeatValidationFailedError(msg=exc), exc)
return params
def update_deployment_parameters(self, plan_name, deployment_parameters):
"""Update the deployment parameters
:param plan_name: The name of the plan and container name
:type plan_name: str
:param deployment_parameters: dictionary of deployment parameters
:type deployment_parameters: dict
"""
plan = self.get_plan(plan_name)
deployment_params_file = 'environments/deployment_parameters.yaml'
# Make sure the dict has the expected environment file format.
if not deployment_parameters.get('parameter_defaults'):
deployment_parameters = {
'parameter_defaults': deployment_parameters
}
# pop the deployment params temporary environment file from the plan
# so it's not included in the validation call. If the stack is valid
# the deployment params temporary environment file is overwritten
if deployment_params_file in plan.files:
plan.files.pop(deployment_params_file)
# Update deployment params and validate through heat API.
template, environment, files = templates.process_plan_data(plan.files)
environment = templates.deep_update(environment, deployment_parameters)
try:
self.heatclient.stacks.validate(
template=template,
files=files,
environment=environment,
show_nested=True)
except heatexceptions.HTTPBadRequest as exc:
six.raise_from(exception.HeatValidationFailedError(msg=exc), exc)
env = yaml.safe_dump(deployment_parameters, default_flow_style=False)
plan.files[deployment_params_file] = {
'contents': env,
'meta': {
'file-type': 'temp-environment',
}
}
self.update_plan(plan_name, plan.files)
def update_plan(self, plan_name, plan_files):
"""Updates files in a plan container
:param plan_name: The name of the plan to use as the container name
:type plan_name: str
:param plan_files: The files to import into the container.
:type plan_files: dict
"""
try:
self.plan_store.update(plan_name, plan_files)
except swiftexceptions.ClientException as ce:
LOG.exception("Swift error updating plan.")
if ce.http_status == 404:
six.raise_from(exception.PlanDoesNotExistError(
name=plan_name), ce)
except Exception:
LOG.exception("Error updating plan.")
raise
return self.get_plan(plan_name)
def validate_plan(self, plan_name):
"""Validate Plan
This private method provides validations to ensure a plan
meets the proper criteria before allowed to persist in storage.
:param plan_files: The files to import into the container.
:type plan_files: dict
:returns boolean
"""
plan = self.get_plan(plan_name)
# there can only be up to one root-template file in metadata
rt = {k: v for (k, v) in plan.files.items()
if v.get('meta', {}).get('file-type') == 'root-template'}
if len(rt) > 1:
raise exception.TooManyRootTemplatesError()
# the plan needs to be validated with heat to ensure it conforms
template, environment, files = templates.process_plan_data(plan.files)
try:
self.heatclient.stacks.validate(
template=template,
files=files,
environment=environment,
show_nested=True)
except heatexceptions.HTTPBadRequest as exc:
LOG.exception("Error validating the plan.")
six.raise_from(exception.HeatValidationFailedError(msg=exc), exc)
# no validation issues found
return True

View File

@ -1,135 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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 tripleo_common.core import constants
from tripleo_common.core import exception
from tripleo_common.core.models import Plan
from tripleo_common.utils import meta
default_container_headers = {
'X-Versions-Location': 'versions',
constants.TRIPLEO_META_USAGE_KEY: 'plan'
}
class SwiftPlanStorageBackend(object):
def __init__(self, swiftclient):
self.swiftclient = swiftclient
def create(self, plan_name):
"""Creates a plan to store files
Creates a plan by creating a Swift container matching plan_name, and
given files into it.
:param plan_name: The name of the plan
:type plan_name: str
:param plan_files: names and contents of files to store
:type plan_files: dict
"""
if plan_name not in self.list():
self.swiftclient.put_container(
plan_name,
headers=default_container_headers
)
else:
raise exception.ContainerAlreadyExistsError(name=plan_name)
def delete(self, plan_name):
"""Deletes a plan and associated files
Deletes a plan by deleting the Swift container matching plan_name.
:param plan_name: The name of the plan
:type plan_name: str
"""
# delete files from plan
for data in self.swiftclient.get_container(plan_name)[1]:
self.swiftclient.delete_object(plan_name, data['name'])
# delete plan container
self.swiftclient.delete_container(plan_name)
def delete_file(self, plan_name, filepath):
"""Deletes a file for a given filepath from a plan container
:param plan_name: The name of the plan
:type plan_name: str
:param filepath: The path of the file to be deleted
"""
self.swiftclient.delete_object(plan_name, filepath)
def get(self, plan_name):
"""Retrieves the files for a given container name
Retrieves the files from the Swift container matching plan_name.
:param plan_name: The name of the plan
:type plan_name: str
:return: a list of files
:rtype list
"""
plan = Plan(plan_name)
container = self.swiftclient.get_container(plan_name)
plan.metadata = container[0]
for data in container[1]:
filename = data['name']
plan_obj = self.swiftclient.get_object(plan_name, filename)
plan.files[filename] = {}
plan.files[filename]['contents'] = plan_obj[1]
meta_info = {k: v for (k, v) in plan_obj[0].items()
if constants.OBJECT_META_KEY_PREFIX in k}
if len(meta_info) > 0:
plan.files[filename]['meta'] = \
meta.remove_key_prefix(meta_info)
return plan
def list(self):
"""Gets a list of containers that store plans
Gets a list of containers that contain metadata with the key of
X-Container-Meta-Usage-Tripleo and value or 'plan'.
:return: a list of strings containing plan names
"""
plan_list = []
for item in self.swiftclient.get_account()[1]:
container = self.swiftclient.get_container(item['name'])[0]
if constants.TRIPLEO_META_USAGE_KEY in container.keys():
plan_list.append(item['name'])
return plan_list
def update(self, plan_name, plan_files):
"""Updates a plan by updating the files in container
Updates a plan by updating the files in the Swift container
matching plan_name.
:param plan_name: The name of the plan
:type plan_name: str
:param plan_files: names and contents of files to store
:type plan_files: dict
"""
for filename, details in plan_files.items():
custom_headers = {}
if 'meta' in details:
custom_headers = meta.add_key_prefix(details['meta'])
self.swiftclient.put_object(
plan_name,
filename,
details['contents'],
headers=custom_headers
)

View File

@ -1,3 +1,6 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# -*- coding: utf-8 -*-
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -11,6 +14,64 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import sys
import six
from six import reraise as raise_
from tripleo_common.i18n import _
from tripleo_common.i18n import _LE
_FATAL_EXCEPTION_FORMAT_ERRORS = False
LOG = logging.getLogger(__name__)
@six.python_2_unicode_compatible
class TripleoCommonException(Exception):
"""Base Tripleo-Common Exception.
To correctly use this class, inherit from it and define a 'msg_fmt'
property. That msg_fmt will get printf'd with the keyword arguments
provided to the constructor.
"""
message = _("An unknown exception occurred.")
def __init__(self, **kwargs):
self.kwargs = kwargs
try:
self.message = self.msg_fmt % kwargs
except KeyError:
exc_info = sys.exc_info()
# kwargs doesn't match a variable in the message
# log the issue and the kwargs
LOG.exception(_LE('Exception in string format operation'))
for name, value in six.iteritems(kwargs):
LOG.error(_LE("%(name)s: %(value)s"),
{'name': name, 'value': value}) # noqa
if _FATAL_EXCEPTION_FORMAT_ERRORS:
raise_(exc_info[0], exc_info[1], exc_info[2])
def __str__(self):
return self.message
def __deepcopy__(self, memo):
return self.__class__(**self.kwargs)
class StackInUseError(TripleoCommonException):
msg_fmt = _("Cannot delete a plan that has an associated stack.")
class ContainerAlreadyExistsError(TripleoCommonException):
msg_fmt = _("A container with the name %(name)s already exists.")
class HeatValidationFailedError(TripleoCommonException):
msg_fmt = _("The plan failed to validate via the Heat service. %(msg)s")
class InvalidNode(ValueError):

View File

@ -15,7 +15,7 @@
import mock
from tripleo_common.actions import plan
from tripleo_common.core import exception
from tripleo_common import exception
from tripleo_common.tests import base
MAPPING_YAML_CONTENTS = """root_template: /path/to/overcloud.yaml

View File

@ -1,70 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import datetime
import time
import six
import yaml
from tripleo_common.core.models import Plan
from tripleo_common.tests import base
class ModelTest(base.TestCase):
def setUp(self):
super(ModelTest, self).setUp()
self.timestamp = time.time()
def test_plan(self):
plan = Plan('overcloud')
plan.metadata = {
'x-container-meta-usage-tripleo': 'plan',
'accept-ranges': 'bytes',
'x-storage-policy': 'Policy-0',
'connection': 'keep-alive',
'x-timestamp': self.timestamp,
'x-trans-id': 'tx1f41a9d34a2a437d8f8dd-00565dd486',
'content-type': 'application/json; charset=utf-8',
'x-versions-location': 'versions'
}
plan.files = {
'some-name.yaml': {
'contents': "some fake contents",
'meta': {'file-type': 'environment'}
},
}
expected_date = datetime.datetime.fromtimestamp(
float(self.timestamp))
self.assertEqual(expected_date, plan.created_date(), "Date mismatch")
def test_eq(self):
self.assertEqual(Plan('foo'), Plan('foo'))
self.assertNotEqual(Plan('bar'), Plan('foo'))
self.assertNotEqual(Plan('bar'), None)
class thing(object):
pass
self.assertNotEqual(Plan('bar'), thing())
def test_repr(self):
plan = Plan('foo')
plan_str = six.text_type(plan)
self.assertEqual({'Plan': {
'files': {}, 'name': 'foo', 'metadata': {}
}}, yaml.safe_load(plan_str))

View File

@ -1,375 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import mock
from heatclient import exc as heatexceptions
from swiftclient import exceptions as swiftexceptions
from tripleo_common.core import exception
from tripleo_common.core import models
from tripleo_common.core import plan
from tripleo_common.tests import base
class PlanManagerTest(base.TestCase):
def setUp(self):
super(PlanManagerTest, self).setUp()
self.heatclient = mock.MagicMock()
self.plan_store = mock.MagicMock()
self.plan_name = "overcloud"
self.stack = mock.MagicMock(
id='123',
status='CREATE_COMPLETE',
stack_name=self.plan_name
)
self.expected_plan = models.Plan(self.plan_name)
self.expected_plan.metadata = {
'x-container-meta-usage-tripleo': 'plan',
}
self.expected_plan.files = {
'some-environment.yaml': {
'contents': "some fake contents",
'meta': {'file-type': 'environment'}
},
'some-root-environment.yaml': {
'contents': "parameters:\n"
" one: uno\n"
" obj:\n"
" two: due\n"
" three: tre\n",
'meta': {
'file-type': 'root-environment',
'enabled': 'True'
}
},
'some-root-template.yaml': {
'contents': "some fake contents",
'meta': {'file-type': 'root-template'}
},
'some-template.yaml': {
'contents': "some fake contents",
},
}
def test_create_plan(self):
self.plan_store.create = mock.MagicMock()
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
plan_mgr.create_plan(self.plan_name, self.expected_plan.files)
self.plan_store.create.assert_called_with(self.plan_name)
# calls the Exception handling in create_plan
with mock.patch('tripleo_common.core.plan.LOG') as log_mock:
self.plan_store.create = mock.Mock(side_effect=ValueError())
self.assertRaises(ValueError,
plan_mgr.create_plan,
self.plan_name, self.expected_plan.files)
log_mock.exception.assert_called_with("Error creating plan.")
def test_delete_plan(self):
# test that stack exists
self.heatclient.stacks.get = mock.MagicMock(return_value=self.stack)
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
self.assertRaises(exception.StackInUseError,
plan_mgr.delete_plan,
self.plan_name)
self.heatclient.stacks.get.assert_called_with(self.plan_name)
# test that stack doesn't exist yet
self.plan_store.delete = mock.MagicMock()
self.heatclient.stacks.get = mock.Mock(
side_effect=heatexceptions.HTTPNotFound)
plan_mgr.delete_plan(self.plan_name)
self.plan_store.delete.assert_called_with(self.plan_name)
# set side effect of swiftexceptions.ClientException
with mock.patch('tripleo_common.core.plan.LOG') as log_mock:
self.plan_store.delete = mock.Mock(
side_effect=swiftexceptions.ClientException(
"test-error", http_status=404))
self.assertRaises(exception.PlanDoesNotExistError,
plan_mgr.delete_plan,
self.plan_name)
log_mock.exception.assert_called_with('Swift error deleting plan.')
# set side effect of random Exception
self.heatclient.stacks.get = mock.Mock(
side_effect=ValueError())
self.assertRaises(ValueError,
plan_mgr.delete_plan,
self.plan_name)
def test_delete_files(self):
self.plan_store.delete_file = mock.MagicMock()
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
plan_mgr.delete_file(self.plan_name, 'fake-file.yaml')
self.plan_store.delete_file.assert_called_with(
self.plan_name, 'fake-file.yaml')
self.plan_store.delete_file = mock.Mock(
side_effect=exception.FileDoesNotExistError(name='fake-file.yaml'))
self.assertRaises(exception.FileDoesNotExistError,
plan_mgr.delete_file, self.plan_name,
'fake-file.yaml')
with mock.patch('tripleo_common.core.plan.LOG') as log_mock:
self.plan_store.delete_file = mock.Mock(side_effect=ValueError())
self.assertRaises(ValueError, plan_mgr.delete_file,
self.plan_name, 'fake-file.yaml')
log_mock.exception.assert_called_with(
"Error deleting file from plan.")
def test_delete_temporary_environment(self):
self.expected_plan.files = {
'some-name.yaml': {
'contents': "some fake contents",
'meta': {'file-type': 'temp-environment'}
},
}
self.plan_store.get = mock.MagicMock(return_value=self.expected_plan)
self.plan_store.delete_file = mock.MagicMock()
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
plan_mgr.delete_temporary_environment(self.plan_name)
self.plan_store.delete_file.assert_called_with(
self.plan_name, 'some-name.yaml')
def test_get_plan(self):
self.expected_plan.files = {
'some-name.yaml': {
'contents': "some fake contents",
'meta': {'file-type': 'environment'}
},
}
self.plan_store.get = mock.MagicMock(return_value=self.expected_plan)
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
self.assertEqual(self.expected_plan,
plan_mgr.get_plan(self.plan_name),
"Plan mismatch")
self.plan_store.get.assert_called_with(self.plan_name)
with mock.patch('tripleo_common.core.plan.LOG') as log_mock:
# test swift container doesn't exist
self.plan_store.get = mock.Mock(
side_effect=swiftexceptions.ClientException(
"test-error", http_status=404))
self.assertRaises(exception.PlanDoesNotExistError,
plan_mgr.get_plan,
self.plan_name)
log_mock.exception.assert_called_with(
'Swift error retrieving plan.')
# test other exception occurs
self.plan_store.get = mock.Mock(side_effect=ValueError())
self.assertRaises(ValueError, plan_mgr.get_plan, 'overcloud')
log_mock.exception.assert_called_with("Error retrieving plan.")
def test_get_plan_list(self):
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
self.plan_store.list = mock.MagicMock(return_value=['overcloud'])
self.assertEqual(['overcloud'], plan_mgr.get_plan_list(),
"get_plan_list failed")
with mock.patch('tripleo_common.core.plan.LOG') as log_mock:
self.plan_store.list = mock.Mock(side_effect=ValueError())
self.assertRaises(ValueError, plan_mgr.get_plan_list)
log_mock.exception.assert_called_with(
"Error retrieving plan list.")
def test_get_deployment_parameters(self):
self.plan_store.get = mock.MagicMock(return_value=self.expected_plan)
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
with mock.patch('tripleo_common.utils.templates') as templates:
templates.process_plan_data.return_value = (
"some fake contents", {
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
}, {'some-template.yaml': 'some fake contents'})
self.heatclient.stacks.validate = mock.MagicMock(
return_value={
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
})
self.assertEqual({
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
},
plan_mgr.get_deployment_parameters(self.plan_name),
"Bad params")
self.heatclient.stacks.validate.assert_called_with(
template="some fake contents",
files={'some-template.yaml': 'some fake contents'},
environment={
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
},
show_nested=True
)
# set side effect of heatexceptions.HTTPBadRequest on validate
self.heatclient.stacks.validate = mock.Mock(
side_effect=heatexceptions.HTTPBadRequest
)
self.assertRaises(exception.HeatValidationFailedError,
plan_mgr.get_deployment_parameters,
self.plan_name)
def test_update_deployment_parameters(self):
self.plan_store.get = mock.MagicMock(return_value=self.expected_plan)
# calls templates.process_plan_data(plan.files)
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
self.expected_plan.files['environments/deployment_parameters.yaml'] = {
'contents':
"parameters:\n"
" one: uno\n"
" obj:\n"
" two: due\n"
" three: tre\n",
'meta': {'file-type': 'temp-environment'}
}
with mock.patch('tripleo_common.utils.templates') as templates:
templates.process_plan_data.return_value = (
"some fake contents", {
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
}, {'some-template.yaml': 'some fake contents'})
self.heatclient.stacks.validate = mock.MagicMock()
plan_mgr.validate_plan(self.plan_name)
self.heatclient.stacks.validate.assert_called_with(
template="some fake contents",
files={'some-template.yaml': 'some fake contents'},
environment={
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
},
show_nested=True
)
# set side effect of heatexceptions.HTTPBadRequest on validate
self.heatclient.stacks.validate = mock.Mock(
side_effect=heatexceptions.HTTPBadRequest
)
self.assertRaises(exception.HeatValidationFailedError,
plan_mgr.get_deployment_parameters,
self.plan_name)
def test_update_plan(self):
self.plan_store.update = mock.MagicMock()
self.plan_store.get = mock.MagicMock(return_value=self.expected_plan)
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
self.assertEqual(self.expected_plan,
plan_mgr.update_plan(
self.plan_name, self.expected_plan.files),
"Plan mismatch")
self.plan_store.get.assert_called_with(self.plan_name)
with mock.patch('tripleo_common.core.plan.LOG') as log_mock:
# test swift container doesn't exist
self.plan_store.update = mock.Mock(
side_effect=swiftexceptions.ClientException(
"test-error", http_status=404))
self.assertRaises(exception.PlanDoesNotExistError,
plan_mgr.update_plan,
self.plan_name,
self.expected_plan.files)
log_mock.exception.assert_called_with(
'Swift error updating plan.')
# test other exception occurs
self.plan_store.update = mock.Mock(side_effect=ValueError())
self.assertRaises(ValueError, plan_mgr.update_plan,
self.plan_name, self.expected_plan.files)
log_mock.exception.assert_called_with("Error updating plan.")
def test_validate_plan(self):
# calls self.get_plan(plan_name)
self.plan_store.get = mock.MagicMock(return_value=self.expected_plan)
# test 2 root-templates to get exception.TooManyRootTemplatesError
self.expected_plan.files['another-root-template.yaml'] = {
'contents': "some fake contents",
'meta': {'file-type': 'root-template'}
}
plan_mgr = plan.PlanManager(self.plan_store, self.heatclient)
self.assertRaises(exception.TooManyRootTemplatesError,
plan_mgr.validate_plan,
self.plan_name)
del(self.expected_plan.files['another-root-template.yaml'])
# calls templates.process_plan_data(plan.files) (mock and assert_call)
with mock.patch('tripleo_common.utils.templates') as templates:
templates.process_plan_data = mock.MagicMock(return_value=(
"some fake contents", {
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
}, {'some-template.yaml': 'some fake contents'}))
self.heatclient.stacks.validate = mock.MagicMock()
plan_mgr.validate_plan(self.plan_name)
self.heatclient.stacks.validate.assert_called_with(
template="some fake contents",
files={'some-template.yaml': 'some fake contents'},
environment={
'parameters': {
'obj': {
'two': 'due',
'three': 'tre'
},
'one': 'uno'
}
},
show_nested=True
)
# set side effect of heatexceptions.HTTPBadRequest on validate
self.heatclient.stacks.validate = mock.Mock(
side_effect=heatexceptions.HTTPBadRequest
)
with mock.patch('tripleo_common.core.plan.LOG') as log_mock:
self.assertRaises(exception.HeatValidationFailedError,
plan_mgr.validate_plan,
self.plan_name)
log_mock.exception.assert_called_with(
"Error validating the plan.")

View File

@ -1,194 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import mock
from tripleo_common.core import exception
from tripleo_common.core.models import Plan
from tripleo_common.core.plan_storage import default_container_headers
from tripleo_common.core.plan_storage import SwiftPlanStorageBackend
from tripleo_common.tests import base
PLAN_DATA = {
'/path/to/overcloud.yaml': {
'contents': "heat_template_version: 2015-04-30\n\n"
"resources:\n"
"\n"
" HorizonSecret:\n"
" type: OS::Heat::RandomString\n"
" properties:\n"
" length: 10\n"
"\n"
" Controller:\n"
" type: OS::Heat::ResourceGroup\n"
" depends_on: Networks\n"
" properties:\n"
" count: {get_param: ControllerCount}\n",
'meta': {'file-type': 'root-template'},
},
'/path/to/environment.yaml': {
'contents': "parameters:\n"
" one: uno\n"
" obj:\n"
" two: due\n"
" three: tre\n",
'meta': {'file-type': 'root-environment'},
},
'/path/to/network-isolation.json': {
'contents': '{"parameters": {"one": "one"}}',
'meta': {'file-type': 'environment', 'order': 1},
},
'/path/to/ceph-storage-env.yaml': {
'contents': "parameters:\n"
" obj:\n"
" two: dos,\n"
" three: three",
'meta': {'file-type': 'environment', 'order': 2},
},
'/path/to/poc-custom-env.yaml': {
'contents': "parameters:\n"
" obj:\n"
" two: two\n"
" some::resource: /path/to/somefile.yaml",
'meta': {'file-type': 'environment', 'order': 0}
},
'/path/to/somefile.yaml': {'contents': "description: lorem ipsum"}
}
class PlanStorageTest(base.TestCase):
def setUp(self):
super(PlanStorageTest, self).setUp()
self.swiftclient = mock.MagicMock()
self.plan_store = SwiftPlanStorageBackend(self.swiftclient)
self.plan_name = "overcloud"
def test_create(self):
# create a plan
self.plan_store.list = mock.MagicMock(return_value=['test1', 'test2'])
self.swiftclient.put_container = mock.MagicMock()
self.plan_store.create(self.plan_name)
self.swiftclient.put_container.assert_called_with(
self.plan_name,
headers=default_container_headers
)
# attempt to create a 2nd plan should fail
self.plan_store.list = mock.MagicMock(return_value=['overcloud'])
self.assertRaisesRegexp(exception.ContainerAlreadyExistsError,
self.plan_name,
self.plan_store.create,
self.plan_name)
def test_delete(self):
self.swiftclient.get_container = mock.MagicMock(
return_value=({}, [
{'name': 'some-name.yaml'},
{'name': 'some-other-name.yaml'},
{'name': 'yet-some-other-name.yaml'},
{'name': 'finally-another-name.yaml'}
])
)
self.swiftclient.delete_object = mock.MagicMock()
self.plan_store.delete(self.plan_name)
mock_calls = [
mock.call('overcloud', 'some-name.yaml'),
mock.call('overcloud', 'some-other-name.yaml'),
mock.call('overcloud', 'yet-some-other-name.yaml'),
mock.call('overcloud', 'finally-another-name.yaml')
]
self.swiftclient.delete_object.assert_has_calls(
mock_calls, any_order=True)
def test_delete_file(self):
self.swiftclient.delete_object = mock.MagicMock()
filepath = '/a/random/path/to/file.yaml'
self.plan_store.delete_file(self.plan_name, filepath)
self.swiftclient.delete_object.assert_called_with(
self.plan_name, filepath)
def test_get(self):
metadata = {
'x-container-meta-usage-tripleo': 'plan',
'accept-ranges': 'bytes',
'x-storage-policy': 'Policy-0',
'connection': 'keep-alive',
'x-timestamp': '1447161410.72641',
'x-trans-id': 'tx1f41a9d34a2a437d8f8dd-00565dd486',
'content-type': 'application/json; charset=utf-8',
'x-versions-location': 'versions'
}
expected_plan = Plan(self.plan_name)
expected_plan.metadata = metadata
expected_plan.files = {
'some-name.yaml': {
'contents': "some fake contents",
'meta': {'file-type': 'environment'}
},
}
self.swiftclient.get_container = mock.MagicMock(return_value=(
metadata, [
{'name': 'some-name.yaml'},
])
)
self.swiftclient.get_object = mock.MagicMock(return_value=(
{'x-object-meta-file-type': 'environment'}, "some fake contents"
))
self.assertEqual(expected_plan.name,
self.plan_store.get(self.plan_name).name)
self.swiftclient.get_container.assert_called_with(self.plan_name)
self.swiftclient.get_object.assert_called_with(
'overcloud', 'some-name.yaml')
def test_list(self):
self.swiftclient.get_account = mock.MagicMock(
return_value=({}, [
{
'count': 1,
'bytes': 55,
'name': 'overcloud'
},
])
)
self.swiftclient.get_container = mock.MagicMock(
return_value=({
'x-container-meta-usage-tripleo': 'plan',
}, [])
)
self.assertEqual(['overcloud'], self.plan_store.list())
self.swiftclient.get_container.assert_called_with('overcloud')
def test_update(self):
expected_plan = Plan(self.plan_name)
expected_plan.metadata = {
'x-container-meta-usage-tripleo': 'plan',
'accept-ranges': 'bytes',
'x-storage-policy': 'Policy-0',
}
expected_plan.files = {
'some-name.yaml': {
'contents': "some fake contents",
'meta': {'file-type': 'environment'}
},
}
self.swiftclient.put_object = mock.MagicMock()
self.plan_store.update(self.plan_name, expected_plan.files)
self.swiftclient.put_object.assert_called_with(
self.plan_name,
'some-name.yaml',
"some fake contents",
headers={'x-object-meta-file-type': 'environment'}
)

View File

@ -1,165 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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 tripleo_common.core import exception
from tripleo_common.tests import base
from tripleo_common.utils.meta import add_file_metadata
MAPPING_YAML_CONTENTS = """root_template: /path/to/overcloud.yaml
root_environment: /path/to/environment.yaml
topics:
- title: Fake Single Environment Group Configuration
description:
environment_groups:
- title:
description: Random fake string of text
environments:
- file: /path/to/network-isolation.json
title: Default Configuration
description:
- title: Fake Multiple Environment Group Configuration
description:
environment_groups:
- title: Random Fake 1
description: Random fake string of text
environments:
- file: /path/to/ceph-storage-env.yaml
title: Fake1
description: Random fake string of text
- title: Random Fake 2
description:
environments:
- file: /path/to/poc-custom-env.yaml
title: Fake2
description:
"""
PLAN_DATA = {
'/path/to/overcloud.yaml': {
'contents': 'heat_template_version: 2015-04-30',
'meta': {'file-type': 'root-template'},
},
'/path/to/environment.yaml': {
'contents': "parameters:\n"
" one: uno\n"
" obj:\n"
" two: due\n"
" three: tre\n",
'meta': {'file-type': 'root-environment', 'enabled': 'True'},
},
'/path/to/network-isolation.json': {
'contents': '{"parameters": {"one": "one"}}',
'meta': {'file-type': 'environment'},
},
'/path/to/ceph-storage-env.yaml': {
'contents': "parameters:\n"
" obj:\n"
" two: dos,\n"
" three: three",
'meta': {'file-type': 'environment'},
},
'/path/to/poc-custom-env.yaml': {
'contents': "parameters:\n"
" obj:\n"
" two: two\n"
" some::resource: /path/to/somefile.yaml",
'meta': {'file-type': 'environment'}
},
'/path/to/somefile.yaml': {'contents': "description: lorem ipsum"},
'capabilities-map.yaml': {
'contents': MAPPING_YAML_CONTENTS,
'meta': {'file-type': 'capabilities-map'},
},
}
PLAN_DATA_NO_META = {
'/path/to/overcloud.yaml': {
'contents': 'heat_template_version: 2015-04-30',
},
'/path/to/environment.yaml': {
'contents': "parameters:\n"
" one: uno\n"
" obj:\n"
" two: due\n"
" three: tre\n",
},
'/path/to/network-isolation.json': {
'contents': '{"parameters": {"one": "one"}}',
},
'/path/to/ceph-storage-env.yaml': {
'contents': "parameters:\n"
" obj:\n"
" two: dos,\n"
" three: three",
},
'/path/to/poc-custom-env.yaml': {
'contents': "parameters:\n"
" obj:\n"
" two: two\n"
" some::resource: /path/to/somefile.yaml",
},
'/path/to/somefile.yaml': {'contents': "description: lorem ipsum"},
'capabilities-map.yaml': {
'contents': MAPPING_YAML_CONTENTS,
'meta': {'file-type': 'capabilities-map'},
},
}
class UtilsMetaTest(base.TestCase):
def test_add_file_metadata(self):
# tests case where files have no metadata yet
plan_files_with_metadata = add_file_metadata(PLAN_DATA_NO_META)
self.assertEqual(
PLAN_DATA,
plan_files_with_metadata,
"Metadata not added properly"
)
# tests case where files already have a metadata dict per file
for k, v in PLAN_DATA.items():
if 'meta' in v:
v.update({'enabled': 'True'})
else:
v['meta'] = {'enabled': 'True'}
for k, v in PLAN_DATA_NO_META.items():
if 'meta' in v:
v.update({'enabled': 'True'})
else:
v['meta'] = {'enabled': 'True'}
plan_files_with_metadata = add_file_metadata(PLAN_DATA_NO_META)
self.assertEqual(
PLAN_DATA,
plan_files_with_metadata,
"Metadata not added properly"
)
# test to ensure having more than one capabilities-map file
# results in an exception
PLAN_DATA_NO_META.update({
'capabilities-map2.yaml': {
'contents': MAPPING_YAML_CONTENTS,
'meta': {'file-type': 'capabilities-map'}
}
})
self.assertRaises(exception.TooManyCapabilitiesMapFilesError,
add_file_metadata,
PLAN_DATA_NO_META)

View File

@ -61,34 +61,6 @@ class UtilsTemplatesTest(base.TestCase):
def setUp(self):
super(UtilsTemplatesTest, self).setUp()
self.tpl, self.env, self.files = templates.process_plan_data(PLAN_DATA)
print(self.files)
def test_find_root_template(self):
# delete the root_template from sample data
del PLAN_DATA['/path/to/overcloud.yaml']
# without root, should return {}
self.assertEqual({}, templates.find_root_template(PLAN_DATA))
# add root_template back to sample data
root_template = {
'/path/to/overcloud.yaml': {
'contents': 'heat_template_version: 2015-04-30',
'meta': {'file-type': 'root-template'}}
}
PLAN_DATA.update(root_template)
self.assertEqual(root_template,
templates.find_root_template(PLAN_DATA))
def test_template_found(self):
self.assertEqual(self.tpl, 'heat_template_version: 2015-04-30')
def test_files_found(self):
self.assertEqual(self.files, {
'/path/to/somefile.yaml': 'description: lorem ipsum',
})
@mock.patch("requests.request")
def test_preprocess_templates(self, mock_request):

View File

@ -1,85 +0,0 @@
# Copyright 2015 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import yaml
from tripleo_common.core import constants
from tripleo_common.core import exception
def add_key_prefix(source):
result = dict()
for keyname, value in source.items():
new_keyname = "%s%s" % (constants.OBJECT_META_KEY_PREFIX, keyname)
result[new_keyname] = value
return result
def remove_key_prefix(source):
result = dict()
for keyname, value in source.items():
new_keyname = keyname.replace(constants.OBJECT_META_KEY_PREFIX, '')
result[new_keyname] = value
return result
def add_file_metadata(plan_files):
cm = {k: v for (k, v) in plan_files.items()
if v.get('meta', {}).get('file-type') == 'capabilities-map'}
# if there is more than one capabilities-map file, throw an exception
# if there is a capabilities-map file, then process it and set metadata
# in files found
if len(cm) > 1:
raise exception.TooManyCapabilitiesMapFilesError()
if len(cm) == 1:
mapfile = yaml.load(list(cm.items())[0][1]['contents'])
# identify the root template
if mapfile['root_template']:
if plan_files[mapfile['root_template']]:
# if the file exists in the plan and has meta, update it
# otherwise add meta dict
if 'meta' in plan_files[mapfile['root_template']]:
plan_files[mapfile['root_template']]['meta'].update(
dict(constants.ROOT_TEMPLATE_META)
)
else:
plan_files[mapfile['root_template']]['meta'] =\
dict(constants.ROOT_TEMPLATE_META)
# identify all environments
for topic in mapfile['topics']:
for eg in topic['environment_groups']:
for env in eg['environments']:
if 'meta' in plan_files[env['file']]:
plan_files[env['file']]['meta'].update(
dict(constants.ENVIRONMENT_META)
)
else:
plan_files[env['file']]['meta'] =\
dict(constants.ENVIRONMENT_META)
# identify the root environment
if mapfile['root_environment']:
if plan_files[mapfile['root_environment']]:
# if the file exists in the plan and has meta, update it
# otherwise add meta dict
if 'meta' in plan_files[mapfile['root_environment']]:
plan_files[mapfile['root_environment']]['meta'].update(
dict(constants.ROOT_ENVIRONMENT_META)
)
else:
plan_files[mapfile['root_environment']]['meta'] =\
dict(constants.ROOT_ENVIRONMENT_META)
return plan_files

View File

@ -48,54 +48,6 @@ def deep_update(base, new):
return base
def process_plan_data(plan_data):
"""Preprocesses and organizes plan files for heatclient interaction
This method separates the root template, environments and other
associated files in preparation to send to heatclient for validation
or deployment. The environment files are merged with the temporary
environment information stored in the deployment parameters.
:param plan_data: the files stored in a plan
:return: template, merged environment and associated files
"""
template = ''
environment = {}
env_items = []
temp_env_items = []
files = {}
for key, val in plan_data.items():
file_type = val.get('meta', {}).get('file-type')
enabled = val.get('meta', {}).get('enabled')
if not file_type:
files[key] = val['contents']
elif file_type == 'environment' and enabled:
env_items.append({'name': key,
'meta': val['meta'],
'contents': val['contents']})
elif file_type == 'temp-environment':
temp_env_items.append({'name': key,
'meta': val['meta'],
'contents': val['contents']})
elif file_type == 'root-template':
template = val['contents']
elif file_type == 'root-environment' and enabled:
environment = _get_dict_from_env_string(key, val['contents'])
# merge environment files
for item in env_items:
env_dict = _get_dict_from_env_string(item['name'], item['contents'])
environment = deep_update(environment, env_dict)
# merge the temporary environment files last
for item in temp_env_items:
env_dict = _get_dict_from_env_string(item['name'], item['contents'])
environment = deep_update(environment, env_dict)
return template, environment, files
def preprocess_templates(swift_base_url, container_name, template,
environments, auth_token):
"""Pre-processes and organizes plan files
@ -168,8 +120,3 @@ def preprocess_templates(swift_base_url, container_name, template,
'environment': env,
'files': files
}
def find_root_template(plan_files):
return {k: v for (k, v) in plan_files.items()
if v.get('meta', {}).get('file-type') == 'root-template'}