Refactor configuration
- split client SLS to config and repo
- replace modules artifactory_config and artifactory_repo by the single
module named `artifactory`
Change-Id: I0fa2dadc2443dbbd40bb10f3745dc4330f0c4578
diff --git a/README.rst b/README.rst
index f9be099..60ac3ec 100644
--- a/README.rst
+++ b/README.rst
@@ -84,6 +84,20 @@
repo_type: remote
url: "http://totheremoterepo:80/"
+
+Repository configuration
+========================
+
+Sample pillar above shows basic repository configuration, but you can use any parameters
+described in https://www.jfrog.com/confluence/display/RTF/Repository+Configuration+JSON
+
+This module does direct map from pillar parameters to repository JSON description
+with two aliases for compatibility:
+
+ * repo_type -> rclass
+ * package_type -> packageType
+
+
Read more
=========
@@ -91,6 +105,7 @@
* https://www.jfrog.com/confluence/display/RTF/PostgreSQL
* https://www.jfrog.com/confluence/display/RTF/Artifactory+REST+API#ArtifactoryRESTAPI-REPOSITORIES
* https://www.jfrog.com/confluence/display/RTF/Repository+Configuration+JSON
+
Documentation and Bugs
======================
diff --git a/_modules/artifactory.py b/_modules/artifactory.py
new file mode 100644
index 0000000..6987ada
--- /dev/null
+++ b/_modules/artifactory.py
@@ -0,0 +1,251 @@
+# -*- coding: utf-8 -*-
+'''
+Module for configuring Artifactory.
+===================================
+'''
+
+import json
+import logging
+import requests
+
+from collections import OrderedDict
+
+from lxml import etree
+from lxml import objectify
+
+
+log = logging.getLogger(__name__)
+
+
+def _api_call(endpoint, data=None, headers=None, method='GET',
+ **connection_args):
+
+ log.debug('Got connection args: {}'.format(connection_args))
+
+ # Set default values if empty
+ if 'proto' not in connection_args:
+ connection_args['proto'] = 'http'
+ if 'host' not in connection_args:
+ connection_args['host'] = 'localhost'
+ if 'port' not in connection_args:
+ connection_args['port'] = 80
+
+ base_url = connection_args.get(
+ 'url',
+ '{proto}://{host}:{port}/artifactory'.format(**connection_args)
+ )
+ api_url = base_url + '/api'
+
+ username = connection_args.get('user', 'admin')
+ password = connection_args.get('password', 'password')
+ ssl_verify = connection_args.get('ssl_verify', True)
+
+ # Prepare session object
+ api_connection = requests.Session()
+ api_connection.auth = (username, password)
+ api_connection.verify = ssl_verify
+
+ # Override default method if data given
+ if(data and method == 'GET'):
+ method = 'POST'
+
+ endpoint_url = api_url + endpoint
+ log.debug('Doing {0} request to {1}'.format(method, endpoint_url))
+
+ # API call request
+ resp = api_connection.request(
+ method=method,
+ url=endpoint_url,
+ data=data,
+ headers=headers
+ )
+
+ if resp.status_code == requests.codes.ok:
+ return True, resp.text
+ else:
+ errors = json.loads(resp.text).get('errors')
+ if errors:
+ for error in errors:
+ log.error('%(status)s:%(message)s' % error)
+ else:
+ log.error('%(status)s:%(message)s' % json.loads(resp.text))
+ return False, json.loads(resp.text)
+
+
+def get_license(**kwargs):
+ endpoint = '/system/license'
+
+ return _api_call(endpoint, **kwargs)
+
+
+def add_license(license_key, **kwargs):
+ endpoint = '/system/license'
+
+ change_data = {
+ 'licenseKey': license_key,
+ }
+
+ return _api_call(
+ endpoint=endpoint,
+ data=json.dumps(change_data),
+ headers={'Content-Type': 'application/json'},
+ **kwargs
+ )
+
+def get_config(**kwargs):
+ endpoint = '/system/configuration'
+
+ return _api_call(endpoint, **kwargs)
+
+
+def set_config(config_data, **kwargs):
+ endpoint = '/system/configuration'
+
+ return _api_call(
+ endpoint=endpoint,
+ data=config_data,
+ headers={'Content-Type': 'application/xml'},
+ **kwargs
+ )
+
+
+def get_ldap_config(name, **kwargs):
+
+ result, config_data = get_config(**kwargs)
+ config = objectify.fromstring(config_data.encode('ascii'))
+
+ # Find existing LDAP settings with specified key ...
+ ldap_config = None
+ for ldap_setting_iter in config.security.ldapSettings.getchildren():
+ if ldap_setting_iter.key.text == name:
+ ldap_config = ldap_setting_iter
+ break
+
+ # ... and create new one if not exists
+ if ldap_config is None:
+ ldap_config = objectify.SubElement(
+ config.security.ldapSettings, 'ldapSetting')
+ objectify.SubElement(ldap_config, 'key')._setText(name)
+
+ return result, etree.tostring(ldap_config)
+
+def set_ldap_config(name, uri, base=None, enabled=True, dn_pattern=None,
+ manager_dn=None, manager_pass=None, search_subtree=True,
+ search_filter='(&(objectClass=inetOrgPerson)(uid={0}))',
+ attr_mail='mail', create_users=True, safe_search=True,
+ **kwargs):
+
+ result, config_data = get_config(**kwargs)
+ config = objectify.fromstring(config_data.encode('ascii'))
+
+ # NOTE! Elements must ber sorted in exact order!
+ key_map = OrderedDict([
+ ('enabled', 'enabled'),
+ ('ldapUrl', 'uri'),
+ ('userDnPattern', 'dn_pattern'),
+ ('search', ''),
+ ('autoCreateUser', 'create_users'),
+ ('emailAttribute', 'attr_mail'),
+ ('ldapPoisoningProtection', 'safe_search'),
+ ])
+
+ key_map_search = OrderedDict([
+ ('searchFilter', 'search_filter'),
+ ('searchBase', 'base'),
+ ('searchSubTree', 'search_subtree'),
+ ('managerDn', 'manager_dn'),
+ ('managerPassword', 'manager_pass'),
+ ])
+
+ # Find existing LDAP settings with specified key ...
+ ldap_config = None
+ for ldap_setting_iter in config.security.ldapSettings.getchildren():
+ if ldap_setting_iter.key.text == name:
+ ldap_config = ldap_setting_iter
+ search_config = ldap_config.search
+ break
+
+ # ... and create new one if not exists
+ if ldap_config is None:
+ ldap_config = objectify.SubElement(
+ config.security.ldapSettings, 'ldapSetting')
+ objectify.SubElement(ldap_config, 'key')._setText(name)
+
+ # LDAP options
+ for xml_key, var_name in key_map.iteritems():
+
+ # Search subtree must follow element order
+ if xml_key == 'search' and not hasattr(ldap_config, 'search'):
+ search_config = objectify.SubElement(ldap_config, 'search')
+ break
+
+ if var_name in locals():
+ # Replace None with empty strings
+ var_value = locals()[var_name] or ''
+ if isinstance(var_value, bool):
+ # Boolean values should be lowercased
+ xml_text = str(var_value).lower()
+ else:
+ xml_text = str(var_value)
+
+ if hasattr(ldap_config, xml_key):
+ ldap_config[xml_key]._setText(xml_text)
+ else:
+ objectify.SubElement(ldap_config, xml_key)._setText(
+ xml_text)
+
+ # Search options (same code as above but using search_config)
+ for xml_key, var_name in key_map_search.iteritems():
+ if var_name in locals():
+ # Replace None with empty strings
+ var_value = locals()[var_name] or ''
+ if isinstance(var_value, bool):
+ # Boolean values should be lowercased
+ xml_text = str(var_value).lower()
+ else:
+ xml_text = str(var_value)
+
+ if hasattr(search_config, xml_key):
+ search_config[xml_key]._setText(xml_text)
+ else:
+ objectify.SubElement(search_config, xml_key)._setText(
+ xml_text)
+
+ change_data = etree.tostring(config)
+
+ return set_config(change_data, **kwargs)
+
+
+def list_repos(**kwargs):
+ endpoint = '/repositories'
+
+ return _api_call(endpoint, **kwargs)
+
+
+def get_repo(name, **kwargs):
+ result, repo_list = list_repos(**kwargs)
+ if name in [r['key'] for r in json.loads(repo_list)]:
+ endpoint = '/repositories/' + name
+ return _api_call(endpoint, **kwargs)
+ else:
+ return True, {}
+
+
+def set_repo(name, repo_config, **kwargs):
+ log.debug('Got repo parameters: {}'.format(repo_config))
+
+ result, repo_list = list_repos(**kwargs)
+ if name in [r['key'] for r in json.loads(repo_list)]:
+ method = 'POST'
+ else:
+ method = 'PUT'
+
+ endpoint = '/repositories/' + name
+
+ return _api_call(
+ endpoint=endpoint,
+ method=method,
+ data=json.dumps(repo_config),
+ headers={'Content-Type': 'application/json'},
+ **kwargs
+ )
diff --git a/_modules/artifactory_config.py b/_modules/artifactory_config.py
deleted file mode 100644
index 5fa4e66..0000000
--- a/_modules/artifactory_config.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
-Module for configuring Artifactory.
-change admin password
-add license key
-confingure ldap
-'''
-
-# 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_config'
-
-
-def __virtual__():
-
- return True
-
-
-
-# "repoLayoutRef" : "maven-2-default",
-
-class Artifactoryconfig:
-
- def __init__(self, config={}):
-
- self.files = []
- self.def_password = 'password'
- self.def_user= 'admin'
-
-
- client_config = {
- 'artifactory_url': 'http://your-instance/artifactory/api',
- 'username': 'your-user',
- 'password': 'password',
- 'license_key' :'key',
- 'artifactory_ldap_url': 'http://localhost',
-# 'headers': {'Content-type': 'application/json'},
- 'ssl_verify': True
- }
-
- 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 change_admin_password(self, **connection_args):
- """
- Usage: POST /api/security/users/authorization/changePassword -H "Content-type: application/json" -d ' { "userName" : "{user}", "oldPassword" : "{old password}", "newPassword1" : "{new password}", "newPassword2" : "{verify new password}" }
- :param connection_args:
- :return: 0 if ok
- """
-
- url = self.artifactory_url + '/security/users/authorization/changePassword'
- log.error(str(url))
- data_pass={ "userName": self.def_user, "oldPassword": self.def_password, "newPassword2": self.password,"newPassword1": self.password}
- auth = (self.username, self.def_password)
-
- r = requests.post(url, auth=auth, json=data_pass)
- log.error(str(r.text))
- return r
-
- def add_license_key(self, **connection_args):
- """
- Usage: POST /api/system/license
- :param connection_args:
- :return: 0 if ok
- """
- url = self.artifactory_url +'/system/license'
- log.error(str(url))
- auth = (self.username, self.password)
- key = {"licenseKey": self.license_key}
- log.error(str(key))
- r = requests.post(url, auth=auth, json=key)
- log.error(str(r.text))
- return r
-
- def configure_ldap(self, **connection_args):
- url = self.artifactory_url + '/system/configuration'
- auth = (self.username, self.password)
- # r = requests.post(url,auth=auth,json=data)
-
- r = requests.get(url, auth=auth)
- # print json.dumps(r.text)
- #log.error(str(r.text))
-
- ldap_url = self.artifactory_ldap_url
- searchFilter = "uid={0}"
- xmlTemplate = """
- <ldapSetting>
- <key>ldap</key>
- <enabled>true</enabled>
- <ldapUrl>%(url)s</ldapUrl>
- <search>
- <searchFilter>%(sf)s</searchFilter>
- <searchSubTree>true</searchSubTree>
- </search>
- <autoCreateUser>true</autoCreateUser>
- <emailAttribute>mail</emailAttribute>
- <ldapPoisoningProtection>true</ldapPoisoningProtection>
- </ldapSetting>
- """
- xml_date = {'url': ldap_url, 'sf': searchFilter}
- a = xmlTemplate % xml_date
-# log.error(str( r.text))
- z = str(r.text).split('<ldapSettings/>')
- out = str(z[0] + '<ldapSettings>' + a + '</ldapSettings>' + z[1])
-
- # out=str(r.text).split('<ldapSettings/>')[0]+'<ldapSettings/>'+str(r.text).split('<ldapSettings/>')[1]
- headers = {'Content-Type': 'application/xml'}
-
- r = requests.post(url, auth=auth, data=out, headers=headers)
- log.error(str(r.text))
- return r
-
-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')),
- 'ssl_verify': get('ssl_verify', True),'license_key':get('license_key','key'),'artifactory_ldap_url':get('ldap_server','url'),
- 'ldap_searchFilter':get('ldap_searchFilter','uid={0}'),'ldap_account_base':get('ldap_account_base','accaunt')
- }
-
- user = get('user', False)
- password = get('password', False)
- if user and password:
- client_config['username'] = user
- client_config['password'] = password
-
- artifactory_config = Artifactoryconfig(client_config)
-
- return artifactory_config
-
-
-
-def artifactory_init(**connection_args):
-
- artifactory = _client(**connection_args)
- artifactory.change_admin_password()
- artifactory.add_license_key()
- artifactory.configure_ldap()
-
diff --git a/_modules/artifactory_repo.py b/_modules/artifactory_repo.py
deleted file mode 100644
index a97d215..0000000
--- a/_modules/artifactory_repo.py
+++ /dev/null
@@ -1,330 +0,0 @@
-# -*- 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'},
- 'ssl_verify': True
- }
-
- 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, verify=self.ssl_verify)
- 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, verify=self.ssl_verify)
- elif query_type == "put":
- response = requests.put(query, data=query.split('?', 1)[1], auth=auth, headers=self.headers, verify=self.ssl_verify)
- 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')),
- 'ssl_verify': get('ssl_verify', True)
- }
-
- 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)
diff --git a/_states/artifactory.py b/_states/artifactory.py
new file mode 100644
index 0000000..ac40b1a
--- /dev/null
+++ b/_states/artifactory.py
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+'''
+Management of artifactory configuration
+=======================================
+'''
+
+
+def __virtual__():
+ if 'artifactory.get_license' in __salt__:
+ return 'artifactory'
+ else:
+ return False, 'Execution module "artifactory" is not loaded'
+
+
+def add_license_key(name, license_key, **kwargs):
+
+ kwargs = __salt__['pillar.get']('artifactory:client:server')
+ kwargs.pop('license_key', None)
+
+ result, old_license_data = __salt__['artifactory.get_license'](**kwargs)
+
+ result, res_data = __salt__['artifactory.add_license'](
+ license_key,
+ **kwargs
+ )
+
+ # Prepare data to return
+ ret = {
+ 'name': name,
+ 'changes': {},
+ 'result': result,
+ 'comment': '',
+ 'pchanges': {},
+ }
+
+ if result:
+ result, new_license_data = __salt__['artifactory.get_license'](**kwargs)
+
+ if old_license_data != new_license_data:
+ ret['changes'] = {
+ 'old': json.dumps(old_license_data),
+ 'new': json.dumps(new_license_data),
+ }
+ ret['comment'] = res_data
+ else:
+ ret['comment'] = res_data['message']
+ if ret['comment'] == ('License could not be installed due '
+ 'to an error: License already exists.'):
+ ret['result'] = True
+
+ return ret
+
+def configure_ldap(name, uri, base=None, enabled=True, dn_pattern=None,
+ manager_dn=None, manager_pass=None, search_subtree=True,
+ search_filter='(&(objectClass=inetOrgPerson)(uid={0}))',
+ attr_mail='mail', create_users=True, safe_search=True):
+
+ kwargs = __salt__['pillar.get']('artifactory:client:server')
+
+ result, ldap_config_old = __salt__['artifactory.get_ldap_config'](name, **kwargs)
+
+ result, res_data = __salt__['artifactory.set_ldap_config'](
+ name, uri, base, enabled, dn_pattern, manager_dn, manager_pass,
+ search_subtree, search_filter, attr_mail, create_users, safe_search,
+ **kwargs
+ )
+
+ # Prepare data to return
+ ret = {
+ 'name': name,
+ 'changes': {},
+ 'result': result,
+ 'comment': '',
+ 'pchanges': {},
+ }
+
+ if result:
+ result, ldap_config_new = __salt__['artifactory.get_ldap_config'](name, **kwargs)
+ if ldap_config_old != ldap_config_new:
+ ret['changes'] = {
+ 'old': ldap_config_old,
+ 'new': ldap_config_new,
+ }
+ ret['comment'] = res_data
+ else:
+ ret['comment'] = res_data.get('errors')[0]['message']
+
+ return ret
+
+def configure_repo(name, **kwargs):
+
+ repo_config = kwargs
+ repo_name = repo_config['key']
+
+ rclass = repo_config.pop('repo_type', 'local')
+ if 'rclass' not in repo_config:
+ repo_config['rclass'] = rclass
+
+ packageType = repo_config.pop('package_type', 'generic')
+ if 'packageType' not in repo_config:
+ repo_config['packageType'] = packageType
+
+ kwargs = __salt__['pillar.get']('artifactory:client:server')
+
+ result, repo_config_old = __salt__['artifactory.get_repo'](repo_name, **kwargs)
+
+ # Prepare data to return
+ ret = {
+ 'name': name,
+ 'changes': {},
+ 'result': result,
+ 'comment': '',
+ 'pchanges': {},
+ }
+
+ result, res_data = __salt__['artifactory.set_repo'](repo_name, repo_config, **kwargs)
+
+ if result:
+ result, repo_config_new = __salt__['artifactory.get_repo'](repo_name, **kwargs)
+ if repo_config_old != repo_config_new:
+ ret['changes'] = {
+ 'old': repo_config_old,
+ 'new': repo_config_new,
+ }
+ ret['comment'] = res_data
+ else:
+ ret['comment'] = res_data.get('errors')[0]['message']
+
+ return ret
diff --git a/_states/artifactory_config.py b/_states/artifactory_config.py
deleted file mode 100644
index 683ccc9..0000000
--- a/_states/artifactory_config.py
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
-Management of artifactory configuration
-======================================
-
-:depends: - requests Python module
-:configuration: See :py:mod:`salt.modules.artifactory` for setup instructions.
-'''
-
-def __virtual__():
- '''
- Only load if the artifactory module is in __salt__
- '''
- return True
-
-
-def artifactory_init( **kwargs):
-
- out = __salt__['artifactory_config.artifactory_init']( **kwargs)
-
- return out
diff --git a/_states/artifactory_repo.py b/_states/artifactory_repo.py
deleted file mode 100644
index e6265c5..0000000
--- a/_states/artifactory_repo.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
-Management of artifactory repositories
-======================================
-
-:depends: - requests Python module
-:configuration: See :py:mod:`salt.modules.artifactory` for setup instructions.
-
-.. code-block:: yaml
-
- local_artifactory_repo:
- artifactory_repo.repo_present:
- - name: remote_artifactory_repo
- - package_type: generic
- - repo_type: local
- remote_artifactory_repo:
- artifactory_repo.repo_present:
- - name: remote_artifactory_repo
- - repo_type: remote
- - url: "http://totheremoterepo:80/"
-
-'''
-
-def __virtual__():
- '''
- Only load if the artifactory module is in __salt__
- '''
- return True
-
-
-def repo_present(name, repo_type, package_type, url=None, **kwargs):
- '''
- Ensures that the artifactory repo exists
-
- :param name: new repo name
- :param description: short repo description
- '''
- ret = {'name': name,
- 'changes': {},
- 'result': True,
- 'comment': 'Repository "{0}" already exists'.format(name)}
-
- # Check if repo is already present
- repo = __salt__['artifactory_repo.repo_get'](name=name, **kwargs)
-
- if 'Error' not in repo:
- #update repo
- pass
- else:
- # Create repo
- __salt__['artifactory_repo.repo_create'](name, repo_type, package_type, url, **kwargs)
- ret['comment'] = 'Repository "{0}" has been added'.format(name)
- ret['changes']['repo'] = 'Created'
- return ret
diff --git a/artifactory/client.sls b/artifactory/client.sls
deleted file mode 100644
index 7588d7d..0000000
--- a/artifactory/client.sls
+++ /dev/null
@@ -1,24 +0,0 @@
-{% from "artifactory/map.jinja" import client with context %}
-{%- if client.enabled %}
-
-artifactory_client_install:
- pkg.installed:
- - names: {{ client.pkgs }}
-
-artifactory_config:
- artifactory_config.artifactory_init
-
-{%- for repo_name, repo in client.repo.iteritems() %}
-
-artifactory_client_repo_{{ repo_name }}:
- artifactory_repo.repo_present:
- - name: {{ repo_name }}
- - repo_type: {{ repo.repo_type }}
- - package_type: {{ repo.package_type }}
- {%- if repo.url is defined %}
- - url: {{ repo.url }}
- {%- endif %}
-
-{%- endfor %}
-
-{%- endif %}
diff --git a/artifactory/client/config.sls b/artifactory/client/config.sls
new file mode 100644
index 0000000..487ba4e
--- /dev/null
+++ b/artifactory/client/config.sls
@@ -0,0 +1,30 @@
+{% from "artifactory/map.jinja" import client with context %}
+{%- if client.server.license_key is defined %}
+add_license_data:
+ artifactory.add_license_key:
+ - license_key: {{client.server.license_key}}
+{%- endif %}
+
+{%- if client.server.ldap_server is defined %}
+ldap:
+ artifactory.configure_ldap:
+ - uri: {{client.server.ldap_server}}
+ - enabled: {{client.server.ldap_server_enabled|default('true')}}
+{%- if client.server.get('ldap_dn_pattern') %}
+ - dn_pattern: {{client.server.ldap_dn_pattern}}
+{%- endif %}
+{%- if client.server.get('ldap_account_base') %}
+ - base: {{client.server.ldap_account_base}}
+{%- endif %}
+{%- if client.server.get('ldap_searchFilter') %}
+ - search_filter: {{client.server.ldap_searchFilter}}
+{%- endif %}
+ - search_subtree: {{client.server.ldap_searchSubtree|default('true')}}
+{%- if client.server.get('ldap_managerDn') %}
+ - manager_dn: {{client.server.ldap_managerDn}}
+ - manager_pass: {{client.server.ldap_managerPass}}
+{%- endif %}
+ - attr_mail: {{client.server.ldap_attr_mail|default('mail')}}
+ - create_users: {{client.server.ldap_create_users|default('true')}}
+ - safe_search: {{client.server.ldap_safe_search|default('true')}}
+{%- endif %}
diff --git a/artifactory/client/init.sls b/artifactory/client/init.sls
new file mode 100644
index 0000000..cd5864c
--- /dev/null
+++ b/artifactory/client/init.sls
@@ -0,0 +1,13 @@
+{% from "artifactory/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+artifactory_client_install:
+ pkg.installed:
+ - names: {{ client.pkgs }}
+
+include:
+- artifactory.client.config
+{%- if client.repo is defined %}
+- artifactory.client.repo
+{%- endif %}
+{%- endif %}
diff --git a/artifactory/client/repo.sls b/artifactory/client/repo.sls
new file mode 100644
index 0000000..3ba728c
--- /dev/null
+++ b/artifactory/client/repo.sls
@@ -0,0 +1,11 @@
+{% from "artifactory/map.jinja" import client with context %}
+{%- for repo_name, repo in client.repo.iteritems() %}
+
+artifactory_repo_{{ repo_name }}:
+ artifactory.configure_repo:
+ - key: {{ repo_name }}
+{%- for key, value in repo.iteritems() %}
+ - {{key}}: {{value}}
+{%- endfor %}
+
+{%- endfor %}
diff --git a/artifactory/map.jinja b/artifactory/map.jinja
index 9decf29..5e2f5d5 100644
--- a/artifactory/map.jinja
+++ b/artifactory/map.jinja
@@ -25,6 +25,7 @@
{%- load_yaml as client_defaults %}
default:
pkgs:
+ - python-lxml
- python-requests
repo: {}
{%- endload %}