Deprecate load_json() in favor of load()

The Rules.load_json function now supports loading YAML and is not
limited to JSON. As such, the name is changed to load(). The old
name remains but is deprecated.

bp policy-yaml
Change-Id: I8c71d1a566779f1641106a996ebbc9551e2f05e3
This commit is contained in:
Brant Knudson 2016-02-15 13:35:53 -06:00
parent 83d209e9ed
commit ea1268bcd3
4 changed files with 38 additions and 13 deletions

View File

@ -217,6 +217,7 @@ desired rule name.
import logging import logging
import os import os
import warnings
from oslo_config import cfg from oslo_config import cfg
from oslo_serialization import jsonutils from oslo_serialization import jsonutils
@ -299,8 +300,12 @@ class Rules(dict):
"""A store for rules. Handles the default_rule setting directly.""" """A store for rules. Handles the default_rule setting directly."""
@classmethod @classmethod
def load_json(cls, data, default_rule=None): def load(cls, data, default_rule=None):
"""Allow loading of YAML/JSON rule data.""" """Allow loading of YAML/JSON rule data.
.. versionadded:: 1.5.0
"""
try: try:
parsed = yaml.safe_load(data) parsed = yaml.safe_load(data)
@ -314,6 +319,21 @@ class Rules(dict):
return cls(rules, default_rule) return cls(rules, default_rule)
@classmethod
def load_json(cls, data, default_rule=None):
"""Allow loading of YAML/JSON rule data.
.. warning::
This method is deprecated as of the 1.5.0 release in favor of
:meth:`load` and may be removed in the 2.0 release.
"""
warnings.warn(
'The load_json() method is deprecated as of the 1.5.0 release in '
'favor of load() and may be removed in the 2.0 release.',
DeprecationWarning)
return cls.load(data, default_rule)
@classmethod @classmethod
def from_dict(cls, rules_dict, default_rule=None): def from_dict(cls, rules_dict, default_rule=None):
"""Allow loading of rule data from a dictionary.""" """Allow loading of rule data from a dictionary."""
@ -494,7 +514,7 @@ class Enforcer(object):
reloaded, data = _cache_handler.read_cached_file( reloaded, data = _cache_handler.read_cached_file(
self._file_cache, path, force_reload=force_reload) self._file_cache, path, force_reload=force_reload)
if reloaded or not self.rules: if reloaded or not self.rules:
rules = Rules.load_json(data, self.default_rule) rules = Rules.load(data, self.default_rule)
self.set_rules(rules, overwrite=overwrite, use_conf=True) self.set_rules(rules, overwrite=overwrite, use_conf=True)
self._loaded_files.append(path) self._loaded_files.append(path)
LOG.debug('Reloaded policy file: %(path)s', {'path': path}) LOG.debug('Reloaded policy file: %(path)s', {'path': path})

View File

@ -40,7 +40,7 @@ def tool(policy_file, access_file, apply_rule, is_admin=False):
access_data['project_id'] = access_data['project']['id'] access_data['project_id'] = access_data['project']['id']
access_data['is_admin'] = is_admin access_data['is_admin'] = is_admin
policy_data = policy_file.read() policy_data = policy_file.read()
rules = policy.Rules.load_json(policy_data, "default") rules = policy.Rules.load(policy_data, "default")
class Object(object): class Object(object):
pass pass

View File

@ -30,7 +30,7 @@ class FixtureTestCase(test_base.PolicyBaseTestCase):
rules_json = { rules_json = {
action: "http:" + self.getUniqueString() action: "http:" + self.getUniqueString()
} }
rules = oslo_policy.Rules.load_json(json.dumps(rules_json)) rules = oslo_policy.Rules.load(json.dumps(rules_json))
self.enforcer.set_rules(rules) self.enforcer.set_rules(rules)
return self.enforcer.enforce(rule=action, return self.enforcer.enforce(rule=action,
target={}, target={},

View File

@ -87,7 +87,7 @@ class RulesTestCase(test_base.BaseTestCase):
"admin_or_owner": [["role:admin"], ["project_id:%(project_id)s"]], "admin_or_owner": [["role:admin"], ["project_id:%(project_id)s"]],
"default": [] "default": []
}) })
rules = policy.Rules.load_json(exemplar, 'default') rules = policy.Rules.load(exemplar, 'default')
self.assertEqual('default', rules.default_rule) self.assertEqual('default', rules.default_rule)
self.assertEqual(dict( self.assertEqual(dict(
@ -103,12 +103,12 @@ class RulesTestCase(test_base.BaseTestCase):
"admin_or_owner": [["role:admin"], ["project_id:%(project_id)s"]], "admin_or_owner": [["role:admin"], ["project_id:%(project_id)s"]],
"default": [ "default": [
}""" }"""
self.assertRaises(ValueError, policy.Rules.load_json, exemplar, self.assertRaises(ValueError, policy.Rules.load, exemplar,
'default') 'default')
@mock.patch.object(_parser, 'parse_rule', lambda x: x) @mock.patch.object(_parser, 'parse_rule', lambda x: x)
def test_load_yaml(self): def test_load_yaml(self):
# Test that simplified YAML can be used with load_json. # Test that simplified YAML can be used with load().
# Show that YAML allows useful comments. # Show that YAML allows useful comments.
exemplar = """ exemplar = """
# Define a custom rule. # Define a custom rule.
@ -116,7 +116,7 @@ admin_or_owner: role:admin or project_id:%(project_id)s
# The default rule is used when there's no action defined. # The default rule is used when there's no action defined.
default: [] default: []
""" """
rules = policy.Rules.load_json(exemplar, 'default') rules = policy.Rules.load(exemplar, 'default')
self.assertEqual('default', rules.default_rule) self.assertEqual('default', rules.default_rule)
self.assertEqual(dict( self.assertEqual(dict(
@ -126,7 +126,7 @@ default: []
@mock.patch.object(_parser, 'parse_rule', lambda x: x) @mock.patch.object(_parser, 'parse_rule', lambda x: x)
def test_load_yaml_invalid_exc(self): def test_load_yaml_invalid_exc(self):
# When the JSON isn't valid, ValueError is raised on load_json. # When the JSON isn't valid, ValueError is raised on load().
# Note the trailing , in the exemplar is invalid JSON. # Note the trailing , in the exemplar is invalid JSON.
exemplar = """{ exemplar = """{
# Define a custom rule. # Define a custom rule.
@ -134,7 +134,7 @@ admin_or_owner: role:admin or project_id:%(project_id)s
# The default rule is used when there's no action defined. # The default rule is used when there's no action defined.
default: [ default: [
}""" }"""
self.assertRaises(ValueError, policy.Rules.load_json, exemplar, self.assertRaises(ValueError, policy.Rules.load, exemplar,
'default') 'default')
@mock.patch.object(_parser, 'parse_rule', lambda x: x) @mock.patch.object(_parser, 'parse_rule', lambda x: x)
@ -165,6 +165,11 @@ default: [
self.assertEqual(exemplar, str(rules)) self.assertEqual(exemplar, str(rules))
def test_load_json_deprecated(self):
with self.assertWarnsRegex(DeprecationWarning,
r'load_json\(\).*load\(\)'):
policy.Rules.load_json(jsonutils.dumps({'default': ''}, 'default'))
class EnforcerTest(base.PolicyBaseTestCase): class EnforcerTest(base.PolicyBaseTestCase):
@ -311,7 +316,7 @@ class EnforcerTest(base.PolicyBaseTestCase):
"deny_stack_user": "not role:stack_user", "deny_stack_user": "not role:stack_user",
"cloudwatch:PutMetricData": "" "cloudwatch:PutMetricData": ""
}) })
rules = policy.Rules.load_json(rules_json) rules = policy.Rules.load(rules_json)
self.enforcer.set_rules(rules) self.enforcer.set_rules(rules)
action = 'cloudwatch:PutMetricData' action = 'cloudwatch:PutMetricData'
creds = {'roles': ''} creds = {'roles': ''}
@ -322,7 +327,7 @@ class EnforcerTest(base.PolicyBaseTestCase):
"deny_stack_user": "not role:stack_user", "deny_stack_user": "not role:stack_user",
"cloudwatch:PutMetricData": "" "cloudwatch:PutMetricData": ""
}) })
rules = policy.Rules.load_json(rules_json) rules = policy.Rules.load(rules_json)
default_rule = _checks.TrueCheck() default_rule = _checks.TrueCheck()
enforcer = policy.Enforcer(self.conf, default_rule=default_rule) enforcer = policy.Enforcer(self.conf, default_rule=default_rule)
enforcer.set_rules(rules) enforcer.set_rules(rules)