Parse stack_adopt_data

The patch parses the argument passed to stack_create, and validates that
it's a dictionary, preventing engine failures in the future.

Closes-Bug: #1277106
Change-Id: I88cbf933ddac5776d5ffc0151bc7a0b296048777
This commit is contained in:
Thomas Herve 2014-02-06 15:59:15 +01:00
parent b54558569b
commit b7fa93a03c
3 changed files with 33 additions and 14 deletions

View File

@ -51,16 +51,7 @@ yaml_loader.add_constructor(u'tag:yaml.org,2002:timestamp',
_construct_yaml_str)
def parse(tmpl_str):
'''
Takes a string and returns a dict containing the parsed structure.
This includes determination of whether the string is using the
JSON or YAML format.
'''
if len(tmpl_str) > cfg.CONF.max_template_size:
msg = (_('Template exceeds maximum allowed size (%s bytes)') %
cfg.CONF.max_template_size)
raise exception.RequestLimitExceeded(message=msg)
def simple_parse(tmpl_str):
try:
tpl = json.loads(tmpl_str)
except ValueError:
@ -71,6 +62,20 @@ def parse(tmpl_str):
else:
if tpl is None:
tpl = {}
return tpl
def parse(tmpl_str):
'''
Takes a string and returns a dict containing the parsed structure.
This includes determination of whether the string is using the
JSON or YAML format.
'''
if len(tmpl_str) > cfg.CONF.max_template_size:
msg = (_('Template exceeds maximum allowed size (%s bytes)') %
cfg.CONF.max_template_size)
raise exception.RequestLimitExceeded(message=msg)
tpl = simple_parse(tmpl_str)
if not isinstance(tpl, dict):
raise ValueError(_('The template is not a JSON object '
'or YAML mapping.'))

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from heat.common import template_format
from heat.rpc import api
from heat.openstack.common import timeutils
from heat.engine import constraints as constr
@ -49,9 +50,14 @@ def extract_args(params):
dict(name=api.PARAM_DISABLE_ROLLBACK,
value=disable_rollback))
if api.PARAM_ADOPT_STACK_DATA in params:
kwargs[api.PARAM_ADOPT_STACK_DATA] = params.get(
api.PARAM_ADOPT_STACK_DATA)
adopt_data = params.get(api.PARAM_ADOPT_STACK_DATA)
if adopt_data:
adopt_data = template_format.simple_parse(adopt_data)
if not isinstance(adopt_data, dict):
raise ValueError(
_('Unexpected adopt data "%s". Adopt data must be a dict.')
% adopt_data)
kwargs[api.PARAM_ADOPT_STACK_DATA] = adopt_data
return kwargs

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import json
import mock
import uuid
@ -55,10 +56,17 @@ class EngineApiTest(HeatTestCase):
self.assertNotIn('timeout_mins', args)
def test_adopt_stack_data_extract_present(self):
p = {'adopt_stack_data': {'Resources': {}}}
p = {'adopt_stack_data': json.dumps({'Resources': {}})}
args = api.extract_args(p)
self.assertTrue(args.get('adopt_stack_data'))
def test_invalid_adopt_stack_data(self):
p = {'adopt_stack_data': json.dumps("foo")}
error = self.assertRaises(ValueError, api.extract_args, p)
self.assertEqual(
'Unexpected adopt data "foo". Adopt data must be a dict.',
str(error))
def test_adopt_stack_data_extract_not_present(self):
args = api.extract_args({})
self.assertNotIn('adopt_stack_data', args)