pyartifactory is a Python library to access the Artifactory REST API.
This library enables you to manage Artifactory resources such as users, groups, permissions, repositories, artifacts and access tokens in your applications. Based on Python 3.8+ type hints.
- Requirements
- Install
- Usage
- Authentication
- SSL Cert Verification Options
- Timeout option
- Admin objects
- Artifacts
- Get the information about a file or folder
- Deploy an artifact
- Deploy an artifact with properties
- Deploy an artifact by checksums
- Download an artifact
- Retrieve artifact list
- Retrieve artifact properties
- Set artifact properties
- Update artifact properties
- Retrieve artifact stats
- Copy artifact to a new location
- Move artifact to a new location
- Delete an artifact
- Builds
- Contributing
- Python 3.8+
pip install pyartifactory
Since Artifactory 6.6.0 there is version 2 of the REST API for permission management, in case you have that version or higher, you need to pass api_version=2 to the constructor when you instantiate the class.
from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'), api_version=1)
from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", access_token="your-access-token")
Note:
- If you set both
access_tokenandauth, the access_token authentication will be chosen - If you do not set any authentication method, API calls will be done without authentication (anonymous)
Specify a local cert to use as client side certificate
from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'), cert="/path_to_file/server.pem", api_version=1)
Specify a local cert to use as custom CA certificate
from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'), verify="/path_to_file/ca.pem", cert="/path_to_file/server.pem", api_version=1)
verifyandcertconfigure certificates for distinct purposes.verifydetermines SSL/TLS certificate validation for the server, whilecertsupplies a client certificate for mutual authentication, as required by the server. You can use either one or both parameters as needed.
Disable host cert verification
from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'), verify=False, api_version=1)
verifycan be also set as a boolean to enable/disable SSL host verification.
Use timeout option to limit connect and read timeout in case the artifactory server is not responding in a timely manner.
from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'), api_version=1, timeout=60)
timeoutis None by default.
First, you need to create a new Artifactory object.
from pyartifactory import Artifactory art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'))
Get the list of users:
users = art.users.list()
Get a single user:
user = art.users.get("test_user")
Create a user:
from pyartifactory.models import NewUser # Create User user = NewUser(name="test_user", password="test_password", email="[email protected]") new_user = art.users.create(user) # Update user user.email = "[email protected]" updated_user = art.users.update(user)
Update a user:
from pyartifactory.models import User user = art.users.get("test_user") # Update user user.email = "[email protected]" updated_user = art.users.update(user)
Delete a user:
art.users.delete("test_user")
Unlock a user:
art.users.unlock("test_user")
Get the list of groups:
groups = art.groups.list()
Get a single group:
group = art.groups.get("group_name")
Create/Update a group:
from pyartifactory.models import Group # Create a Group group = Group(name="test_group", description="test_group") new_group = art.groups.create(group) # Update a Group group.description = "test_group_2" updated_group = art.groups.update(group)
Delete a group:
art.groups.delete("test_group")
A set of methods for performing operations on apiKeys, passwords ...
>>> art.security. art.security.create_api_key( art.security.get_encrypted_password( art.security.revoke_api_key( art.security.get_api_key( art.security.regenerate_api_key( art.security.revoke_user_api_key(
Create an access token:
token = art.security.create_access_token(user_name='artifactory_user', refreshable=True, scope="applied-permissions/user")
Revoke an existing revocable token:
art.security.revoke_access_token(token.access_token)
Get the list of repositories:
repositories = art.repositories.list()
Get a single repository
repo = art.repositories.get_repo("repo_name") # According to the repo type, you'll have either a local, virtual or remote repository returned
Create/Update a repository:
from pyartifactory.models import ( LocalRepository, VirtualRepository, RemoteRepository, FederatedRepository ) # Create local repo local_repo = LocalRepository(key="test_local_repo") new_local_repo = art.repositories.create_repo(local_repo) # Create virtual repo virtual_repo = VirtualRepository(key="test_virtual_repo") new_virtual_repo = art.repositories.create_repo(virtual_repo) # Create remote repo remote_repo = RemoteRepository(key="test_remote_repo", url="http://test-url.com") 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" updated_local_repo = art.repositories.update_repo(local_repo)
Delete a repository:
art.repositories.delete("test_local_repo")
Get the list of permissions:
permissions = art.permissions.list()
Get a single permission:
users = art.permissions.get("test_permission")
Create/Update a permission:
from pyartifactory.models import Permission # Create a permission permission = Permission( **{ "name": "test_permission", "repositories": ["test_repository"], "principals": { "users": {"test_user": ["r", "w", "n", "d"]}, "groups": {"developers": ["r"]}, }, } ) perm = art.permissions.create(permission) # Update permission permission.repositories = ["test_repository_2"] updated_permission = art.permissions.update(permission)
from pyartifactory import Artifactory from pyartifactory.models import PermissionV2 from pyartifactory.models.permission import PermissionEnumV2, PrincipalsPermissionV2, RepoV2, BuildV2, ReleaseBundleV2 # To use PermissionV2, make sure to set api_version=2 art = Artifactory(url="ARTIFACTORY_URL", auth=('USERNAME','PASSWORD_OR_API_KEY'), api_version=2) # Create a permission permission = PermissionV2( name="test_permission", repo=RepoV2( repositories=["test_repository"], actions=PrincipalsPermissionV2( users={ "test_user": [ PermissionEnumV2.read, PermissionEnumV2.annotate, PermissionEnumV2.write, PermissionEnumV2.delete, ] }, groups={ "developers": [ PermissionEnumV2.read, PermissionEnumV2.annotate, PermissionEnumV2.write, PermissionEnumV2.delete, ], }, ), includePatterns=["**"], excludePatterns=[], ), build=BuildV2( actions=PrincipalsPermissionV2( users={ "test_user": [ PermissionEnumV2.read, PermissionEnumV2.write, ] }, groups={ "developers": [ PermissionEnumV2.read, PermissionEnumV2.write, ], }, ), includePatterns=[""], excludePatterns=[""], ), releaseBundle=ReleaseBundleV2( repositories=["release-bundles"], actions=PrincipalsPermissionV2( users={ "test_user": [ PermissionEnumV2.read, ] }, groups={ "developers": [ PermissionEnumV2.read, ], }, ), includePatterns=[""], excludePatterns=[""], ) # You don't have to set all the objects repo, build and releaseBundle # If you only need repo for example, you can set only the repo object ) perm = art.permissions.create(permission) # Update permission permission.repo.repositories = ["test_repository_2"] updated_permission = art.permissions.update(permission)
Delete a permission:
art.permissions.delete("test_permission")
artifact_info = art.artifacts.info("<ARTIFACT_PATH_IN_ARTIFACTORY>") # file_info = art.artifacts.info("my-repository/my/artifact/directory/file.txt") # folder_info = art.artifacts.info("my-repository/my/artifact/directory")
artifact = art.artifacts.deploy("<LOCAL_FILE_LOCATION>", "<ARTIFACT_PATH_IN_ARTIFACTORY>") # artifact = art.artifacts.deploy("Desktop/myNewFile.txt", "my-repository/my/new/artifact/directory/file.txt")
artifact = art.artifacts.deploy("<LOCAL_FILE_LOCATION>", "<ARTIFACT_PATH_IN_ARTIFACTORY>", "<PROPERTIES>") # artifact = art.artifacts.deploy("Desktop/myNewFile.txt", "my-repository/my/new/artifact/directory/file.txt", {"retention": ["30"]})
artifact = art.artifacts.deploy("<LOCAL_FILE_LOCATION>", "<ARTIFACT_PATH_IN_ARTIFACTORY>", checksum_enabled=True) # artifact = art.artifacts.deploy("Desktop/myNewFile.txt", "my-repository/my/new/artifact/directory/file.txt", checksums=True)
Deploy an artifact to the specified destination by checking if the artifact content already exists in Artifactory.
If Artifactory already contains a user-readable artifact with the same checksum the artifact content is copied over to the new location and returns a response without requiring content transfer.
Otherwise, a 404 error is returned to indicate that content upload is expected in order to deploy the artifact.
Note: The performance might suffer when deploying artifacts with checksums enabled.
artifact = art.artifacts.download("<ARTIFACT_PATH_IN_ARTIFACTORY>", "<LOCAL_DIRECTORY_PATH>") # artifact = art.artifacts.download("my-artifactory-repository/my/new/artifact/file.txt", "Desktop/my/local/directory") # The artifact location is returned by the download method # If you have not set a <LOCAL_DIRECTORY_PATH>, the artifact will be downloaded in the current directory
artifacts = art.artifacts.list("<ARTIFACT_PATH_IN_ARTIFACTORY>") # files_only = art.artifacts.list("<ARTIFACT_PATH_IN_ARTIFACTORY>", list_folders=False) # non_recursive = art.artifacts.list("<ARTIFACT_PATH_IN_ARTIFACTORY>", recursive=False) # max_depth = art.artifacts.list("<ARTIFACT_PATH_IN_ARTIFACTORY>", depth=3)
artifact_properties = art.artifacts.properties("<ARTIFACT_PATH_IN_ARTIFACTORY>") # returns all properties # artifact_properties = art.artifacts.properties("my-repository/my/new/artifact/directory/file.txt") artifact_properties = art.artifacts.properties("<ARTIFACT_PATH_IN_ARTIFACTORY>", ["prop1", "prop2"]) # returns specific properties artifact_properties.properties["prop1"] # ["value1", "value1-bis"]
artifact_properties = art.artifacts.set_properties("<ARTIFACT_PATH_IN_ARTIFACTORY>", {"prop1": ["value"], "prop2": ["value1", "value2", "etc"}) # recursive mode is enabled by default artifact_properties = art.artifacts.set_properties("<ARTIFACT_PATH_IN_ARTIFACTORY>", {"prop1": ["value"], "prop2": ["value1", "value2", "etc"]}, False) # disable recursive mode
artifact_properties = art.artifacts.update_properties("<ARTIFACT_PATH_IN_ARTIFACTORY>", {"prop1": ["value"], "prop2": ["value1", "value2", "etc"}) # recursive mode is enabled by default artifact_properties = art.artifacts.update_properties("<ARTIFACT_PATH_IN_ARTIFACTORY>", {"prop1": ["value"], "prop2": ["value1", "value2", "etc"}, False) # disable recursive mode
artifact_stats = art.artifacts.stats("<ARTIFACT_PATH_IN_ARTIFACTORY>") # artifact_stats = art.artifacts.stats("my-repository/my/new/artifact/directory/file.txt")
artifact = art.artifacts.copy("<CURRENT_ARTIFACT_PATH_IN_ARTIFACTORY>","<NEW_ARTIFACT_PATH_IN_ARTIFACTORY>") # If you want to run a dryRun test, you can do the following: # artifact = art.artifacts.copy("my-repository/current/artifact/path/file.txt","my-repository/new/artifact/path/file.txt", dryrun=True) # It will return properties of the newly copied artifact
artifact = art.artifacts.move("<CURRENT_ARTIFACT_PATH_IN_ARTIFACTORY>","<NEW_ARTIFACT_PATH_IN_ARTIFACTORY>") # You can also run a dryRun test with the move operation # It will return properties of the newly moved artifact
art.artifacts.delete("<ARTIFACT_PATH_IN_ARTIFACTORY>")
build_list: BuildListResponse = art.builds.list()
build_runs: BuildRuns = art.builds.get_build_runs("<build_name>")
build_info: BuildInfo = art.builds.get_build_info("<build_name>", "<build_number>")
Note: optional BuildProperties can be used to query the correct build info of interest.
build_properties = BuildProperties(diff="<older_build>") build_info: BuildInfo = art.builds.get_build_info("<build_name>", "<build_number>", properties=build_properties) # build_info contains diff between <build_number> and <older_build>
# started is the earliest build time to return build_properties = BuildProperties(started="<yyyy-MM-dd'T'HH:mm:ss.SSSZ>") build_info: BuildInfo = art.builds.get_build_info("<build_name>", "<build_number>", properties=build_properties)
build_create_request = BuildCreateRequest(name="<build_name>", number="<build_number>", started="<Build start time in the format of yyyy-MM-dd'T'HH:mm:ss.SSSZ>") create_build = art.builds.create_build(build_create_request)
build_promote_request = BuildPromotionRequest(sourceRepo="<source-jfrog-repo>", targetRepo="<target-jfrog-repo>") promote_build: BuildPromotionResult = art.builds.promote_build("<build_name>", "<build_number>", build_promote_request)
build_delete_request = BuildDeleteRequest(buildName="<build_name>", buildNumbers=["<build_number>", "<another_build_number>", ...]) art.builds.delete(build_delete_request)
build_delete_request = BuildDeleteRequest(buildName="<build_name>", deleteAll=True) art.builds.delete(build_delete_request)
art.builds.build_rename("<build_name>", "<new_build_name>")
build_diffs: BuildDiffResponse = art.builds.build_diff("<build_name>", "<build_number>", "<older_build_number>")
Please read the Development - Contributing guidelines.