| import io |
| import json |
| import logging |
| import sys |
| |
| LOG = logging.getLogger(__name__) |
| |
| import yaml |
| import yaml.constructor |
| |
| try: |
| # included in standard lib from Python 2.7 |
| from collections import OrderedDict |
| except ImportError: |
| # try importing the backported drop-in replacement |
| # it's available on PyPI |
| from ordereddict import OrderedDict |
| |
| # https://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts |
| class OrderedDictYAMLLoader(yaml.Loader): |
| """ |
| A YAML loader that loads mappings into ordered dictionaries. |
| """ |
| |
| def __init__(self, *args, **kwargs): |
| yaml.Loader.__init__(self, *args, **kwargs) |
| |
| self.add_constructor(u'tag:yaml.org,2002:map', type(self).construct_yaml_map) |
| self.add_constructor(u'tag:yaml.org,2002:omap', type(self).construct_yaml_map) |
| |
| def construct_yaml_map(self, node): |
| data = OrderedDict() |
| yield data |
| value = self.construct_mapping(node) |
| data.update(value) |
| |
| def construct_mapping(self, node, deep=False): |
| if isinstance(node, yaml.MappingNode): |
| self.flatten_mapping(node) |
| else: |
| raise yaml.constructor.ConstructorError(None, None, |
| 'expected a mapping node, but found %s' % node.id, node.start_mark) |
| |
| mapping = OrderedDict() |
| for key_node, value_node in node.value: |
| key = self.construct_object(key_node, deep=deep) |
| try: |
| hash(key) |
| except TypeError as exc: |
| raise yaml.constructor.ConstructorError('while constructing a mapping', |
| node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark) |
| value = self.construct_object(value_node, deep=deep) |
| mapping[key] = value |
| return mapping |
| |
| |
| def __virtual__(): |
| return True |
| |
| |
| def rule_list(path, **kwargs): |
| try: |
| with io.open(path, 'r') as file_handle: |
| rules = yaml.load(file_handle, OrderedDictYAMLLoader) or OrderedDict() |
| except Exception as e: |
| msg = "Unable to load policy file %s: %s" % (path, repr(e)) |
| LOG.debug(msg) |
| rules = {'Error': msg} |
| return rules |
| |
| |
| def rule_delete(name, path, **kwargs): |
| ret = {} |
| rules = __salt__['keystone_policy.rule_list'](path, **kwargs) |
| if 'Error' not in rules: |
| if name not in rules: |
| return ret |
| del rules[name] |
| try: |
| with io.open(path, 'w') as file_handle: |
| if path.endswith('json'): |
| serialized = json.dumps(rules, indent=4) |
| else: |
| serialized = yaml.safe_dump(rules, indent=4) |
| if sys.version_info[0] >= 3: |
| file_handle.write(serialized) |
| else: |
| file_handle.write(unicode(serialized)) |
| except Exception as e: |
| msg = "Unable to save policy file: %s" % repr(e) |
| LOG.error(msg) |
| return {'Error': msg} |
| ret = 'Rule {0} deleted'.format(name) |
| return ret |
| |
| |
| def rule_set(name, rule, path, **kwargs): |
| rules = __salt__['keystone_policy.rule_list'](path, **kwargs) |
| if 'Error' not in rules: |
| if name in rules and rules[name] == rule: |
| return {name: 'Rule %s already exists and is in correct state' % name} |
| rules.update({name: rule}) |
| try: |
| with io.open(path, 'w') as file_handle: |
| if path.endswith('json'): |
| serialized = json.dumps(rules, indent=4) |
| else: |
| serialized = yaml.safe_dump(rules, indent=4) |
| if sys.version_info[0] >= 3: |
| file_handle.write(serialized) |
| else: |
| file_handle.write(unicode(serialized)) |
| except Exception as e: |
| msg = "Unable to save policy file %s: %s" % (path, repr(e)) |
| LOG.error(msg) |
| return {'Error': msg} |
| return rule_get(name, path, **kwargs) |
| return rules |
| |
| |
| def rule_get(name, path, **kwargs): |
| ret = {} |
| rules = __salt__['keystone_policy.rule_list'](path, **kwargs) |
| if 'Error' in rules: |
| ret['Error'] = rules['Error'] |
| elif name in rules: |
| ret[name] = rules.get(name) |
| |
| return ret |
| |