summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrabi <ramishra@redhat.com>2016-08-04 10:10:51 +0530
committerrabi <ramishra@redhat.com>2016-08-22 13:46:34 +0530
commit59b2a559ecf7c9302a1d8bd835ba4ea9380bbc0e (patch)
tree17551f6b849ff1e349e5327e909a37dc9005d19d
parent36a0ad29e53e30528a03577f71b2f6fc396daa05 (diff)
downloadheat-59b2a559ecf7c9302a1d8bd835ba4ea9380bbc0e.tar.gz
Move merge_environment to environment_util module
This moves the merge_environment utility function from service.py to environment_util.py. Change-Id: Ia005cf47d5e655e60359f8da397a712e749ce13c Blueprint: environment-merging
-rw-r--r--heat/common/environment_util.py38
-rw-r--r--heat/engine/service.py35
-rw-r--r--heat/tests/engine/service/test_service_engine.py47
-rw-r--r--heat/tests/engine/service/test_stack_create.py3
-rw-r--r--heat/tests/engine/service/test_stack_update.py5
-rw-r--r--heat/tests/test_common_env_util.py50
-rw-r--r--heat/tests/test_engine_service.py3
7 files changed, 100 insertions, 81 deletions
diff --git a/heat/common/environment_util.py b/heat/common/environment_util.py
index 5ee4f4984..b19a4606d 100644
--- a/heat/common/environment_util.py
+++ b/heat/common/environment_util.py
@@ -10,6 +10,9 @@
# 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 collections
+
+from heat.common import environment_format
ALLOWED_PARAM_MERGE_STRATEGIES = (OVERWRITE, MERGE, DEEP_MERGE) = (
'overwrite', 'merge', 'deep_merge')
@@ -27,3 +30,38 @@ def get_param_merge_strategy(merge_strategies, param_key):
return merge_strategy
return env_default
+
+
+def deep_update(old, new):
+ '''Merge nested dictionaries.'''
+ for k, v in new.items():
+ if isinstance(v, collections.Mapping):
+ r = deep_update(old.get(k, {}), v)
+ old[k] = r
+ else:
+ old[k] = new[k]
+ return old
+
+
+def merge_environments(environment_files, files, params):
+ """Merges environment files into the stack input parameters.
+
+ If a list of environment files have been specified, this call will
+ pull the contents of each from the files dict, parse them as
+ environments, and merge them into the stack input params. This
+ behavior is the same as earlier versions of the Heat client that
+ performed this params population client-side.
+
+ :param environment_files: ordered names of the environment files
+ found in the files dict
+ :type environment_files: list or None
+ :param files: mapping of stack filenames to contents
+ :type files: dict
+ :param params: parameters describing the stack
+ :type dict:
+ """
+ if environment_files:
+ for filename in environment_files:
+ raw_env = files[filename]
+ parsed_env = environment_format.parse(raw_env)
+ deep_update(params, parsed_env)
diff --git a/heat/engine/service.py b/heat/engine/service.py
index 49788d4da..ebe1193d9 100644
--- a/heat/engine/service.py
+++ b/heat/engine/service.py
@@ -33,6 +33,7 @@ import webob
from heat.common import context
from heat.common import environment_format as env_fmt
+from heat.common import environment_util as env_util
from heat.common import exception
from heat.common.i18n import _
from heat.common.i18n import _LE
@@ -69,8 +70,6 @@ from heat.objects import watch_data
from heat.objects import watch_rule
from heat.rpc import api as rpc_api
from heat.rpc import worker_api as rpc_worker_api
-from heatclient.common import environment_format
-from heatclient.common import template_utils
cfg.CONF.import_opt('engine_life_check_timeout', 'heat.common.config')
cfg.CONF.import_opt('max_resources_per_stack', 'heat.common.config')
@@ -680,7 +679,7 @@ class EngineService(service.Service):
tmpl = templatem.Template.load(cnxt, template_id)
env = tmpl.env
else:
- self._merge_environments(environment_files, files, params)
+ env_util.merge_environments(environment_files, files, params)
env = environment.Environment(params)
tmpl = templatem.Template(template, files=files, env=env)
self._validate_new_stack(cnxt, stack_name, tmpl)
@@ -701,30 +700,6 @@ class EngineService(service.Service):
env.registry.log_resource_info(prefix=stack_name)
return stack
- @staticmethod
- def _merge_environments(environment_files, files, params):
- """Merges environment files into the stack input parameters.
-
- If a list of environment files have been specified, this call will
- pull the contents of each from the files dict, parse them as
- environments, and merge them into the stack input params. This
- behavior is the same as earlier versions of the Heat client that
- performed this params population client-side.
-
- :param environment_files: ordered names of the environment files
- found in the files dict
- :type environment_files: list or None
- :param files: mapping of stack filenames to contents
- :type files: dict
- :param params: parameters describing the stack
- :type dict:
- """
- if environment_files:
- for filename in environment_files:
- raw_env = files[filename]
- parsed_env = environment_format.parse(raw_env)
- template_utils.deep_update(params, parsed_env)
-
@context.request_context
def preview_stack(self, cnxt, stack_name, template, params, files,
args, environment_files=None):
@@ -969,7 +944,7 @@ class EngineService(service.Service):
:param template_id: the ID of a pre-stored template in the DB
"""
# Handle server-side environment file resolution
- self._merge_environments(environment_files, files, params)
+ env_util.merge_environments(environment_files, files, params)
# Get the database representation of the existing stack
db_stack = self._get_stack(cnxt, stack_identity)
@@ -1026,7 +1001,7 @@ class EngineService(service.Service):
heat-api process if using a template-url.
"""
# Handle server-side environment file resolution
- self._merge_environments(environment_files, files, params)
+ env_util.merge_environments(environment_files, files, params)
# Get the database representation of the existing stack
db_stack = self._get_stack(cnxt, stack_identity)
@@ -1206,7 +1181,7 @@ class EngineService(service.Service):
service_check_defer = True
- self._merge_environments(environment_files, files, params)
+ env_util.merge_environments(environment_files, files, params)
env = environment.Environment(params)
tmpl = templatem.Template(template, files=files, env=env)
try:
diff --git a/heat/tests/engine/service/test_service_engine.py b/heat/tests/engine/service/test_service_engine.py
index 0aa2d41b3..8fb3226c1 100644
--- a/heat/tests/engine/service/test_service_engine.py
+++ b/heat/tests/engine/service/test_service_engine.py
@@ -411,50 +411,3 @@ class ServiceEngineTest(common.HeatTestCase):
self.eng.start()
self.assertEqual(cfg.CONF.executor_thread_pool_size,
cfg.CONF.database.max_overflow)
-
- def test_merge_environments(self):
- # Setup
- params = {'parameters': {
- 'p0': 'CORRECT',
- 'p1': 'INCORRECT',
- 'p2': 'INCORRECT'}
- }
- env_1 = '''
- {'parameters' : {
- 'p1': 'CORRECT',
- 'p2': 'INCORRECT-ENV-1',
- }}'''
- env_2 = '''
- {'parameters': {
- 'p2': 'CORRECT'
- }}'''
-
- files = {'env_1': env_1, 'env_2': env_2}
- environment_files = ['env_1', 'env_2']
-
- # Test
- self.eng._merge_environments(environment_files, files, params)
-
- # Verify
- expected = {'parameters': {
- 'p0': 'CORRECT',
- 'p1': 'CORRECT',
- 'p2': 'CORRECT',
- }}
- self.assertEqual(expected, params)
-
- def test_merge_environments_no_env_files(self):
- params = {'parameters': {'p0': 'CORRECT'}}
- env_1 = '''
- {'parameters' : {
- 'p0': 'INCORRECT',
- }}'''
-
- files = {'env_1': env_1}
-
- # Test - Should ignore env_1 in files
- self.eng._merge_environments(None, files, params)
-
- # Verify
- expected = {'parameters': {'p0': 'CORRECT'}}
- self.assertEqual(expected, params)
diff --git a/heat/tests/engine/service/test_stack_create.py b/heat/tests/engine/service/test_stack_create.py
index 761b9aea4..0db72f67e 100644
--- a/heat/tests/engine/service/test_stack_create.py
+++ b/heat/tests/engine/service/test_stack_create.py
@@ -16,6 +16,7 @@ from oslo_messaging.rpc import dispatcher
from oslo_service import threadgroup
import six
+from heat.common import environment_util as env_util
from heat.common import exception
from heat.engine.clients.os import glance
from heat.engine.clients.os import nova
@@ -54,7 +55,7 @@ class StackCreateTest(common.HeatTestCase):
mock_env = self.patchobject(environment, 'Environment',
return_value=stk.env)
mock_stack = self.patchobject(stack, 'Stack', return_value=stk)
- mock_merge = self.patchobject(self.man, '_merge_environments')
+ mock_merge = self.patchobject(env_util, 'merge_environments')
result = self.man.create_stack(self.ctx, stack_name,
template, params, None, {},
environment_files=environment_files)
diff --git a/heat/tests/engine/service/test_stack_update.py b/heat/tests/engine/service/test_stack_update.py
index 4b1b70cae..49d736788 100644
--- a/heat/tests/engine/service/test_stack_update.py
+++ b/heat/tests/engine/service/test_stack_update.py
@@ -18,6 +18,7 @@ from oslo_config import cfg
from oslo_messaging.rpc import dispatcher
import six
+from heat.common import environment_util as env_util
from heat.common import exception
from heat.common import messaging
from heat.common import service_utils
@@ -121,7 +122,7 @@ class ServiceStackUpdateTest(common.HeatTestCase):
self.patchobject(eventlet.queue, 'LightQueue',
return_value=mock.Mock())
- mock_merge = self.patchobject(self.man, '_merge_environments')
+ mock_merge = self.patchobject(env_util, 'merge_environments')
# Test
environment_files = ['env_1']
@@ -991,7 +992,7 @@ resources:
mock_env = self.patchobject(environment, 'Environment',
return_value=stk.env)
mock_validate = self.patchobject(stk, 'validate', return_value=None)
- mock_merge = self.patchobject(self.man, '_merge_environments')
+ mock_merge = self.patchobject(env_util, 'merge_environments')
# Patch _resolve_all_attributes or it tries to call novaclient
self.patchobject(resource.Resource, '_resolve_all_attributes',
diff --git a/heat/tests/test_common_env_util.py b/heat/tests/test_common_env_util.py
index bfcb8665e..b8975462d 100644
--- a/heat/tests/test_common_env_util.py
+++ b/heat/tests/test_common_env_util.py
@@ -48,3 +48,53 @@ class TestEnvironmentUtil(common.HeatTestCase):
param_strategy = env_util.get_param_merge_strategy(merge_strategies,
'param1')
self.assertEqual(env_util.OVERWRITE, param_strategy)
+
+
+class TestMergeEnvironments(common.HeatTestCase):
+
+ def test_merge_environments(self):
+ # Setup
+ params = {'parameters': {
+ 'p0': 'CORRECT',
+ 'p1': 'INCORRECT',
+ 'p2': 'INCORRECT'}
+ }
+ env_1 = '''
+ {'parameters' : {
+ 'p1': 'CORRECT',
+ 'p2': 'INCORRECT-ENV-1',
+ }}'''
+ env_2 = '''
+ {'parameters': {
+ 'p2': 'CORRECT'
+ }}'''
+
+ files = {'env_1': env_1, 'env_2': env_2}
+ environment_files = ['env_1', 'env_2']
+
+ # Test
+ env_util.merge_environments(environment_files, files, params)
+
+ # Verify
+ expected = {'parameters': {
+ 'p0': 'CORRECT',
+ 'p1': 'CORRECT',
+ 'p2': 'CORRECT',
+ }}
+ self.assertEqual(expected, params)
+
+ def test_merge_environments_no_env_files(self):
+ params = {'parameters': {'p0': 'CORRECT'}}
+ env_1 = '''
+ {'parameters' : {
+ 'p0': 'INCORRECT',
+ }}'''
+
+ files = {'env_1': env_1}
+
+ # Test - Should ignore env_1 in files
+ env_util.merge_environments(None, files, params)
+
+ # Verify
+ expected = {'parameters': {'p0': 'CORRECT'}}
+ self.assertEqual(expected, params)
diff --git a/heat/tests/test_engine_service.py b/heat/tests/test_engine_service.py
index 60a1bb0ab..d70dfa2f3 100644
--- a/heat/tests/test_engine_service.py
+++ b/heat/tests/test_engine_service.py
@@ -21,6 +21,7 @@ from oslo_serialization import jsonutils as json
import six
from heat.common import context
+from heat.common import environment_util as env_util
from heat.common import exception
from heat.common import identifier
from heat.common import template_format
@@ -1165,7 +1166,7 @@ class StackServiceTest(common.HeatTestCase):
self._preview_stack)
self.assertEqual(exception.StackValidationFailed, ex.exc_info[0])
- @mock.patch.object(service.EngineService, '_merge_environments')
+ @mock.patch.object(env_util, 'merge_environments')
def test_preview_environment_files(self, mock_merge):
# Setup
environment_files = ['env_1']