diff --git a/docs/gl_objects/groups.rst b/docs/gl_objects/groups.rst index 37977da29..479cbd27e 100644 --- a/docs/gl_objects/groups.rst +++ b/docs/gl_objects/groups.rst @@ -458,3 +458,24 @@ Edit group push rules:: Delete group push rules:: pr.delete() + +Group Service Account +===================== + +Reference +--------- + +* v4 API: + + + :class:`gitlab.v4.objects.GroupServiceAccount` + + :class:`gitlab.v4.objects.GroupServiceAccountManager` + + :attr:`gitlab.v4.objects.Group.serviceaccounts` + +* GitLab API: https://docs.gitlab.com/ee/api/groups.html#service-accounts + +Examples +--------- + +Create group service account (only allowed at top level group):: + + group.serviceaccount.create({'name': 'group-service-account', 'username': 'group-service-account'}) diff --git a/gitlab/v4/objects/__init__.py b/gitlab/v4/objects/__init__.py index b13e25951..0871b4dd9 100644 --- a/gitlab/v4/objects/__init__.py +++ b/gitlab/v4/objects/__init__.py @@ -59,6 +59,7 @@ from .reviewers import * from .runners import * from .secure_files import * +from .service_accounts import * from .settings import * from .sidekiq import * from .snippets import * diff --git a/gitlab/v4/objects/groups.py b/gitlab/v4/objects/groups.py index 9f509bd1e..41e379ea3 100644 --- a/gitlab/v4/objects/groups.py +++ b/gitlab/v4/objects/groups.py @@ -46,6 +46,7 @@ from .projects import GroupProjectManager, SharedProjectManager # noqa: F401 from .push_rules import GroupPushRulesManager from .runners import GroupRunnerManager # noqa: F401 +from .service_accounts import GroupServiceAccountManager # noqa: F401 from .statistics import GroupIssuesStatisticsManager # noqa: F401 from .variables import GroupVariableManager # noqa: F401 from .wikis import GroupWikiManager # noqa: F401 @@ -102,6 +103,7 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject): variables: GroupVariableManager wikis: GroupWikiManager saml_group_links: "GroupSAMLGroupLinkManager" + service_accounts: "GroupServiceAccountManager" @cli.register_custom_action("Group", ("project_id",)) @exc.on_http_error(exc.GitlabTransferProjectError) diff --git a/gitlab/v4/objects/service_accounts.py b/gitlab/v4/objects/service_accounts.py new file mode 100644 index 000000000..c44c2cde3 --- /dev/null +++ b/gitlab/v4/objects/service_accounts.py @@ -0,0 +1,18 @@ +from gitlab.base import RESTManager, RESTObject +from gitlab.mixins import CreateMixin +from gitlab.types import RequiredOptional + +__all__ = ["GroupServiceAccount", "GroupServiceAccountManager"] + + +class GroupServiceAccount(RESTObject): + pass + + +class GroupServiceAccountManager(CreateMixin, RESTManager): + _path = "/groups/{group_id}/service_accounts" + _obj_cls = GroupServiceAccount + _from_parent_attrs = {"group_id": "id"} + _create_attrs = RequiredOptional( + optional=("name", "username"), + ) diff --git a/tests/functional/api/test_groups.py b/tests/functional/api/test_groups.py index 8efc3245d..93200241a 100644 --- a/tests/functional/api/test_groups.py +++ b/tests/functional/api/test_groups.py @@ -308,3 +308,12 @@ def test_group_saml_group_links(group): group.saml_group_links.create( {"saml_group_name": "saml-group-1", "access_level": 10} ) + + +@pytest.mark.gitlab_premium +def test_group_service_account(group): + service_account = group.service_accounts.create( + {"name": "gitlab-service-account", "username": "gitlab-service-account"} + ) + assert service_account.name == "gitlab-service-account" + assert service_account.username == "gitlab-service-account" diff --git a/tests/unit/objects/test_groups.py b/tests/unit/objects/test_groups.py index 6fe4c7db1..2caa085b2 100644 --- a/tests/unit/objects/test_groups.py +++ b/tests/unit/objects/test_groups.py @@ -83,6 +83,11 @@ "max_file_size": 100, } +service_account_content = { + "name": "gitlab-service-account", + "username": "gitlab-service-account", +} + @pytest.fixture def resp_groups(): @@ -325,6 +330,19 @@ def resp_restore_group(created_content): yield rsps +@pytest.fixture +def resp_create_group_service_account(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/groups/1/service_accounts", + json=service_account_content, + content_type="application/json", + status=200, + ) + yield rsps + + def test_get_group(gl, resp_groups): data = gl.groups.get(1) assert isinstance(data, gitlab.v4.objects.Group) @@ -466,3 +484,11 @@ def test_delete_saml_group_link(group, resp_delete_saml_group_link): def test_group_restore(group, resp_restore_group): group.restore() + + +def test_create_group_service_account(group, resp_create_group_service_account): + service_account = group.service_accounts.create( + {"name": "gitlab-service-account", "username": "gitlab-service-account"} + ) + assert service_account.name == "gitlab-service-account" + assert service_account.username == "gitlab-service-account"