blob: 2e79f224daa01c975d0ca4d5ab078903e2e5f6cb [file] [log] [blame]
Adam Tenglerb1ebaca2017-05-04 21:06:08 +00001import io
2import json
3import logging
4
Petr Michalec073067a2017-10-27 15:37:46 +02005LOG = logging.getLogger(__name__)
Alexey Stupnikove124c3b2017-10-19 19:58:09 +03006
Kirill Bespalov4fe0d082017-06-29 19:02:13 +03007import yaml
Petr Michalec073067a2017-10-27 15:37:46 +02008import yaml.constructor
Kirill Bespalov4fe0d082017-06-29 19:02:13 +03009
Petr Michalec073067a2017-10-27 15:37:46 +020010try:
11 # included in standard lib from Python 2.7
12 from collections import OrderedDict
13except ImportError:
14 # try importing the backported drop-in replacement
15 # it's available on PyPI
16 from ordereddict import OrderedDict
17
18# https://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts
19class OrderedDictYAMLLoader(yaml.Loader):
20 """
21 A YAML loader that loads mappings into ordered dictionaries.
22 """
23
24 def __init__(self, *args, **kwargs):
25 yaml.Loader.__init__(self, *args, **kwargs)
26
27 self.add_constructor(u'tag:yaml.org,2002:map', type(self).construct_yaml_map)
28 self.add_constructor(u'tag:yaml.org,2002:omap', type(self).construct_yaml_map)
29
30 def construct_yaml_map(self, node):
31 data = OrderedDict()
32 yield data
33 value = self.construct_mapping(node)
34 data.update(value)
35
36 def construct_mapping(self, node, deep=False):
37 if isinstance(node, yaml.MappingNode):
38 self.flatten_mapping(node)
39 else:
40 raise yaml.constructor.ConstructorError(None, None,
41 'expected a mapping node, but found %s' % node.id, node.start_mark)
42
43 mapping = OrderedDict()
44 for key_node, value_node in node.value:
45 key = self.construct_object(key_node, deep=deep)
46 try:
47 hash(key)
48 except TypeError, exc:
49 raise yaml.constructor.ConstructorError('while constructing a mapping',
50 node.start_mark, 'found unacceptable key (%s)' % exc, key_node.start_mark)
51 value = self.construct_object(value_node, deep=deep)
52 mapping[key] = value
53 return mapping
Adam Tenglerb1ebaca2017-05-04 21:06:08 +000054
55
56def __virtual__():
57 return True
58
59
60def rule_list(path, **kwargs):
61 try:
62 with io.open(path, 'r') as file_handle:
Petr Michalec073067a2017-10-27 15:37:46 +020063 rules = yaml.load(file_handle, OrderedDictYAMLLoader) or OrderedDict()
Adam Tenglerb1ebaca2017-05-04 21:06:08 +000064 except Exception as e:
Kirill Bespalov4fe0d082017-06-29 19:02:13 +030065 msg = "Unable to load policy file %s: %s" % (path, repr(e))
Adam Tenglerb1ebaca2017-05-04 21:06:08 +000066 LOG.debug(msg)
67 rules = {'Error': msg}
68 return rules
69
70
71def rule_delete(name, path, **kwargs):
72 ret = {}
73 rules = __salt__['keystone_policy.rule_list'](path, **kwargs)
74 if 'Error' not in rules:
75 if name not in rules:
76 return ret
77 del rules[name]
78 try:
79 with io.open(path, 'w') as file_handle:
Kirill Bespalov4fe0d082017-06-29 19:02:13 +030080 if path.endswith('json'):
81 serialized = json.dumps(rules, indent=4)
82 else:
83 serialized = yaml.safe_dump(rules, indent=4)
84 file_handle.write(unicode(serialized))
Adam Tenglerb1ebaca2017-05-04 21:06:08 +000085 except Exception as e:
Kirill Bespalov4fe0d082017-06-29 19:02:13 +030086 msg = "Unable to save policy file: %s" % repr(e)
Adam Tenglerb1ebaca2017-05-04 21:06:08 +000087 LOG.error(msg)
88 return {'Error': msg}
89 ret = 'Rule {0} deleted'.format(name)
90 return ret
91
92
93def rule_set(name, rule, path, **kwargs):
94 rules = __salt__['keystone_policy.rule_list'](path, **kwargs)
95 if 'Error' not in rules:
96 if name in rules and rules[name] == rule:
97 return {name: 'Rule %s already exists and is in correct state' % name}
98 rules.update({name: rule})
99 try:
100 with io.open(path, 'w') as file_handle:
Kirill Bespalov4fe0d082017-06-29 19:02:13 +0300101 if path.endswith('json'):
102 serialized = json.dumps(rules, indent=4)
103 else:
104 serialized = yaml.safe_dump(rules, indent=4)
105 file_handle.write(unicode(serialized))
Adam Tenglerb1ebaca2017-05-04 21:06:08 +0000106 except Exception as e:
Kirill Bespalov4fe0d082017-06-29 19:02:13 +0300107 msg = "Unable to save policy file %s: %s" % (path, repr(e))
Adam Tenglerb1ebaca2017-05-04 21:06:08 +0000108 LOG.error(msg)
109 return {'Error': msg}
110 return rule_get(name, path, **kwargs)
111 return rules
112
113
114def rule_get(name, path, **kwargs):
115 ret = {}
116 rules = __salt__['keystone_policy.rule_list'](path, **kwargs)
117 if 'Error' in rules:
118 ret['Error'] = rules['Error']
119 elif name in rules:
120 ret[name] = rules.get(name)
121
122 return ret
123