| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent fcd72fe commit d0a0348
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -52,6 +52,7 @@ API examples | |||
| 52 | 52 | gl_objects/repositories | |
| 53 | 53 | gl_objects/repository_tags | |
| 54 | 54 | gl_objects/search | |
| 55 | + gl_objects/secure_files | ||
| 55 | 56 | gl_objects/settings | |
| 56 | 57 | gl_objects/snippets | |
| 57 | 58 | gl_objects/statistics | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,47 @@ | |||
| 1 | + ############ | ||
| 2 | + Secure Files | ||
| 3 | + ############ | ||
| 4 | + | ||
| 5 | + secure files | ||
| 6 | + ============ | ||
| 7 | + | ||
| 8 | + References | ||
| 9 | + ---------- | ||
| 10 | + | ||
| 11 | + * v4 API: | ||
| 12 | + | ||
| 13 | + + :class:`gitlab.v4.objects.SecureFile` | ||
| 14 | + + :class:`gitlab.v4.objects.SecureFileManager` | ||
| 15 | + + :attr:`gitlab.v4.objects.Project.secure_files` | ||
| 16 | + | ||
| 17 | + * GitLab API: https://docs.gitlab.com/ee/api/secure_files.html | ||
| 18 | + | ||
| 19 | + Examples | ||
| 20 | + -------- | ||
| 21 | + | ||
| 22 | + Get a project secure file:: | ||
| 23 | + | ||
| 24 | + secure_files = gl.projects.get(1, lazy=True).secure_files.get(1) | ||
| 25 | + print(secure_files.name) | ||
| 26 | + | ||
| 27 | + List project secure files:: | ||
| 28 | + | ||
| 29 | + secure_files = gl.projects.get(1, lazy=True).secure_files.list() | ||
| 30 | + print(secure_files[0].name) | ||
| 31 | + | ||
| 32 | + Create project secure file:: | ||
| 33 | + | ||
| 34 | + secure_file = gl.projects.get(1).secure_files.create({"name": "test", "file": "secure.txt"}) | ||
| 35 | + | ||
| 36 | + Download a project secure file:: | ||
| 37 | + | ||
| 38 | + content = secure_file.download() | ||
| 39 | + print(content) | ||
| 40 | + with open("/tmp/secure.txt", "wb") as f: | ||
| 41 | + secure_file.download(streamed=True, action=f.write) | ||
| 42 | + | ||
| 43 | + Remove a project secure file:: | ||
| 44 | + | ||
| 45 | + gl.projects.get(1).secure_files.delete(1) | ||
| 46 | + # or | ||
| 47 | + secure_file.delete() | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -53,6 +53,7 @@ | |||
| 53 | 53 | from .releases import * | |
| 54 | 54 | from .repositories import * | |
| 55 | 55 | from .runners import * | |
| 56 | + from .secure_files import * | ||
| 56 | 57 | from .settings import * | |
| 57 | 58 | from .sidekiq import * | |
| 58 | 59 | from .snippets import * | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -82,6 +82,7 @@ | |||
| 82 | 82 | from .releases import ProjectReleaseManager # noqa: F401 | |
| 83 | 83 | from .repositories import RepositoryMixin | |
| 84 | 84 | from .runners import ProjectRunnerManager # noqa: F401 | |
| 85 | + from .secure_files import SecureFileManager # noqa: F401 | ||
| 85 | 86 | from .snippets import ProjectSnippetManager # noqa: F401 | |
| 86 | 87 | from .statistics import ( # noqa: F401 | |
| 87 | 88 | ProjectAdditionalStatisticsManager, | |
@@ -209,6 +210,7 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO | |||
| 209 | 210 | remote_mirrors: "ProjectRemoteMirrorManager" | |
| 210 | 211 | repositories: ProjectRegistryRepositoryManager | |
| 211 | 212 | runners: ProjectRunnerManager | |
| 213 | + secure_files: SecureFileManager | ||
| 212 | 214 | services: ProjectServiceManager | |
| 213 | 215 | snippets: ProjectSnippetManager | |
| 214 | 216 | storage: "ProjectStorageManager" | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,69 @@ | |||
| 1 | + """ | ||
| 2 | + GitLab API: | ||
| 3 | + https://docs.gitlab.com/ee/api/secure_files.html | ||
| 4 | + """ | ||
| 5 | + from typing import Any, Callable, cast, Iterator, Optional, TYPE_CHECKING, Union | ||
| 6 | + | ||
| 7 | + import requests | ||
| 8 | + | ||
| 9 | + from gitlab import cli | ||
| 10 | + from gitlab import exceptions as exc | ||
| 11 | + from gitlab import utils | ||
| 12 | + from gitlab.base import RESTManager, RESTObject | ||
| 13 | + from gitlab.mixins import NoUpdateMixin, ObjectDeleteMixin | ||
| 14 | + from gitlab.types import FileAttribute, RequiredOptional | ||
| 15 | + | ||
| 16 | + __all__ = ["SecureFile", "SecureFileManager"] | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + class SecureFile(ObjectDeleteMixin, RESTObject): | ||
| 20 | + @cli.register_custom_action("SecureFile") | ||
| 21 | + @exc.on_http_error(exc.GitlabGetError) | ||
| 22 | + def download( | ||
| 23 | + self, | ||
| 24 | + streamed: bool = False, | ||
| 25 | + action: Optional[Callable[[bytes], None]] = None, | ||
| 26 | + chunk_size: int = 1024, | ||
| 27 | + *, | ||
| 28 | + iterator: bool = False, | ||
| 29 | + **kwargs: Any, | ||
| 30 | + ) -> Optional[Union[bytes, Iterator[Any]]]: | ||
| 31 | + """Download the secure file. | ||
| 32 | + | ||
| 33 | + Args: | ||
| 34 | + streamed: If True the data will be processed by chunks of | ||
| 35 | + `chunk_size` and each chunk is passed to `action` for | ||
| 36 | + treatment | ||
| 37 | + iterator: If True directly return the underlying response | ||
| 38 | + iterator | ||
| 39 | + action: Callable responsible of dealing with chunk of | ||
| 40 | + data | ||
| 41 | + chunk_size: Size of each chunk | ||
| 42 | + **kwargs: Extra options to send to the server (e.g. sudo) | ||
| 43 | + | ||
| 44 | + Raises: | ||
| 45 | + GitlabAuthenticationError: If authentication is not correct | ||
| 46 | + GitlabGetError: If the artifacts could not be retrieved | ||
| 47 | + | ||
| 48 | + Returns: | ||
| 49 | + The artifacts if `streamed` is False, None otherwise.""" | ||
| 50 | + path = f"{self.manager.path}/{self.id}/download" | ||
| 51 | + result = self.manager.gitlab.http_get( | ||
| 52 | + path, streamed=streamed, raw=True, **kwargs | ||
| 53 | + ) | ||
| 54 | + if TYPE_CHECKING: | ||
| 55 | + assert isinstance(result, requests.Response) | ||
| 56 | + return utils.response_content( | ||
| 57 | + result, streamed, action, chunk_size, iterator=iterator | ||
| 58 | + ) | ||
| 59 | + | ||
| 60 | + | ||
| 61 | + class SecureFileManager(NoUpdateMixin, RESTManager): | ||
| 62 | + _path = "/projects/{project_id}/secure_files" | ||
| 63 | + _obj_cls = SecureFile | ||
| 64 | + _from_parent_attrs = {"project_id": "id"} | ||
| 65 | + _create_attrs = RequiredOptional(required=("name", "file")) | ||
| 66 | + _types = {"file": FileAttribute} | ||
| 67 | + | ||
| 68 | + def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> SecureFile: | ||
| 69 | + return cast(SecureFile, super().get(id=id, lazy=lazy, **kwargs)) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,101 @@ | |||
| 1 | + """ | ||
| 2 | + GitLab API: https://docs.gitlab.com/ee/api/secure_files.html | ||
| 3 | + """ | ||
| 4 | + | ||
| 5 | + import pytest | ||
| 6 | + import responses | ||
| 7 | + | ||
| 8 | + from gitlab.v4.objects import SecureFile | ||
| 9 | + | ||
| 10 | + secure_file_content = { | ||
| 11 | + "id": 1, | ||
| 12 | + "name": "myfile.jks", | ||
| 13 | + "checksum": "16630b189ab34b2e3504f4758e1054d2e478deda510b2b08cc0ef38d12e80aac", | ||
| 14 | + "checksum_algorithm": "sha256", | ||
| 15 | + "created_at": "2022-02-22T22:22:22.222Z", | ||
| 16 | + "expires_at": None, | ||
| 17 | + "metadata": None, | ||
| 18 | + } | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + @pytest.fixture | ||
| 22 | + def resp_list_secure_files(): | ||
| 23 | + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: | ||
| 24 | + rsps.add( | ||
| 25 | + method=responses.GET, | ||
| 26 | + url="http://localhost/api/v4/projects/1/secure_files", | ||
| 27 | + json=[secure_file_content], | ||
| 28 | + content_type="application/json", | ||
| 29 | + status=200, | ||
| 30 | + ) | ||
| 31 | + yield rsps | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + @pytest.fixture | ||
| 35 | + def resp_create_secure_file(): | ||
| 36 | + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: | ||
| 37 | + rsps.add( | ||
| 38 | + method=responses.POST, | ||
| 39 | + url="http://localhost/api/v4/projects/1/secure_files", | ||
| 40 | + json=secure_file_content, | ||
| 41 | + content_type="application/json", | ||
| 42 | + status=200, | ||
| 43 | + ) | ||
| 44 | + yield rsps | ||
| 45 | + | ||
| 46 | + | ||
| 47 | + @pytest.fixture | ||
| 48 | + def resp_download_secure_file(binary_content): | ||
| 49 | + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: | ||
| 50 | + rsps.add( | ||
| 51 | + method=responses.GET, | ||
| 52 | + url="http://localhost/api/v4/projects/1/secure_files/1", | ||
| 53 | + json=secure_file_content, | ||
| 54 | + content_type="application/json", | ||
| 55 | + status=200, | ||
| 56 | + ) | ||
| 57 | + rsps.add( | ||
| 58 | + method=responses.GET, | ||
| 59 | + url="http://localhost/api/v4/projects/1/secure_files/1/download", | ||
| 60 | + body=binary_content, | ||
| 61 | + content_type="application/octet-stream", | ||
| 62 | + status=200, | ||
| 63 | + ) | ||
| 64 | + yield rsps | ||
| 65 | + | ||
| 66 | + | ||
| 67 | + @pytest.fixture | ||
| 68 | + def resp_remove_secure_file(no_content): | ||
| 69 | + with responses.RequestsMock() as rsps: | ||
| 70 | + rsps.add( | ||
| 71 | + method=responses.DELETE, | ||
| 72 | + url="http://localhost/api/v4/projects/1/secure_files/1", | ||
| 73 | + json=no_content, | ||
| 74 | + content_type="application/json", | ||
| 75 | + status=204, | ||
| 76 | + ) | ||
| 77 | + yield rsps | ||
| 78 | + | ||
| 79 | + | ||
| 80 | + def test_list_secure_files(project, resp_list_secure_files): | ||
| 81 | + secure_files = project.secure_files.list() | ||
| 82 | + assert len(secure_files) == 1 | ||
| 83 | + assert secure_files[0].id == 1 | ||
| 84 | + assert secure_files[0].name == "myfile.jks" | ||
| 85 | + | ||
| 86 | + | ||
| 87 | + def test_create_secure_file(project, resp_create_secure_file): | ||
| 88 | + secure_files = project.secure_files.create({"name": "test", "file": "myfile.jks"}) | ||
| 89 | + assert secure_files.id == 1 | ||
| 90 | + assert secure_files.name == "myfile.jks" | ||
| 91 | + | ||
| 92 | + | ||
| 93 | + def test_download_secure_file(project, binary_content, resp_download_secure_file): | ||
| 94 | + secure_file = project.secure_files.get(1) | ||
| 95 | + secure_content = secure_file.download() | ||
| 96 | + assert isinstance(secure_file, SecureFile) | ||
| 97 | + assert secure_content == binary_content | ||
| 98 | + | ||
| 99 | + | ||
| 100 | + def test_remove_secure_file(project, resp_remove_secure_file): | ||
| 101 | + project.secure_files.delete(1) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments