From 2cb23153bdf3e31dd88cd271e650afb11af09d94 Mon Sep 17 00:00:00 2001 From: Feilong Wang Date: Fri, 15 May 2020 16:07:56 +1200 Subject: [PATCH] Support upgrade on behalf of user by admin Unleash the capability that admin user can do rolling upgrade on behalf of the end user so that cloud admin can do urgent security patching when it's really necessary. Task: 39784 Story: 2007675 Change-Id: I8fa9a30ee8252b94baa80e4bbca197b285fb7f71 --- magnum/api/controllers/v1/cluster_actions.py | 5 +++ magnum/common/policies/cluster.py | 12 ++++++ .../controllers/v1/test_cluster_actions.py | 39 ++++++++++++++++++- ...de-on-behalf-of-user-c04994831360f8c1.yaml | 5 +++ 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 releasenotes/notes/support-upgrade-on-behalf-of-user-c04994831360f8c1.yaml diff --git a/magnum/api/controllers/v1/cluster_actions.py b/magnum/api/controllers/v1/cluster_actions.py index e068cca380..abe27068f3 100644 --- a/magnum/api/controllers/v1/cluster_actions.py +++ b/magnum/api/controllers/v1/cluster_actions.py @@ -135,6 +135,11 @@ class ActionsController(base.Controller): :param cluster_ident: UUID of a cluster or logical name of the cluster. """ context = pecan.request.context + if context.is_admin: + policy.enforce(context, "cluster:upgrade_all_projects", + action="cluster:upgrade_all_projects") + context.all_tenants = True + cluster = api_utils.get_resource('Cluster', cluster_ident) policy.enforce(context, 'cluster:upgrade', cluster, action='cluster:upgrade') diff --git a/magnum/common/policies/cluster.py b/magnum/common/policies/cluster.py index bc20e44e47..15b63226b2 100644 --- a/magnum/common/policies/cluster.py +++ b/magnum/common/policies/cluster.py @@ -172,7 +172,19 @@ rules = [ 'method': 'POST' } ] + ), + policy.DocumentedRuleDefault( + name=CLUSTER % 'upgrade_all_projects', + check_str=base.RULE_ADMIN_API, + description='Upgrade an existing cluster across all projects.', + operations=[ + { + 'path': '/v1/clusters/{cluster_ident}/actions/upgrade', + 'method': 'POST' + } + ] ) + ] diff --git a/magnum/tests/unit/api/controllers/v1/test_cluster_actions.py b/magnum/tests/unit/api/controllers/v1/test_cluster_actions.py index 41fdac53e1..8a512ca0e0 100644 --- a/magnum/tests/unit/api/controllers/v1/test_cluster_actions.py +++ b/magnum/tests/unit/api/controllers/v1/test_cluster_actions.py @@ -12,6 +12,9 @@ from unittest import mock +from oslo_utils import uuidutils + +from magnum.common import context as magnum_context from magnum.conductor import api as rpcapi import magnum.conf from magnum.tests.unit.api import base as api_base @@ -143,8 +146,8 @@ class TestClusterUpgrade(api_base.FunctionalTest): project_id=self.cluster_obj.project_id, is_default=False) p = mock.patch.object(rpcapi.API, 'cluster_upgrade') - self.mock_cluster_resize = p.start() - self.mock_cluster_resize.side_effect = self._sim_rpc_cluster_upgrade + self.mock_cluster_upgrade = p.start() + self.mock_cluster_upgrade.side_effect = self._sim_rpc_cluster_upgrade self.addCleanup(p.stop) def _sim_rpc_cluster_upgrade(self, cluster, cluster_template, batch_size, @@ -162,6 +165,38 @@ class TestClusterUpgrade(api_base.FunctionalTest): "container-infra latest"}) self.assertEqual(202, response.status_code) + def test_upgrade_cluster_as_admin(self): + token_info = { + 'token': { + 'project': {'id': 'fake_project_1'}, + 'user': {'id': 'fake_user_1'} + } + } + user_context = magnum_context.RequestContext( + auth_token_info=token_info, + project_id='fake_project_1', + user_id='fake_user_1', + is_admin=False) + cluster_uuid = uuidutils.generate_uuid() + cluster_template_uuid = uuidutils.generate_uuid() + obj_utils.create_test_cluster_template( + user_context, + public=True, uuid=cluster_template_uuid) + obj_utils.create_test_cluster( + user_context, + uuid=cluster_uuid, + cluster_template_id=cluster_template_uuid) + + cluster_upgrade_req = {"cluster_template": "test_2"} + self.context.is_admin = True + response = self.post_json( + '/clusters/%s/actions/upgrade' % + cluster_uuid, + cluster_upgrade_req, + headers={"Openstack-Api-Version": "container-infra latest"}) + + self.assertEqual(202, response.status_int) + def test_upgrade_default_worker(self): cluster_upgrade_req = { "cluster_template": "test_2", diff --git a/releasenotes/notes/support-upgrade-on-behalf-of-user-c04994831360f8c1.yaml b/releasenotes/notes/support-upgrade-on-behalf-of-user-c04994831360f8c1.yaml new file mode 100644 index 0000000000..d3fc72d7ba --- /dev/null +++ b/releasenotes/notes/support-upgrade-on-behalf-of-user-c04994831360f8c1.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Cloud admin user now can do rolling upgrade on behalf of end + user so as to do urgent security patching when it's necessary.