diff --git a/config.yaml b/config.yaml index 56c53c09..322e07f5 100644 --- a/config.yaml +++ b/config.yaml @@ -121,10 +121,16 @@ options: # Keystone integration operator-roles: type: string - default: "Member,Admin" + default: "Member" description: | Comma-separated list of Swift operator roles; used when integrating with OpenStack Keystone. + admin-roles: + type: string + default: "Admin" + description: | + Comma-separated list of Swift admin roles; used when integrating with + OpenStack Keystone. Admin roles can set the user quota amount. region: type: string default: RegionOne diff --git a/hooks/ceph_radosgw_context.py b/hooks/ceph_radosgw_context.py index 7e4fed8c..54b73822 100644 --- a/hooks/ceph_radosgw_context.py +++ b/hooks/ceph_radosgw_context.py @@ -96,7 +96,13 @@ class IdentityServiceContext(context.IdentityServiceContext): ctxt.pop('admin_domain_id') ctxt['auth_type'] = 'keystone' - ctxt['user_roles'] = config('operator-roles') + if cmp_pkgrevno('radosgw', "11.0.0") >= 0: + ctxt['user_roles'] = config('operator-roles') + ctxt['admin_roles'] = config('admin-roles') + else: + ctxt['user_roles'] = config('operator-roles') + if config('admin-roles'): + ctxt['user_roles'] += (',' + config('admin-roles')) ctxt['cache_size'] = config('cache-size') if self.context_complete(ctxt): return ctxt diff --git a/hooks/hooks.py b/hooks/hooks.py index 7db0e240..8debca8f 100755 --- a/hooks/hooks.py +++ b/hooks/hooks.py @@ -298,11 +298,15 @@ def identity_joined(relid=None): (canonical_url(CONFIGS, INTERNAL), port) public_url = '%s:%s/swift/v1' % \ (canonical_url(CONFIGS, PUBLIC), port) + roles = [x for x in [config('operator-roles'), config('admin-roles')] if x] + requested_roles = '' + if roles: + requested_roles = ','.join(roles) if len(roles) > 1 else roles[0] relation_set(service='swift', region=config('region'), public_url=public_url, internal_url=internal_url, admin_url=admin_url, - requested_roles=config('operator-roles'), + requested_roles=requested_roles, relation_id=relid) diff --git a/templates/ceph.conf b/templates/ceph.conf index db55dd4e..c1ea349d 100644 --- a/templates/ceph.conf +++ b/templates/ceph.conf @@ -51,6 +51,7 @@ rgw keystone admin project = {{ admin_tenant_name }} rgw keystone admin token = {{ admin_token }} {% endif -%} rgw keystone accepted roles = {{ user_roles }} +rgw keystone accepted admin roles = {{ admin_roles }} rgw keystone token cache size = {{ cache_size }} rgw s3 auth use keystone = true rgw s3 auth order = local, external diff --git a/unit_tests/test_ceph_radosgw_context.py b/unit_tests/test_ceph_radosgw_context.py index f1c80a56..1ba768f2 100644 --- a/unit_tests/test_ceph_radosgw_context.py +++ b/unit_tests/test_ceph_radosgw_context.py @@ -85,8 +85,12 @@ class IdentityServiceContextTest(CharmTestCase): @patch.object(charmhelpers.contrib.openstack.context, 'log') def test_ids_ctxt(self, _log, _rids, _runits, _rget, _ctxt_comp, _format_ipv6_addr, _filter_installed_packages, - jewel_installed=False): + jewel_installed=False, cmp_pkgrevno_side_effects=None): + self.cmp_pkgrevno.side_effect = (cmp_pkgrevno_side_effects + if cmp_pkgrevno_side_effects + else [-1, -1]) self.test_config.set('operator-roles', 'Babel') + self.test_config.set('admin-roles', 'Dart') self.test_config.set('cache-size', '42') self.test_relation.set({'admin_token': 'ubuntutesting'}) self.relation_ids.return_value = ['identity-service:5'] @@ -95,9 +99,6 @@ class IdentityServiceContextTest(CharmTestCase): _rids.return_value = 'rid1' _runits.return_value = 'runit' _ctxt_comp.return_value = True - self.cmp_pkgrevno.return_value = -1 - if jewel_installed: - self.cmp_pkgrevno.return_value = 0 id_data = { 'service_port': 9876, 'service_host': '127.0.0.4', @@ -127,8 +128,12 @@ class IdentityServiceContextTest(CharmTestCase): 'service_host': '127.0.0.4', 'service_port': 9876, 'service_protocol': 'http', - 'user_roles': 'Babel', } + if cmp_pkgrevno_side_effects and cmp_pkgrevno_side_effects[1] >= 0: + expect['user_roles'] = 'Babel' + expect['admin_roles'] = 'Dart' + else: + expect['user_roles'] = 'Babel,Dart' if jewel_installed: expect['auth_keystone_v3_supported'] = True self.assertEqual(expect, ids_ctxt()) @@ -145,6 +150,7 @@ class IdentityServiceContextTest(CharmTestCase): self, _log, _rids, _runits, _rget, _ctxt_comp, _format_ipv6_addr, _filter_installed_packages, jewel_installed=False): self.test_config.set('operator-roles', 'Babel') + self.test_config.set('admin-roles', 'Dart') self.test_config.set('cache-size', '42') self.test_relation.set({'admin_token': 'ubuntutesting'}) self.relation_ids.return_value = ['identity-service:5'] @@ -183,7 +189,7 @@ class IdentityServiceContextTest(CharmTestCase): 'service_host': '127.0.0.4', 'service_port': 9876, 'service_protocol': 'http', - 'user_roles': 'Babel', + 'user_roles': 'Babel,Dart', } if jewel_installed: expect['auth_keystone_v3_supported'] = True @@ -201,6 +207,7 @@ class IdentityServiceContextTest(CharmTestCase): self, _log, _rids, _runits, _rget, _ctxt_comp, _format_ipv6_addr, _filter_installed_packages, jewel_installed=False): self.test_config.set('operator-roles', 'Babel') + self.test_config.set('admin-roles', 'Dart') self.test_config.set('cache-size', '42') self.test_relation.set({'admin_token': 'ubuntutesting'}) self.relation_ids.return_value = ['identity-service:5'] @@ -244,14 +251,19 @@ class IdentityServiceContextTest(CharmTestCase): 'service_host': '127.0.0.4', 'service_port': 9876, 'service_protocol': 'http', - 'user_roles': 'Babel', + 'user_roles': 'Babel,Dart', } if jewel_installed: expect['auth_keystone_v3_supported'] = True self.assertEqual(expect, ids_ctxt()) def test_ids_ctxt_jewel(self): - self.test_ids_ctxt(jewel_installed=True) + self.test_ids_ctxt(jewel_installed=True, + cmp_pkgrevno_side_effects=[0, -1]) + + def test_ids_ctxt_luminous(self): + self.test_ids_ctxt(jewel_installed=True, + cmp_pkgrevno_side_effects=[1, 0]) @patch.object(charmhelpers.contrib.openstack.context, 'filter_installed_packages', return_value=['absent-pkg']) diff --git a/unit_tests/test_hooks.py b/unit_tests/test_hooks.py index cc046b83..45207e7c 100644 --- a/unit_tests/test_hooks.py +++ b/unit_tests/test_hooks.py @@ -244,21 +244,31 @@ class CephRadosGWTests(CharmTestCase): @patch('charmhelpers.contrib.openstack.ip.resolve_address') @patch('charmhelpers.contrib.openstack.ip.config') def test_identity_joined(self, _config, _resolve_address): - self.related_units = ['unit/0'] - self.cmp_pkgrevno.return_value = 1 - _resolve_address.return_value = 'myserv' - _config.side_effect = self.test_config.get - self.test_config.set('region', 'region1') - self.test_config.set('operator-roles', 'admin') - ceph_hooks.identity_joined(relid='rid') - self.relation_set.assert_called_with( - service='swift', - region='region1', - public_url='http://myserv:80/swift/v1', - internal_url='http://myserv:80/swift/v1', - requested_roles='admin', - relation_id='rid', - admin_url='http://myserv:80/swift') + + def _test_identify_joined(expected): + self.related_units = ['unit/0'] + self.cmp_pkgrevno.return_value = 1 + _resolve_address.return_value = 'myserv' + _config.side_effect = self.test_config.get + self.test_config.set('region', 'region1') + ceph_hooks.identity_joined(relid='rid') + self.relation_set.assert_called_with( + service='swift', + region='region1', + public_url='http://myserv:80/swift/v1', + internal_url='http://myserv:80/swift/v1', + requested_roles=expected, + relation_id='rid', + admin_url='http://myserv:80/swift') + + inputs = [{'operator': 'foo', 'admin': 'bar', 'expected': 'foo,bar'}, + {'operator': 'foo', 'expected': 'foo'}, + {'admin': 'bar', 'expected': 'bar'}, + {'expected': ''}] + for input in inputs: + self.test_config.set('operator-roles', input.get('operator', '')) + self.test_config.set('admin-roles', input.get('admin', '')) + _test_identify_joined(input['expected']) @patch('charmhelpers.contrib.openstack.ip.service_name', lambda *args: 'ceph-radosgw')