Add policy-upgrade tool

Add a new "oslopolicy-policy-upgrade" commnd. Using this command,
operator can upgrade their self-defined policy files to follow
the new format in the new release when upgrading OpenStack services.

Change-Id: Iad9740bd8a5e4fdf1d1e64d61bc93f2483c531f3
This commit is contained in:
wangxiyuan 2018-10-29 20:00:19 +08:00
parent b9fd10e261
commit ab28b32ee9
4 changed files with 160 additions and 0 deletions

View File

@ -14,8 +14,10 @@ import logging
import sys
import textwrap
import warnings
import yaml
from oslo_config import cfg
from oslo_serialization import jsonutils
import stevedore
from oslo_policy import policy
@ -45,6 +47,12 @@ ENFORCER_OPTS = [
'which to look for a policy.Enforcer.'),
]
UPGRADE_OPTS = [
cfg.StrOpt('policy',
required=True,
help='Path to the policy file which need to be updated.')
]
def get_policies_dict(namespaces):
"""Find the options available via the given namespaces.
@ -330,6 +338,48 @@ def generate_policy(args=None):
_generate_policy(conf.namespace, conf.output_file)
def _upgrade_policies(policies, default_policies):
old_policies_keys = list(policies.keys())
for section in sorted(default_policies.keys()):
rule_defaults = default_policies[section]
for rule_default in rule_defaults:
if (rule_default.deprecated_rule and
rule_default.deprecated_rule.name in old_policies_keys):
policies[rule_default.name] = policies.pop(
rule_default.deprecated_rule.name)
LOG.info('The name of policy %(old_name)s has been upgraded to'
'%(new_name)',
{'old_name': rule_default.deprecated_rule.name,
'new_name': rule_default.name})
def upgrade_policy(args=None):
logging.basicConfig(level=logging.WARN)
conf = cfg.ConfigOpts()
conf.register_cli_opts(GENERATOR_OPTS + RULE_OPTS + UPGRADE_OPTS)
conf.register_opts(GENERATOR_OPTS + RULE_OPTS + UPGRADE_OPTS)
conf(args)
with open(conf.policy, 'r') as input_data:
policies = policy.parse_file_contents(input_data.read())
default_policies = get_policies_dict(conf.namespace)
_upgrade_policies(policies, default_policies)
if conf.output_file:
if conf.format == 'yaml':
yaml.safe_dump(policies, open(conf.output_file, 'w'),
default_flow_style=False)
elif conf.format == 'json':
jsonutils.dump(policies, open(conf.output_file, 'w'),
indent=4)
else:
if conf.format == 'yaml':
sys.stdout.write(yaml.safe_dump(policies,
default_flow_style=False))
elif conf.format == 'json':
sys.stdout.write(jsonutils.dumps(policies, indent=4))
def list_redundant(args=None):
logging.basicConfig(level=logging.WARN)
conf = cfg.ConfigOpts()

View File

@ -16,10 +16,12 @@ import mock
from oslo_config import cfg
import stevedore
import testtools
import yaml
from oslo_policy import generator
from oslo_policy import policy
from oslo_policy.tests import base
from oslo_serialization import jsonutils
OPTS = {'base_rules': [policy.RuleDefault('admin', 'is_admin:True',
@ -572,3 +574,104 @@ class ListRedundantTestCase(base.PolicyBaseTestCase):
opt1 = matches[1]
self.assertEqual('"owner"', opt1[0])
self.assertEqual('"project_id:%(project_id)s"', opt1[1])
class UpgradePolicyTestCase(base.PolicyBaseTestCase):
def setUp(self):
super(UpgradePolicyTestCase, self).setUp()
policy_json_contents = jsonutils.dumps({
"deprecated_name": "rule:admin"
})
self.create_config_file('policy.json', policy_json_contents)
deprecated_policy = policy.DeprecatedRule(
name='deprecated_name',
check_str='rule:admin'
)
self.new_policy = policy.DocumentedRuleDefault(
name='new_policy_name',
check_str='rule:admin',
description='test_policy',
operations=[{'path': '/test', 'method': 'GET'}],
deprecated_rule=deprecated_policy,
deprecated_reason='test',
deprecated_since='Stein'
)
self.extensions = []
ext = stevedore.extension.Extension(name='test_upgrade',
entry_point=None,
plugin=None,
obj=[self.new_policy])
self.extensions.append(ext)
def test_upgrade_policy_json_file(self):
test_mgr = stevedore.named.NamedExtensionManager.make_test_instance(
extensions=self.extensions, namespace='test_upgrade')
with mock.patch('stevedore.named.NamedExtensionManager',
return_value=test_mgr):
testargs = ['olsopolicy-policy-upgrade',
'--policy',
self.get_config_file_fullname('policy.json'),
'--namespace', 'test_upgrade',
'--output-file',
self.get_config_file_fullname('new_policy.json'),
'--format', 'json']
with mock.patch('sys.argv', testargs):
generator.upgrade_policy()
new_file = self.get_config_file_fullname('new_policy.json')
new_policy = jsonutils.loads(open(new_file, 'r').read())
self.assertIsNotNone(new_policy.get('new_policy_name'))
self.assertIsNone(new_policy.get('deprecated_name'))
def test_upgrade_policy_yaml_file(self):
test_mgr = stevedore.named.NamedExtensionManager.make_test_instance(
extensions=self.extensions, namespace='test_upgrade')
with mock.patch('stevedore.named.NamedExtensionManager',
return_value=test_mgr):
testargs = ['olsopolicy-policy-upgrade',
'--policy',
self.get_config_file_fullname('policy.json'),
'--namespace', 'test_upgrade',
'--output-file',
self.get_config_file_fullname('new_policy.yaml'),
'--format', 'yaml']
with mock.patch('sys.argv', testargs):
generator.upgrade_policy()
new_file = self.get_config_file_fullname('new_policy.yaml')
new_policy = yaml.safe_load(open(new_file, 'r'))
self.assertIsNotNone(new_policy.get('new_policy_name'))
self.assertIsNone(new_policy.get('deprecated_name'))
def test_upgrade_policy_json_stdout(self):
test_mgr = stevedore.named.NamedExtensionManager.make_test_instance(
extensions=self.extensions, namespace='test_upgrade')
stdout = self._capture_stdout()
with mock.patch('stevedore.named.NamedExtensionManager',
return_value=test_mgr):
testargs = ['olsopolicy-policy-upgrade',
'--policy',
self.get_config_file_fullname('policy.json'),
'--namespace', 'test_upgrade',
'--format', 'json']
with mock.patch('sys.argv', testargs):
generator.upgrade_policy()
expected = '''{
"new_policy_name": "rule:admin"
}'''
self.assertEqual(expected, stdout.getvalue())
def test_upgrade_policy_yaml_stdout(self):
test_mgr = stevedore.named.NamedExtensionManager.make_test_instance(
extensions=self.extensions, namespace='test_upgrade')
stdout = self._capture_stdout()
with mock.patch('stevedore.named.NamedExtensionManager',
return_value=test_mgr):
testargs = ['olsopolicy-policy-upgrade',
'--policy',
self.get_config_file_fullname('policy.json'),
'--namespace', 'test_upgrade',
'--format', 'yaml']
with mock.patch('sys.argv', testargs):
generator.upgrade_policy()
expected = '''new_policy_name: rule:admin
'''
self.assertEqual(expected, stdout.getvalue())

View File

@ -0,0 +1,6 @@
---
features:
- |
Add ``oslopolicy-policy-upgrade`` command to help operators upgrade their
self-defined policy file to new release format. It will upgrade the
deprected policy name with the new name.

View File

@ -38,6 +38,7 @@ console_scripts =
oslopolicy-sample-generator = oslo_policy.generator:generate_sample
oslopolicy-policy-generator = oslo_policy.generator:generate_policy
oslopolicy-list-redundant = oslo_policy.generator:list_redundant
oslopolicy-policy-upgrade = oslo_policy.generator:upgrade_policy
oslo.policy.rule_checks =
http = oslo_policy._external:HttpCheck