pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: https://github.com/python-gitlab/python-gitlab/commit/feb6cedeffa75ef386ef13a3226bc07bcb396f61

f1.css" /> feat(api): add full service account support at instance, group, and p… · python-gitlab/python-gitlab@feb6ced · GitHub
Skip to content

Commit feb6ced

Browse files
syphernlJohnVillalovos
authored andcommitted
feat(api): add full service account support at instance, group, and project level
1 parent 849301b commit feb6ced

6 files changed

Lines changed: 890 additions & 5 deletions

File tree

docs/api-objects.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ API examples
6464
gl_objects/resource_groups
6565
gl_objects/search
6666
gl_objects/secure_files
67+
gl_objects/service_accounts
6768
gl_objects/settings
6869
gl_objects/snippets
6970
gl_objects/statistics
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
################
2+
Service Accounts
3+
################
4+
5+
References
6+
----------
7+
8+
* v4 API:
9+
10+
+ :class:`gitlab.v4.objects.ServiceAccount`
11+
+ :class:`gitlab.v4.objects.ServiceAccountManager`
12+
+ :class:`gitlab.v4.objects.GroupServiceAccount`
13+
+ :class:`gitlab.v4.objects.GroupServiceAccountManager`
14+
+ :class:`gitlab.v4.objects.GroupServiceAccountAccessToken`
15+
+ :class:`gitlab.v4.objects.GroupServiceAccountAccessTokenManager`
16+
+ :class:`gitlab.v4.objects.ProjectServiceAccount`
17+
+ :class:`gitlab.v4.objects.ProjectServiceAccountManager`
18+
+ :class:`gitlab.v4.objects.ProjectServiceAccountAccessToken`
19+
+ :class:`gitlab.v4.objects.ProjectServiceAccountAccessTokenManager`
20+
21+
* GitLab API: https://docs.gitlab.com/api/service_accounts/
22+
23+
Instance service accounts
24+
-------------------------
25+
26+
List instance service accounts::
27+
28+
accounts = gl.service_accounts.list()
29+
30+
Create an instance service account::
31+
32+
sa = gl.service_accounts.create({})
33+
# with optional attributes
34+
sa = gl.service_accounts.create({"name": "my-bot", "username": "my-bot", "email": "my-bot@example.com"})
35+
36+
Update an instance service account::
37+
38+
gl.service_accounts.update(sa.id, {"name": "renamed-bot"})
39+
# or via the object
40+
sa.name = "renamed-bot"
41+
sa.save()
42+
43+
Group service accounts
44+
----------------------
45+
46+
List group service accounts::
47+
48+
accounts = group.service_accounts.list()
49+
50+
Create a group service account::
51+
52+
sa = group.service_accounts.create({})
53+
# with optional attributes
54+
sa = group.service_accounts.create({"name": "ci-bot", "username": "ci-bot"})
55+
56+
Update a group service account::
57+
58+
group.service_accounts.update(sa.id, {"name": "renamed-bot"})
59+
# or via the object
60+
sa.name = "renamed-bot"
61+
sa.save()
62+
63+
Delete a group service account::
64+
65+
group.service_accounts.delete(sa.id)
66+
# or via the object
67+
sa.delete()
68+
69+
Group service account personal access tokens
70+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
71+
72+
List tokens for a group service account::
73+
74+
tokens = sa.access_tokens.list()
75+
76+
Create a token for a group service account::
77+
78+
token = sa.access_tokens.create({
79+
"name": "ci-token",
80+
"scopes": ["api"],
81+
"expires_at": "2026-01-01",
82+
})
83+
print(token.token)
84+
85+
Rotate a token::
86+
87+
token.rotate()
88+
print(token.token)
89+
# or directly using a token ID
90+
new_token = sa.access_tokens.rotate(token.id)
91+
print(new_token["token"])
92+
93+
Revoke a token::
94+
95+
sa.access_tokens.delete(token.id)
96+
# or via the object
97+
token.delete()
98+
99+
Project service accounts
100+
------------------------
101+
102+
List project service accounts::
103+
104+
accounts = project.service_accounts.list()
105+
106+
Create a project service account::
107+
108+
sa = project.service_accounts.create({})
109+
# with optional attributes
110+
sa = project.service_accounts.create({"name": "ci-bot", "username": "ci-bot"})
111+
112+
Update a project service account::
113+
114+
project.service_accounts.update(sa.id, {"name": "renamed-bot"})
115+
# or via the object
116+
sa.name = "renamed-bot"
117+
sa.save()
118+
119+
Delete a project service account::
120+
121+
project.service_accounts.delete(sa.id)
122+
# or via the object
123+
sa.delete()
124+
125+
Project service account personal access tokens
126+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127+
128+
List tokens for a project service account::
129+
130+
tokens = sa.access_tokens.list()
131+
132+
Create a token for a project service account::
133+
134+
token = sa.access_tokens.create({
135+
"name": "ci-token",
136+
"scopes": ["read_repository"],
137+
"expires_at": "2026-01-01",
138+
})
139+
print(token.token)
140+
141+
Rotate a token::
142+
143+
token.rotate()
144+
print(token.token)
145+
# or directly using a token ID
146+
new_token = sa.access_tokens.rotate(token.id)
147+
print(new_token["token"])
148+
149+
Revoke a token::
150+
151+
sa.access_tokens.delete(token.id)
152+
# or via the object
153+
token.delete()

gitlab/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ def __init__(
211211
"""See :class:`~gitlab.v4.objects.PersonalAccessTokenManager`"""
212212
self.topics = objects.TopicManager(self)
213213
"""See :class:`~gitlab.v4.objects.TopicManager`"""
214+
self.service_accounts = objects.ServiceAccountManager(self)
215+
"""See :class:`~gitlab.v4.objects.ServiceAccountManager`"""
214216
self.statistics = objects.ApplicationStatisticsManager(self)
215217
"""See :class:`~gitlab.v4.objects.ApplicationStatisticsManager`"""
216218

gitlab/v4/objects/projects.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
from .resource_groups import ProjectResourceGroupManager
9292
from .runners import ProjectRunnerManager # noqa: F401
9393
from .secure_files import ProjectSecureFileManager # noqa: F401
94+
from .service_accounts import ProjectServiceAccountManager # noqa: F401
9495
from .snippets import ProjectSnippetManager # noqa: F401
9596
from .statistics import ( # noqa: F401
9697
ProjectAdditionalStatisticsManager,
@@ -251,6 +252,7 @@ class Project(
251252
repositories: ProjectRegistryRepositoryManager
252253
runners: ProjectRunnerManager
253254
secure_files: ProjectSecureFileManager
255+
service_accounts: ProjectServiceAccountManager
254256
services: ProjectServiceManager
255257
snippets: ProjectSnippetManager
256258
external_status_checks: ProjectExternalStatusCheckManager
Lines changed: 140 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,155 @@
1+
"""
2+
GitLab API: https://docs.gitlab.com/api/service_accounts/
3+
"""
4+
15
from gitlab.base import RESTObject
2-
from gitlab.mixins import CreateMixin, DeleteMixin, ListMixin, ObjectDeleteMixin
3-
from gitlab.types import RequiredOptional
6+
from gitlab.mixins import (
7+
CreateMixin,
8+
DeleteMixin,
9+
ListMixin,
10+
ObjectDeleteMixin,
11+
ObjectRotateMixin,
12+
RotateMixin,
13+
SaveMixin,
14+
UpdateMethod,
15+
UpdateMixin,
16+
)
17+
from gitlab.types import ArrayAttribute, RequiredOptional
18+
19+
__all__ = [
20+
"ServiceAccount",
21+
"ServiceAccountManager",
22+
"GroupServiceAccount",
23+
"GroupServiceAccountManager",
24+
"GroupServiceAccountAccessToken",
25+
"GroupServiceAccountAccessTokenManager",
26+
"ProjectServiceAccount",
27+
"ProjectServiceAccountManager",
28+
"ProjectServiceAccountAccessToken",
29+
"ProjectServiceAccountAccessTokenManager",
30+
]
31+
32+
_SA_ACCOUNT_ATTRS = RequiredOptional(optional=("name", "username", "email"))
33+
34+
_SA_TOKEN_CREATE_ATTRS = RequiredOptional(
35+
required=("name", "scopes"), optional=("description", "expires_at")
36+
)
37+
38+
_SA_TOKEN_LIST_FILTERS = (
39+
"created_after",
40+
"created_before",
41+
"expires_after",
42+
"expires_before",
43+
"last_used_after",
44+
"last_used_before",
45+
"revoked",
46+
"search",
47+
"sort",
48+
"state",
49+
)
450

5-
__all__ = ["GroupServiceAccount", "GroupServiceAccountManager"]
651

52+
# ---------------------------------------------------------------------------
53+
# Instance-level service accounts
54+
# ---------------------------------------------------------------------------
755

8-
class GroupServiceAccount(ObjectDeleteMixin, RESTObject):
56+
57+
class ServiceAccount(SaveMixin, RESTObject):
958
pass
1059

1160

61+
class ServiceAccountManager(
62+
CreateMixin[ServiceAccount], ListMixin[ServiceAccount], UpdateMixin[ServiceAccount]
63+
):
64+
_path = "/service_accounts"
65+
_obj_cls = ServiceAccount
66+
_create_attrs = _SA_ACCOUNT_ATTRS
67+
_update_attrs = _SA_ACCOUNT_ATTRS
68+
_update_method = UpdateMethod.PATCH
69+
_list_filters = ("order_by", "sort")
70+
71+
72+
# ---------------------------------------------------------------------------
73+
# Group-level service accounts
74+
# ---------------------------------------------------------------------------
75+
76+
77+
class GroupServiceAccountAccessToken(ObjectDeleteMixin, ObjectRotateMixin, RESTObject):
78+
pass
79+
80+
81+
class GroupServiceAccountAccessTokenManager(
82+
CreateMixin[GroupServiceAccountAccessToken],
83+
DeleteMixin[GroupServiceAccountAccessToken],
84+
ListMixin[GroupServiceAccountAccessToken],
85+
RotateMixin[GroupServiceAccountAccessToken],
86+
):
87+
_path = "/groups/{group_id}/service_accounts/{user_id}/personal_access_tokens"
88+
_obj_cls = GroupServiceAccountAccessToken
89+
_from_parent_attrs = {"group_id": "group_id", "user_id": "id"}
90+
_create_attrs = _SA_TOKEN_CREATE_ATTRS
91+
_types = {"scopes": ArrayAttribute}
92+
_list_filters = _SA_TOKEN_LIST_FILTERS
93+
94+
95+
class GroupServiceAccount(SaveMixin, ObjectDeleteMixin, RESTObject):
96+
access_tokens: GroupServiceAccountAccessTokenManager
97+
98+
1299
class GroupServiceAccountManager(
13100
CreateMixin[GroupServiceAccount],
14101
DeleteMixin[GroupServiceAccount],
15102
ListMixin[GroupServiceAccount],
103+
UpdateMixin[GroupServiceAccount],
16104
):
17105
_path = "/groups/{group_id}/service_accounts"
18106
_obj_cls = GroupServiceAccount
19107
_from_parent_attrs = {"group_id": "id"}
20-
_create_attrs = RequiredOptional(optional=("name", "username"))
108+
_create_attrs = _SA_ACCOUNT_ATTRS
109+
_update_attrs = _SA_ACCOUNT_ATTRS
110+
_update_method = UpdateMethod.PATCH
111+
_list_filters = ("order_by", "sort")
112+
113+
114+
# ---------------------------------------------------------------------------
115+
# Project-level service accounts
116+
# ---------------------------------------------------------------------------
117+
118+
119+
class ProjectServiceAccountAccessToken(
120+
ObjectDeleteMixin, ObjectRotateMixin, RESTObject
121+
):
122+
pass
123+
124+
125+
class ProjectServiceAccountAccessTokenManager(
126+
CreateMixin[ProjectServiceAccountAccessToken],
127+
DeleteMixin[ProjectServiceAccountAccessToken],
128+
ListMixin[ProjectServiceAccountAccessToken],
129+
RotateMixin[ProjectServiceAccountAccessToken],
130+
):
131+
_path = "/projects/{project_id}/service_accounts/{user_id}/personal_access_tokens"
132+
_obj_cls = ProjectServiceAccountAccessToken
133+
_from_parent_attrs = {"project_id": "project_id", "user_id": "id"}
134+
_create_attrs = _SA_TOKEN_CREATE_ATTRS
135+
_types = {"scopes": ArrayAttribute}
136+
_list_filters = _SA_TOKEN_LIST_FILTERS
137+
138+
139+
class ProjectServiceAccount(SaveMixin, ObjectDeleteMixin, RESTObject):
140+
access_tokens: ProjectServiceAccountAccessTokenManager
141+
142+
143+
class ProjectServiceAccountManager(
144+
CreateMixin[ProjectServiceAccount],
145+
DeleteMixin[ProjectServiceAccount],
146+
ListMixin[ProjectServiceAccount],
147+
UpdateMixin[ProjectServiceAccount],
148+
):
149+
_path = "/projects/{project_id}/service_accounts"
150+
_obj_cls = ProjectServiceAccount
151+
_from_parent_attrs = {"project_id": "id"}
152+
_create_attrs = _SA_ACCOUNT_ATTRS
153+
_update_attrs = _SA_ACCOUNT_ATTRS
154+
_update_method = UpdateMethod.PATCH
155+
_list_filters = ("order_by", "sort")

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy