diff --git a/docs/gl_objects/groups.rst b/docs/gl_objects/groups.rst index 02d2bb097..199847d9f 100644 --- a/docs/gl_objects/groups.rst +++ b/docs/gl_objects/groups.rst @@ -74,6 +74,11 @@ Remove a group:: # or group.delete() +Share/unshare the group with a group:: + + group.share(group2.id, gitlab.DEVELOPER_ACCESS) + group.unshare(group2.id) + Import / Export =============== diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 6b47e08db..2f3e8a591 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -1467,6 +1467,44 @@ def ldap_sync(self, **kwargs): path = "/groups/%s/ldap_sync" % self.get_id() self.manager.gitlab.http_post(path, **kwargs) + @cli.register_custom_action("Group", ("group_id", "group_access"), ("expires_at",)) + @exc.on_http_error(exc.GitlabCreateError) + def share(self, group_id, group_access, expires_at=None, **kwargs): + """Share the group with a group. + + Args: + group_id (int): ID of the group. + group_access (int): Access level for the group. + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabCreateError: If the server failed to perform the request + """ + path = "/groups/%s/share" % self.get_id() + data = { + "group_id": group_id, + "group_access": group_access, + "expires_at": expires_at, + } + self.manager.gitlab.http_post(path, post_data=data, **kwargs) + + @cli.register_custom_action("Group", ("group_id",)) + @exc.on_http_error(exc.GitlabDeleteError) + def unshare(self, group_id, **kwargs): + """Delete a shared group link within a group. + + Args: + group_id (int): ID of the group. + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabDeleteError: If the server failed to perform the request + """ + path = "/groups/%s/share/%s" % (self.get_id(), group_id) + self.manager.gitlab.http_delete(path, **kwargs) + class GroupManager(CRUDMixin, RESTManager): _path = "/groups" diff --git a/tools/python_test_v4.py b/tools/python_test_v4.py index c43eebdd1..6ecaf24b4 100644 --- a/tools/python_test_v4.py +++ b/tools/python_test_v4.py @@ -255,8 +255,9 @@ p_id = gl.groups.list(search="group2")[0].id group3 = gl.groups.create({"name": "group3", "path": "group3", "parent_id": p_id}) +group4 = gl.groups.create({"name": "group4", "path": "group4"}) -assert len(gl.groups.list()) == 3 +assert len(gl.groups.list()) == 4 assert len(gl.groups.list(search="oup1")) == 1 assert group3.parent_id == p_id assert group2.subgroups.list()[0].id == group3.id @@ -266,6 +267,16 @@ group2.members.create({"access_level": gitlab.const.OWNER_ACCESS, "user_id": user2.id}) +group4.share(group1.id, gitlab.const.DEVELOPER_ACCESS) +group4.share(group2.id, gitlab.const.MAINTAINER_ACCESS) +# Reload group4 to have updated shared_with_groups +group4 = gl.groups.get(group4.id) +assert len(group4.shared_with_groups) == 2 +group4.unshare(group1.id) +# Reload group4 to have updated shared_with_groups +group4 = gl.groups.get(group4.id) +assert len(group4.shared_with_groups) == 1 + # User memberships (admin only) memberships1 = user1.memberships.list() assert len(memberships1) == 1 @@ -419,7 +430,7 @@ gr2_project = gl.projects.create({"name": "gr2_project", "namespace_id": group2.id}) sudo_project = gl.projects.create({"name": "sudo_project"}, sudo=user1.name) -assert len(gl.projects.list(owned=True)) == 2 +assert len(gl.projects.list(owned=True)) == 3 assert len(gl.projects.list(search="admin")) == 1 assert len(gl.projects.list(as_list=False)) == 4