OpenStack Orchestration (Heat)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
6.2 KiB

# vim: tabstop=4 shiftwidth=4 softtabstop=4
# 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
# 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 collections
import re
import logging
logger = logging.getLogger('heat.engine.checkeddict')
class CheckedDict(collections.MutableMapping):
def __init__(self, name): = {} = name
def addschema(self, key, schema):[key] = schema
def get_attr(self, key, attr):
return[key].get(attr, '')
def __setitem__(self, key, value):
'''Since this function gets called whenever we modify the
dictionary (object), we can (and do) validate those keys that we
know how to validate.
def str_to_num(s):
return int(s)
except ValueError:
return float(s)
num_converter = {'Integer': int,
'Number': str_to_num,
'Float': float}
if not key in
raise KeyError('%s: key %s not found' % (, key))
if 'Type' in[key]:
t =[key]['Type']
if t == 'String':
if not isinstance(value, basestring):
raise ValueError('%s: %s Value must be a string' %
(, key))
if 'MaxLength' in[key]:
if len(value) > int([key]['MaxLength']):
raise ValueError('%s: %s is too long; MaxLength %s' %
(, key,[key]['MaxLength']))
if 'MinLength' in[key]:
if len(value) < int([key]['MinLength']):
raise ValueError('%s: %s is too short; MinLength %s' %
(, key,[key]['MinLength']))
if 'AllowedPattern' in[key]:
rc = re.match('^%s$' %[key]['AllowedPattern'],
if rc is None:
raise ValueError('%s: Pattern %s does not match %s' %
elif t in ['Integer', 'Number', 'Float']:
# just try convert and see if it will throw a ValueError
num = num_converter[t](value)
minn = num
maxn = num
if 'MaxValue' in[key]:
maxn = num_converter[t]([key]['MaxValue'])
if 'MinValue' in[key]:
minn = num_converter[t]([key]['MinValue'])
if num > maxn or num < minn:
raise ValueError('%s: %s is out of range' % (,
elif t == 'Map':
if not isinstance(value, dict):
raise ValueError('%s: %s Value must be a map' %
(, key))
elif t == 'List':
if not isinstance(value, (list, tuple)):
raise ValueError('%s: %s Value must be a list' %
(, key))
elif t == 'CommaDelimitedList':
sp = value.split(',')
logger.warn('Unknown value type "%s"' % t)
if 'AllowedValues' in[key]:
if not value in[key]['AllowedValues']:
raise ValueError('%s: %s Value must be one of %s' %
(, key,
str([key]['AllowedValues'])))[key]['Value'] = value
def __getitem__(self, key):
if not key in
raise KeyError('%s: key %s not found' % (, key))
if 'Value' in[key]:
elif 'Default' in[key]:
elif 'Required' in[key]:
if not[key]['Required']:
return None
raise ValueError('%s: %s must be provided' % (, key))
raise ValueError('%s: %s must be provided' % (, key))
def __len__(self):
return len(
def __contains__(self, key):
return key in
def __iter__(self):
return iter(
def __delitem__(self, k):
class Properties(CheckedDict):
def __init__(self, name, schema):
CheckedDict.__init__(self, name) = schema
# set some defaults
for s in
if not 'Implemented' in[s]:[s]['Implemented'] = True
if not 'Required' in[s]:[s]['Required'] = False
def validate(self):
for key in
# are there missing required Properties
if 'Required' in[key]:
if[key]['Required'] \
and not 'Value' in[key]:
return '%s Property must be provided' % key
# are there unimplemented Properties
if not[key]['Implemented'] and 'Value' in[key]:
return '%s Property not implemented yet' % key
return None