Skip to content

feat(job_token_scope): support job token access allowlist API #2767

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/gl_objects/job_token_scope.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,23 @@ Refresh the current state of job token scope::
scope.refresh()
print(scope.inbound_enabled)
# False

Get a project's CI/CD job token inbound allowlist::

allowlist = scope.allowlist.list()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure yet about this naming here, but it follows both the endpoint URL and our convention 😕

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it would definetly be clearer if it were scope.projects_allowlist since gitlab have added groups_allowlist https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-allowlist-of-groups

But scope.allowlist does absolutely match the API design doc so it is probably best overall to be consistent with their docs 🤷


Add a project to the project's inbound allowlist::

allowed_project = scope.allowlist.create({"target_project_id": 42})

Remove a project from the project's inbound allowlist::

allowed_project.delete()
# or directly using a project ID
scope.allowlist.delete(42)

.. warning::

Similar to above, the ID attributes you receive from the create and list
APIs are not consistent. To safely retrieve the ID of the allowlisted project
regardless of how the object was created, always use its ``.get_id()`` method.
28 changes: 28 additions & 0 deletions gitlab/v4/objects/job_token_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

from gitlab.base import RESTManager, RESTObject
from gitlab.mixins import (
CreateMixin,
DeleteMixin,
GetWithoutIdMixin,
ListMixin,
ObjectDeleteMixin,
RefreshMixin,
SaveMixin,
UpdateMethod,
UpdateMixin,
)
from gitlab.types import RequiredOptional


__all__ = [
"ProjectJobTokenScope",
Expand All @@ -18,6 +24,8 @@
class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject):
_id_attr = None

allowlist: "AllowlistedProjectManager"


class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
_path = "/projects/{project_id}/job_token_scope"
Expand All @@ -27,3 +35,23 @@ class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager):

def get(self, **kwargs: Any) -> ProjectJobTokenScope:
return cast(ProjectJobTokenScope, super().get(**kwargs))


class AllowlistedProject(ObjectDeleteMixin, RESTObject):
_id_attr = "target_project_id" # note: only true for create endpoint

def get_id(self) -> int:
"""Returns the id of the resource. This override deals with
the fact that either an `id` or a `target_project_id` attribute
is returned by the server depending on the endpoint called."""
try:
return cast(int, getattr(self, self._id_attr))
except AttributeError:
return cast(int, getattr(self, "id"))
Comment on lines +47 to +50
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitLab at it again - create response:

{
  "source_project_id": 1,
  "target_project_id": 2
}

list response:

{
  "id": 4,
  "description": null,
  "name": "Diaspora Client",
  "name_with_namespace": "Diaspora / Diaspora Client",
  "path": "diaspora-client",
  ...
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm kind of thinking for the create to not return anything. As the caller appears to use all the values when creating that will be returned. Not sure if that would simplify things or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Convention in REST and so far in python-gitlab would be to return the object that has been created. Means that in future if Gitlab add optional things into the contract which get returned back in the POST, user's would get insight into that



class AllowlistedProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
_path = "/projects/{project_id}/job_token_scope/allowlist"
_obj_cls = AllowlistedProject
_from_parent_attrs = {"project_id": "project_id"}
_create_attrs = RequiredOptional(required=("target_project_id",))