diff --git a/changelogs/fragments/3248-adds-few-more-gitlab-group-options.yml b/changelogs/fragments/3248-adds-few-more-gitlab-group-options.yml new file mode 100644 index 0000000000..f565fea565 --- /dev/null +++ b/changelogs/fragments/3248-adds-few-more-gitlab-group-options.yml @@ -0,0 +1,2 @@ +minor_changes: + - gitlab_group - add new options ``project_creation_level``, ``auto_devops_enabled``, ``subgroup_creation_level`` (https://github.com/ansible-collections/community.general/pull/3248). diff --git a/plugins/modules/source_control/gitlab/gitlab_group.py b/plugins/modules/source_control/gitlab/gitlab_group.py index 42e1801a81..cdf0f41b65 100644 --- a/plugins/modules/source_control/gitlab/gitlab_group.py +++ b/plugins/modules/source_control/gitlab/gitlab_group.py @@ -61,6 +61,23 @@ options: choices: ["private", "internal", "public"] default: private type: str + project_creation_level: + description: + - Determine if developers can create projects in the group. + choices: ["developer", "maintainer", "noone"] + type: str + version_added: 3.7.0 + auto_devops_enabled: + description: + - Default to Auto DevOps pipeline for all projects within this group. + type: bool + version_added: 3.7.0 + subgroup_creation_level: + description: + - Allowed to create subgroups. + choices: ["maintainer", "owner"] + type: str + version_added: 3.7.0 ''' EXAMPLES = ''' @@ -93,6 +110,20 @@ EXAMPLES = ''' path: my_first_group state: present parent: "super_parent/parent" + +# Other group which only allows sub-groups - no projects +- name: "Create GitLab Group for SubGroups only" + community.general.gitlab_group: + api_url: https://gitlab.example.com/ + validate_certs: True + api_username: dj-wasabi + api_password: "MySecretPassword" + name: my_main_group + path: my_main_group + state: present + project_creation_level: noone + auto_devops_enabled: false + subgroup_creation_level: maintainer ''' RETURN = ''' @@ -166,7 +197,10 @@ class GitLabGroup(object): 'name': name, 'path': options['path'], 'parent_id': parent_id, - 'visibility': options['visibility'] + 'visibility': options['visibility'], + 'project_creation_level': options['project_creation_level'], + 'auto_devops_enabled': options['auto_devops_enabled'], + 'subgroup_creation_level': options['subgroup_creation_level'], } if options.get('description'): payload['description'] = options['description'] @@ -176,7 +210,11 @@ class GitLabGroup(object): changed, group = self.updateGroup(self.groupObject, { 'name': name, 'description': options['description'], - 'visibility': options['visibility']}) + 'visibility': options['visibility'], + 'project_creation_level': options['project_creation_level'], + 'auto_devops_enabled': options['auto_devops_enabled'], + 'subgroup_creation_level': options['subgroup_creation_level'], + }) self.groupObject = group if changed: @@ -258,6 +296,9 @@ def main(): state=dict(type='str', default="present", choices=["absent", "present"]), parent=dict(type='str'), visibility=dict(type='str', default="private", choices=["internal", "private", "public"]), + project_creation_level=dict(type='str', choices=['developer', 'maintainer', 'noone']), + auto_devops_enabled=dict(type='bool'), + subgroup_creation_level=dict(type='str', choices=['maintainer', 'owner']), )) module = AnsibleModule( @@ -281,6 +322,9 @@ def main(): state = module.params['state'] parent_identifier = module.params['parent'] group_visibility = module.params['visibility'] + project_creation_level = module.params['project_creation_level'] + auto_devops_enabled = module.params['auto_devops_enabled'] + subgroup_creation_level = module.params['subgroup_creation_level'] if not HAS_GITLAB_PACKAGE: module.fail_json(msg=missing_required_lib("python-gitlab"), exception=GITLAB_IMP_ERR) @@ -314,7 +358,10 @@ def main(): if gitlab_group.createOrUpdateGroup(group_name, parent_group, { "path": group_path, "description": description, - "visibility": group_visibility}): + "visibility": group_visibility, + "project_creation_level": project_creation_level, + "auto_devops_enabled": auto_devops_enabled, + "subgroup_creation_level": subgroup_creation_level}): module.exit_json(changed=True, msg="Successfully created or updated the group %s" % group_name, group=gitlab_group.groupObject._attrs) else: module.exit_json(changed=False, msg="No need to update the group %s" % group_name, group=gitlab_group.groupObject._attrs) diff --git a/tests/integration/targets/gitlab_group/tasks/main.yml b/tests/integration/targets/gitlab_group/tasks/main.yml index 34444134c2..fbf8de29a0 100644 --- a/tests/integration/targets/gitlab_group/tasks/main.yml +++ b/tests/integration/targets/gitlab_group/tasks/main.yml @@ -72,3 +72,28 @@ assert: that: - gitlab_group_state_desc.group.description == "My Test Group" + +- name: Cleanup GitLab Group for project_creation_level Test + gitlab_group: + api_url: "{{ gitlab_host }}" + validate_certs: false + api_token: "{{ gitlab_login_token }}" + name: ansible_test_group + path: ansible_test_group + state: absent + +- name: Create GitLab Group for project_creation_level Test + gitlab_group: + api_url: "{{ gitlab_host }}" + validate_certs: false + api_token: "{{ gitlab_login_token }}" + name: ansible_test_group + path: ansible_test_group + project_creation_level: noone + state: present + register: gitlab_group_state_pcl + +- name: Test group created with project_creation_level + assert: + that: + - gitlab_group_state_pcl.group.project_creation_level == "noone" diff --git a/tests/unit/plugins/modules/source_control/gitlab/gitlab.py b/tests/unit/plugins/modules/source_control/gitlab/gitlab.py index 5feff78b43..cca9ab5ae6 100644 --- a/tests/unit/plugins/modules/source_control/gitlab/gitlab.py +++ b/tests/unit/plugins/modules/source_control/gitlab/gitlab.py @@ -194,6 +194,7 @@ def resp_get_group(url, request): '"lfs_enabled": true, "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",' '"web_url": "http://localhost:3000/groups/foo-bar", "request_access_enabled": false,' '"full_name": "Foobar Group", "full_path": "foo-bar",' + '"project_creation_level": "maintainer", "subgroup_creation_level": "maintainer",' '"file_template_project_id": 1, "parent_id": null, "projects": [{"id": 1,"description": null, "default_branch": "master",' '"ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",' '"http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",' @@ -225,7 +226,8 @@ def resp_create_group(url, request): '"lfs_enabled": true, "avatar_url": "http://localhost:3000/uploads/group/avatar/1/foo.jpg",' '"web_url": "http://localhost:3000/groups/foo-bar", "request_access_enabled": false,' '"full_name": "Foobar Group", "full_path": "foo-bar",' - '"file_template_project_id": 1, "parent_id": null}') + '"file_template_project_id": 1, "parent_id": null,' + '"project_creation_level": "developer", "subgroup_creation_level": "maintainer"}') content = content.encode("utf-8") return response(200, content, headers, None, 5, request) @@ -238,7 +240,8 @@ def resp_create_subgroup(url, request): '"lfs_enabled": true, "avatar_url": "http://localhost:3000/uploads/group/avatar/2/bar.jpg",' '"web_url": "http://localhost:3000/groups/foo-bar/bar-foo", "request_access_enabled": false,' '"full_name": "BarFoo Group", "full_path": "foo-bar/bar-foo",' - '"file_template_project_id": 1, "parent_id": 1}') + '"file_template_project_id": 1, "parent_id": 1,' + '"project_creation_level": "noone"}') content = content.encode("utf-8") return response(200, content, headers, None, 5, request) diff --git a/tests/unit/plugins/modules/source_control/gitlab/test_gitlab_group.py b/tests/unit/plugins/modules/source_control/gitlab/test_gitlab_group.py index abf49860f9..0b05f8a7ff 100644 --- a/tests/unit/plugins/modules/source_control/gitlab/test_gitlab_group.py +++ b/tests/unit/plugins/modules/source_control/gitlab/test_gitlab_group.py @@ -68,32 +68,43 @@ class TestGitlabGroup(GitlabModuleTestCase): def test_create_group(self): group = self.moduleUtil.createGroup({'name': "Foobar Group", 'path': "foo-bar", - 'description': "An interesting group"}) + 'description': "An interesting group", + 'project_creation_level': "developer", + 'subgroup_creation_level': "maintainer"}) self.assertEqual(type(group), Group) self.assertEqual(group.name, "Foobar Group") self.assertEqual(group.path, "foo-bar") self.assertEqual(group.description, "An interesting group") + self.assertEqual(group.project_creation_level, "developer") + self.assertEqual(group.subgroup_creation_level, "maintainer") self.assertEqual(group.id, 1) @with_httmock(resp_create_subgroup) def test_create_subgroup(self): - group = self.moduleUtil.createGroup({'name': "BarFoo Group", 'path': "bar-foo", "parent_id": 1}) + group = self.moduleUtil.createGroup({'name': "BarFoo Group", + 'path': "bar-foo", + 'parent_id': 1, + 'project_creation_level': "noone"}) self.assertEqual(type(group), Group) self.assertEqual(group.name, "BarFoo Group") self.assertEqual(group.full_path, "foo-bar/bar-foo") + self.assertEqual(group.project_creation_level, "noone") self.assertEqual(group.id, 2) self.assertEqual(group.parent_id, 1) @with_httmock(resp_get_group) def test_update_group(self): group = self.gitlab_instance.groups.get(1) - changed, newGroup = self.moduleUtil.updateGroup(group, {'name': "BarFoo Group", "visibility": "private"}) + changed, newGroup = self.moduleUtil.updateGroup(group, {'name': "BarFoo Group", + 'visibility': "private", + 'project_creation_level': "maintainer"}) self.assertEqual(changed, True) self.assertEqual(newGroup.name, "BarFoo Group") self.assertEqual(newGroup.visibility, "private") + self.assertEqual(newGroup.project_creation_level, "maintainer") changed, newGroup = self.moduleUtil.updateGroup(group, {'name': "BarFoo Group"})