blob: 2efa12b5ebad03ad2b955bae779adb2defcc505f [file] [log] [blame]
# -*- coding: utf-8 -*-
'''
Module for fetching artifacts from Artifactory
'''
# Import python libs
from __future__ import absolute_import
import os
import base64
import logging
# Import Salt libs
import salt.utils
import salt.ext.six.moves.http_client # pylint: disable=import-error,redefined-builtin,no-name-in-module
from salt.ext.six.moves import urllib # pylint: disable=no-name-in-module
from salt.ext.six.moves.urllib.error import HTTPError, URLError # pylint: disable=no-name-in-module
import json
import requests
log = logging.getLogger(__name__)
__virtualname__ = 'artifactory_repo'
def __virtual__():
return True
repo_config = {
"key": "local-repo1",
"rclass" : "local",
"packageType": "generic",
"description": "The local repository public description",
}
# "repoLayoutRef" : "maven-2-default",
class ArtifactoryClient:
def __init__(self, config={}):
self.files = []
client_config = {
'artifactory_url': 'http://your-instance/artifactory/api',
'search_prop': 'search/prop',
'search_name': 'search/artifact',
'search_repos': 'repositories',
'username': 'your-user',
'password': 'password',
'headers': {'Content-type': 'application/json'}
}
client_config.update(config)
# Set instance variables for every value in party_config
for k, v in client_config.items():
setattr(self, '%s' % (k,), v)
def create_repository(self, name, config, **connection_args):
repositories = []
query = "%s/%s/%s" % (self.artifactory_url, self.search_repos, name)
auth = (self.username, self.password)
r = requests.put(query, auth=auth, json=config)
print(r.content)
raw_response = self.query_artifactory(query)
if raw_response is None:
return []
response = json.loads(raw_response.text)
for line in response:
for item in line:
repositories.append(line)
if repositories:
return repositories
return []
def get_repositories(self, repo_type=None, **connection_args):
repositories = []
if repo_type is None:
query = "%s/%s" % (self.artifactory_url, self.search_repos)
else:
query = "%s/%s?type=%s" % (self.artifactory_url,
self.search_repos, repo_type)
raw_response = self.query_artifactory(query)
if raw_response is None:
return []
response = json.loads(raw_response.text)
for line in response:
for item in line:
repositories.append(line)
if repositories:
return repositories
return []
def query_artifactory(self, query, query_type='get'):
"""
Send request to Artifactory API endpoint.
@param: query - Required. The URL (including endpoint) to send to the Artifactory API
@param: query_type - Optional. CRUD method. Defaults to 'get'.
"""
auth = (self.username, self.password)
query_type = query_type.lower()
if query_type == "get":
response = requests.get(query, auth=auth, headers=self.headers)
elif query_type == "put":
response = requests.put(query, data=query.split('?', 1)[1], auth=auth, headers=self.headers)
if query_type == "post":
pass
if not response.ok:
return None
return response
def query_file_info(self, filename):
"""
Send request to Artifactory API endpoint for file details.
@param: filename - Required. The shortname of the artifact
"""
query = "%s/storage/%s" % (self.artifactory_url, filename)
raw_response = self.query_artifactory(query)
if raw_response is None:
return raw_response
response = json.loads(raw_response.text)
return response
def find_by_properties(self, properties):
"""
Look up an artifact, or artifacts, in Artifactory by using artifact properties.
@param: properties - List of properties to use as search criteria.
"""
query = "%s/%s?%s" % (self.artifactory_url,
self.search_prop, urlencode(properties))
raw_response = self.query_artifactory(query)
if raw_response is None:
return raw_response
response = json.loads(raw_response.text)
for item in response['results']:
for k, v in item.items():
setattr(self, '%s' % (k,), v)
if not response['results']:
return None
artifact_list = []
for u in response['results']:
artifact_list.append(os.path.basename(u['uri']))
self.files = artifact_list
setattr(self, 'count', len(artifact_list))
return "OK"
def find(self, filename):
"""
Look up an artifact, or artifacts, in Artifactory by
its filename.
@param: filename - Filename of the artifact to search.
"""
query = "%s/%s?name=%s" % (self.artifactory_url,
self.search_name, filename)
raw_response = self.query_artifactory(query)
if raw_response is None:
return raw_response
response = json.loads(raw_response.text)
if len(response['results']) < 1:
return None
setattr(self, 'name', filename)
setattr(self, 'url', json.dumps(response))
return "OK"
def get_properties(self, filename, properties=None):
"""
Get an artifact's properties, as defined in the Properties tab in
Artifactory.
@param: filename - Filename of artifact of which to get properties.
@param: properties - Optional. List of properties to help filter results.
"""
if properties:
query = "%s?properties=%s" % (filename, ",".join(properties))
else:
query = "%s?properties" % filename
raw_response = self.query_artifactory(query)
if raw_response is None:
return raw_response
response = json.loads(raw_response.text)
for key, value in response.items():
setattr(self, '%s' % (key,), value)
return "OK"
def _client(**connection_args):
'''
Set up artifactory credentials
'''
prefix = "artifactory"
# look in connection_args first, then default to config file
def get(key, default=None):
return connection_args.get('connection_' + key,
__salt__['config.get'](prefix, {})).get(key, default)
client_config = {
'artifactory_url': '%s://%s:%s/artifactory/api' % (get('proto', 'http'), get('host', 'localhost'), get('port', '8080'))
}
user = get('user', False)
password = get('password', False)
if user and password:
client_config['username'] = user
client_config['password'] = password
artifactory_client = ArtifactoryClient(client_config)
return artifactory_client
def repo_list(repo_type=None, **connection_args):
'''
Return a list of available repositories
CLI Example:
.. code-block:: bash
salt '*' artifactory_repo.repo_list
salt '*' artifactory_repo.repo_list REMOTE
salt '*' artifactory_repo.repo_list LOCAL
'''
ret = {}
artifactory = _client(**connection_args)
repos = artifactory.get_repositories(repo_type)
for repo in repos:
if 'key' in repo:
ret[repo.get('key')] = repo
return ret
def repo_get(name, **connection_args):
'''
Return a list of available repositories
CLI Example:
.. code-block:: bash
salt '*' artifactory_repo.repo_get reponame
'''
ret = {}
repos = repo_list(None, **connection_args)
if not name in repos:
return {'Error': "Error retrieving repository {0}".format(name)}
ret[name] = repos[name]
return ret
def repo_create(name, repo_type="local", package="generic", url=None, **connection_args):
'''
Create a artifactory repository
:param name: new repo name
:param repo_type: new repo type
:param package: new repo package type
"gradle" | "ivy" | "sbt" | "nuget" | "gems" | "npm" | "bower" |
"debian" | "pypi" | "docker" | "vagrant" | "gitlfs" | "yum" |
"generic"
CLI Examples:
.. code-block:: bash
salt '*' artifactory_repo.repo_create projectname remote generic
'''
ret = {}
if url in connection_args and url == None:
url = connection_args['url']
repo = repo_get(name, **connection_args)
if repo and not "Error" in repo:
log.debug("Repository {0} exists".format(name))
return repo
repo_config = {
"key": name,
"rclass" : repo_type,
"packageType": package,
"description": "The local repository public description",
}
if repo_type == "remote":
repo_config['url'] = url
artifactory = _client(**connection_args)
artifactory.create_repository(name, repo_config)
return repo_get(name, **connection_args)