Skip to content

Commit

Permalink
Merge pull request #158 from dakky/master
Browse files Browse the repository at this point in the history
Feature: Added federated repo type
  • Loading branch information
anancarv authored Apr 30, 2024
2 parents 15e936f + 09bf220 commit 39acb68
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 17 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,12 @@ repo = art.repositories.get_repo("repo_name")

Create/Update a repository:
```python
from pyartifactory.models import LocalRepository, VirtualRepository, RemoteRepository
from pyartifactory.models import (
LocalRepository,
VirtualRepository,
RemoteRepository,
FederatedRepository
)

# Create local repo
local_repo = LocalRepository(key="test_local_repo")
Expand All @@ -231,6 +236,10 @@ new_virtual_repo = art.repositories.create_repo(virtual_repo)
remote_repo = RemoteRepository(key="test_remote_repo")
new_remote_repo = art.repositories.create_repo(remote_repo)

# Create federated repo
remote_repo = FederatedRepository(key="test_remote_repo")
new_federated_repo = art.repositories.create_repo(remote_repo)

# Update a repository
local_repo = art.repositories.get_repo("test_local_repo")
local_repo.description = "test_local_repo"
Expand Down
13 changes: 11 additions & 2 deletions pyartifactory/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from .group import Group, SimpleGroup
from .permission import Permission, PermissionV2, SimplePermission
from .repository import (
FederatedRepository,
FederatedRepositoryResponse,
LocalRepository,
LocalRepositoryResponse,
RemoteRepository,
Expand All @@ -26,9 +28,14 @@
)
from .user import BaseUserModel, NewUser, SimpleUser, User, UserResponse

AnyRepositoryResponse = Union[LocalRepositoryResponse, VirtualRepositoryResponse, RemoteRepositoryResponse]
AnyRepositoryResponse = Union[
LocalRepositoryResponse,
VirtualRepositoryResponse,
RemoteRepositoryResponse,
FederatedRepositoryResponse,
]

AnyRepository = Union[LocalRepository, VirtualRepository, RemoteRepository]
AnyRepository = Union[LocalRepository, VirtualRepository, RemoteRepository, FederatedRepository]
AnyPermission = Union[Permission, PermissionV2]

__all__ = [
Expand All @@ -50,6 +57,8 @@
"LocalRepositoryResponse",
"RemoteRepository",
"RemoteRepositoryResponse",
"FederatedRepository",
"FederatedRepositoryResponse",
"SimpleRepository",
"VirtualRepository",
"VirtualRepositoryResponse",
Expand Down
73 changes: 73 additions & 0 deletions pyartifactory/models/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class RClassEnum(str, Enum):
local = "local"
virtual = "virtual"
remote = "remote"
federated = "federated"


class ChecksumPolicyType(str, Enum):
Expand Down Expand Up @@ -114,6 +115,18 @@ class ContentSynchronisation(BaseModel):
source: Source = Source()


class FederatedMembers(BaseModel):
url: str = ""
enabled: Literal["true", "false"] = "true"


class FederatedMembersResponse(BaseModel):
"""Models a federated member response."""

url: str = ""
enabled: bool = True


class SimpleRepository(BaseModel):
"""Models a simple repository."""

Expand Down Expand Up @@ -306,3 +319,63 @@ class RemoteRepositoryResponse(RemoteRepository):
enableVagrantSupport: bool = False
enableGitLfsSupport: bool = False
enableDistRepoSupport: bool = False


class FederatedBaseRepostoryModel(BaseRepositoryModel):
"""
Models a basic federated repo without members as they can't be overwritten
and differ in response and request
"""

rclass: Literal[RClassEnum.federated] = RClassEnum.federated
checksumPolicyType: ChecksumPolicyType = ChecksumPolicyType.client_checksums
handleReleases: bool = True
handleSnapshots: bool = True
maxUniqueSnapshots: int = 0
maxUniqueTags: int = 0
debianTrivialLayout: bool = False
snapshotVersionBehavior: SnapshotVersionBehavior = SnapshotVersionBehavior.non_unique
suppressPomConsistencyChecks: bool = False
blackedOut: bool = False
xrayIndex: bool = False
propertySets: Optional[List[str]] = None
dockerApiVersion: str = "V2"
archiveBrowsingEnabled: bool = False
calculateYumMetadata: bool = False
yumRootDepth: int = 0
enableFileListsIndexing: bool = False
optionalIndexCompressionFormats: Optional[List[str]] = None
downloadRedirect: bool = False
cdnRedirect: bool = False
blockPushingSchema1: bool = False
primaryKeyPairRef: Optional[str] = None
secondaryKeyPairRef: Optional[str] = None
priorityResolution: bool = False
cargoInternalIndex: bool = False


class FederatedRepository(FederatedBaseRepostoryModel):
"""Models a federated Repository (member model differs from reponse)."""

members: List[FederatedMembers] = []


class FederatedRepositoryResponse(FederatedBaseRepostoryModel):
"""Models a federated repository response (member model differs from request)."""

members: List[FederatedMembersResponse] = []
enableComposerSupport: bool = False
enableNuGetSupport: bool = False
enableGemsSupport: bool = False
enableNpmSupport: bool = False
enableBowerSupport: bool = False
enableCocoaPodsSupport: bool = False
enableConanSupport: bool = False
enableDebianSupport: bool = False
enablePypiSupport: bool = False
enablePuppetSupport: bool = False
enableDockerSupport: bool = False
forceNugetAuthentication: bool = False
enableVagrantSupport: bool = False
enableGitLfsSupport: bool = False
enableDistRepoSupport: bool = False
59 changes: 45 additions & 14 deletions pyartifactory/objects/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
from typing import List, Union, overload

import requests
from pydantic import ValidationError
from requests import Response

from pyartifactory.exception import ArtifactoryError, RepositoryAlreadyExistsError, RepositoryNotFoundError
from pyartifactory.models import AnyRepository, AnyRepositoryResponse
from pyartifactory.models.repository import (
FederatedRepository,
FederatedRepositoryResponse,
LocalRepository,
LocalRepositoryResponse,
RClassEnum,
RemoteRepository,
RemoteRepositoryResponse,
SimpleRepository,
Expand All @@ -35,18 +37,32 @@ def get_repo(self, repo_name: str) -> AnyRepositoryResponse:
"""
Finds repository in artifactory. Raises an exception if the repo doesn't exist.
:param repo_name: Name of the repository to retrieve
:return: Either a local, virtual or remote repository
:return: Either a local, virtual, remote or federated repository
"""
try:
response = self._get(f"api/{self._uri}/{repo_name}")
response_data = response.json()
rclass = None

try:
artifact_info: AnyRepositoryResponse = LocalRepositoryResponse.model_validate(response.json())
except ValidationError:
try:
artifact_info = VirtualRepositoryResponse.model_validate(response.json())
except ValidationError:
artifact_info = RemoteRepositoryResponse.model_validate(response.json())
return artifact_info
rclass = response_data["rclass"]
except KeyError:
raise KeyError('"rclass" key not found in the response data received by artifactory.')

# Match to the correct repository type depending on the rclass
if rclass == RClassEnum.local:
return LocalRepositoryResponse.model_validate(response_data)
elif rclass == RClassEnum.virtual:
return VirtualRepositoryResponse.model_validate(response_data)
elif rclass == RClassEnum.remote:
return RemoteRepositoryResponse.model_validate(response_data)
elif rclass == RClassEnum.federated:
return FederatedRepositoryResponse.model_validate(response_data)
else:
# this should never happen and is a missing repotype in the library
raise ArtifactoryError(
f"Unknown repository type found in response: {rclass}. Please report this issue.",
)
except requests.exceptions.HTTPError as error:
http_response: Union[Response, None] = error.response
if isinstance(http_response, Response) and http_response.status_code in (404, 400):
Expand All @@ -66,11 +82,19 @@ def create_repo(self, repo: VirtualRepository) -> VirtualRepositoryResponse:
def create_repo(self, repo: RemoteRepository) -> RemoteRepositoryResponse:
...

def create_repo(self, repo: AnyRepository) -> AnyRepositoryResponse:
@overload
def create_repo(self, repo: FederatedRepository) -> FederatedRepositoryResponse:
...

def create_repo(
self,
repo: AnyRepository,
) -> AnyRepositoryResponse:
"""
Creates a local, virtual or remote repository
:param repo: Either a local, virtual or remote repository
:return: LocalRepositoryResponse, VirtualRepositoryResponse or RemoteRepositoryResponse object
Creates a local, virtual, remote or federated repository
:param repo: Either a local, virtual, remote or federated repository
:return: LocalRepositoryResponse, VirtualRepositoryResponse, RemoteRepositoryResponse
or FederatedRepositoryResponse object
"""
repo_name = repo.key
try:
Expand Down Expand Up @@ -99,7 +123,14 @@ def update_repo(self, repo: VirtualRepository) -> VirtualRepositoryResponse:
def update_repo(self, repo: RemoteRepository) -> RemoteRepositoryResponse:
...

def update_repo(self, repo: AnyRepository) -> AnyRepositoryResponse:
@overload
def update_repo(self, repo: FederatedRepository) -> FederatedRepositoryResponse:
...

def update_repo(
self,
repo: AnyRepository,
) -> AnyRepositoryResponse:
"""
Updates a local, virtual or remote repository
:param repo: Either a local, virtual or remote repository
Expand Down
Loading

0 comments on commit 39acb68

Please sign in to comment.