Skip to content

Commit

Permalink
ccloud: add possibility to set default tag(s)
Browse files Browse the repository at this point in the history
configuration option to set tags that get added to newly created projects

Change-Id: Icac8d54506082816bdaeacb73853a20b49735c16
  • Loading branch information
Carthaca committed Nov 27, 2020
1 parent a289ff5 commit 6fc5179
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 deletions.
12 changes: 12 additions & 0 deletions keystone/conf/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@
will default to using the server's host name.
"""))

default_tag = cfg.MultiStrOpt(
'default_tag',
default=[],
help=utils.fmt("""
Default `tag`(s) for newly created projects. If left undefined, Keystone will
create projects without an initial tag. This field can be set multiple times in
order to set multiple default tags, for example:
default_tag=tag_0
default_tag=tag_1
"""))

notification_format = cfg.StrOpt(
'notification_format',
default='cadf',
Expand Down Expand Up @@ -148,6 +159,7 @@
strict_password_check,
insecure_debug,
default_publisher_id,
default_tag,
notification_format,
notification_opt_out,
]
Expand Down
10 changes: 10 additions & 0 deletions keystone/resource/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ def create_project(self, project_id, project, initiator=None):
project['name'] = project['name'].strip()
project.setdefault('description', '')

# ccloud add default tag(s)
if CONF.default_tag:
default_tags = [x.strip() for x in CONF.default_tag]
if 'tags' in project:
# a user may have provided a tag, which is a default tag, again
# make unique by converting to a set
project['tags'] = list(set(project['tags'] + default_tags))
else:
project['tags'] = default_tags

# For regular projects, the controller will ensure we have a valid
# domain_id. For projects acting as a domain, the project_id
# is, effectively, the domain_id - and for such projects we don't
Expand Down
6 changes: 6 additions & 0 deletions keystone/tests/unit/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ def new_project_ref(domain_id=None, is_domain=False, **kwargs):
return ref


def new_project_without_tags_ref(domain_id=None, is_domain=False, **kwargs):
ref = new_project_ref(domain_id=domain_id, is_domain=is_domain, **kwargs)
ref.pop('tags')
return ref


def new_user_ref(domain_id, project_id=None, **kwargs):
ref = {
'id': uuid.uuid4().hex,
Expand Down
45 changes: 33 additions & 12 deletions keystone/tests/unit/test_v3_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
CONF = keystone.conf.CONF
PROVIDERS = provider_api.ProviderAPIs

_DEFAULT_TAG = ['single_tag']
_DEFAULT_TAGS = [None, [], ['vc-a-0', 'tag_1', 'tag_2'], _DEFAULT_TAG]


class ResourceTestCase(test_v3.RestfulTestCase,
test_v3.AssignmentTestMixin):
Expand Down Expand Up @@ -777,7 +780,7 @@ def _create_projects_hierarchy(self, hierarchy_size=1):

return projects

def _create_project_and_tags(self, num_of_tags=1):
def _create_project_and_tags(self, num_of_tags=1, with_default_tag=False):
"""Create a project and a number of tags attached to that project.
:param num_of_tags: the desired number of tags created with a specified
Expand All @@ -787,9 +790,19 @@ def _create_project_and_tags(self, num_of_tags=1):
random tags
"""
tags = [uuid.uuid4().hex for i in range(num_of_tags)]
ref = unit.new_project_ref(
domain_id=self.domain_id,
tags=tags)

if num_of_tags > 0:
if with_default_tag:
# remove the last tag
tags.pop()
# add default tag instead
tags += _DEFAULT_TAG
ref = unit.new_project_ref(
domain_id=self.domain_id,
tags=tags)
else:
ref = unit.new_project_without_tags_ref(
domain_id=self.domain_id)
resp = self.post('/projects', body={'project': ref})
return resp.result['project'], tags

Expand Down Expand Up @@ -1601,14 +1614,22 @@ def test_delete_not_leaf_project(self):
expected_status=http_client.FORBIDDEN)

def test_create_project_with_tags(self):
project, tags = self._create_project_and_tags(num_of_tags=10)
ref = self.get(
'/projects/%(project_id)s' % {
'project_id': project['id']},
expected_status=http_client.OK)
self.assertIn('tags', ref.result['project'])
for tag in tags:
self.assertIn(tag, ref.result['project']['tags'])
for config_setting in _DEFAULT_TAGS:
if config_setting is not None:
self.config_fixture.config(default_tag=config_setting)
for tag_number in [0, 10]:
project, tags = self._create_project_and_tags(
num_of_tags=tag_number, with_default_tag=True)
ref = self.get(
'/projects/%(project_id)s' % {
'project_id': project['id']},
expected_status=http_client.OK)
self.assertIn('tags', ref.result['project'])
for tag in tags:
self.assertIn(tag, ref.result['project']['tags'])
if config_setting is not None:
for tag in config_setting:
self.assertIn(tag, ref.result['project']['tags'])

def test_update_project_with_tags(self):
project, tags = self._create_project_and_tags(num_of_tags=9)
Expand Down

0 comments on commit 6fc5179

Please sign in to comment.