Merge "Move merge_environment to environment_util module"

This commit is contained in:
Jenkins 2016-08-24 13:11:54 +00:00 committed by Gerrit Code Review
commit 39f43109e0
7 changed files with 100 additions and 81 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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)

View File

@ -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',

View File

@ -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)

View File

@ -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']