Artifactory repository enforcement
diff --git a/_modules/artifactory_repo.py b/_modules/artifactory_repo.py
new file mode 100644
index 0000000..674d0fc
--- /dev/null
+++ b/_modules/artifactory_repo.py
@@ -0,0 +1,328 @@
+# -*- 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': 'http://%s:%s/artifactory/api' % (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)