Gerrit client and project enforcement
diff --git a/README.rst b/README.rst
index a7f9cc3..0cca655 100644
--- a/README.rst
+++ b/README.rst
@@ -8,7 +8,7 @@
Sample pillars
==============
-Sipmple gerrit service
+Simple gerrit service
.. code-block:: yaml
@@ -20,6 +20,77 @@
address: https://gerrit-ci.gerritforge.com/job/Gerrit-stable-2.13/20/artifact/buck-out/gen/gerrit.war
hash: 2e17064b8742c4622815593ec496c571
+Full service setup
+
+.. code-block:: yaml
+
+ gerrit:
+ server:
+ canonical_web_url: http://10.10.10.148:8082/
+ email_private_key: ""
+ token_private_key: ""
+ initial_user:
+ full_name: John Doe
+ email: 'mail@jdoe.com'
+ username: jdoe
+ plugin:
+ download-commands:
+ engine: gerrit
+ # replication:
+ # engine: gerrit
+ reviewnotes:
+ engine: gerrit
+ singleusergroup:
+ engine: gerrit
+ ssh_rsa_key: |
+ -----BEGIN RSA PRIVATE KEY-----
+ MIIEowIBAAKCAQEAs0Y8mxS3dfs5zG8Du5vdBkfOCOng1IEUmFZIirJ8oBgJOd54
+ QgmkDFB7oP9eTCgz9k/rix1uJWhhVCMBzrWzH5IODO+tyy/tK66pv2BWtVfTDhBA
+ nShOLDNbSIBaV8E/NcrbnQN+b0alp4N7rQnavkOYl+JQncKjz1csmCodirscB9Oj
+ rdo6NG9olv9IQd/tDQxEeDyQkoW50aCEWcq7o+QaTzgnlrL+XZEzhzjdcvA9m8go
+ ...
+ jvMXms60iD/A5OpG33LWHNNzQBP486SxG75LB+Xs5sp5j2/b7VF5LJLhpGiJv9Mk
+ ydbuy8iuuvali2uF133kAlLqnrWfVTYQQI1OfW5glOv1L6kv94dU
+ -----END RSA PRIVATE KEY-----
+ ssh_rsa_key_pub: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzRjybFLd1+znMbwO7m90GR84I6eDUgRSYVkiKsnygGAk53nhCCaQMUHug/15MKDP2T+uLHW4laGFUIwHOtbMfkg4M763LL+0rrqm/YFa1V9MOEECdKE4sM1tIgFpXwT81ytudA35vRqWng3utCdq+Q5iX4lCdwqPPVyyYKh2KuxwH06Ot2jo0b2iW/0hB3+0NDER4PJCShbnRoIRZyruj5BpPOCeWsv5dkTOHON1y8D2byCgNGdCBIRx7x9Qb4dKK2F01r0/bfBGxELJzBdQ8XO14bQ7VOd3gTxrccTM4tVS7/uc/vtjiq7MKjnHGf/svbw9bTHAXbXcWXtOlRe51
+ email: mail@domain.com
+ auth:
+ engine: HTTP
+ source:
+ engine: http
+ address: https://gerrit-releases.storage.googleapis.com/gerrit-2.12.4.war
+ hash: sha256=45786a920a929c6258de6461bcf03ddec8925577bd485905f102ceb6e5e1e47c
+ database:
+ engine: postgresql
+ host: localhost
+ port: 5432
+ name: gerrit
+ user: gerrit
+ password: ${_param:postgresql_gerrit_password}
+
+Gerrit client enforcing projects
+
+.. code-block:: yaml
+
+ gerrit:
+ client:
+ enabled: True
+ server:
+ host: 10.10.10.148
+ user: newt
+ key: |
+ -----BEGIN RSA PRIVATE KEY-----
+ MIIEowIBAAKCAQEAs0Y8mxS3dfs5zG8Du5vdBkfOCOng1IEUmFZIirJ8oBgJOd54
+ QgmkDFB7oP9eTCgz9k/rix1uJWhhVCMBzrWzH5IODO+tyy/tK66pv2BWtVfTDhBA
+ ...
+ l1UrxQKBgEklBTuEiDRibKGXQBwlAYvK2He09hWpqtpt9/DVel6s4A1bbTWDHyoP
+ jvMXms60iD/A5OpG33LWHNNzQBP486SxG75LB+Xs5sp5j2/b7VF5LJLhpGiJv9Mk
+ ydbuy8iuuvali2uF133kAlLqnrWfVTYQQI1OfW5glOv1L6kv94dU
+ -----END RSA PRIVATE KEY-----
+ project:
+ test_salt_project:
+ enabled: true
+
Read more
=========
diff --git a/_modules/gerrit.py b/_modules/gerrit.py
new file mode 100644
index 0000000..c4048cf
--- /dev/null
+++ b/_modules/gerrit.py
@@ -0,0 +1,155 @@
+# -*- coding: utf-8 -*-
+'''
+Module for handling gerrit calls.
+
+:optdepends: - gerritlib Python adapter
+:configuration: This module is not usable until the following are specified
+ either in a pillar or in the minion's config file::
+
+ gerrit.host: localhost
+ gerrit.user: admin
+ gerrit.key: |
+ -----BEGIN RSA PRIVATE KEY-----
+ MIIEowIBAAKCAQEAs0Y8mxS3dfs5zG8Du5vdBkfOCOng1IEUmFZIirJ8oBgJOd54
+ ...
+ jvMXms60iD/A5OpG33LWHNNzQBP486SxG75LB+Xs5sp5j2/b7VF5LJLhpGiJv9Mk
+ ydbuy8iuuvali2uF133kAlLqnrWfVTYQQI1OfW5glOv1L6kv94dU
+ -----END RSA PRIVATE KEY-----
+
+'''
+
+from __future__ import absolute_import
+
+import logging
+import os
+
+LOG = logging.getLogger(__name__)
+
+# Import third party libs
+HAS_GERRIT = False
+try:
+ from gerritlib import gerrit
+ HAS_GERRIT = True
+except ImportError:
+ pass
+
+
+def __virtual__():
+ '''
+ Only load this module if gerrit
+ is installed on this minion.
+ '''
+ if HAS_GERRIT:
+ return 'gerrit'
+ return False
+
+__opts__ = {}
+
+
+def auth(**connection_args):
+ '''
+ Set up gerrit credentials
+
+ Only intended to be used within gerrit-enabled modules
+ '''
+
+ prefix = "gerrit"
+
+ # 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)
+
+ host = get('host', 'localhost')
+ user = get('user', 'admin')
+ keyfile = get('keyfile', '/var/cache/salt/minion/gerrit_rsa')
+
+ gerrit_client = gerrit.Gerrit(host, user, keyfile=keyfile)
+ return gerrit_client
+
+
+def project_create(name, **kwargs):
+ '''
+ Create a gerrit project
+
+ :param name: new project name
+
+ CLI Examples:
+
+ .. code-block:: bash
+
+ salt '*' gerrit.project_create namespace/nova description='nova project'
+
+ '''
+ ret = {}
+ gerrit_client = auth(**kwargs)
+
+ project = project_get(name, **kwargs)
+
+ if project and not "Error" in project:
+ LOG.debug("Project {0} exists".format(name))
+ return project
+
+ new = gerrit_client.createProject(name)
+ return project_get(name, **kwargs)
+
+def project_get(name, **kwargs):
+ '''
+ Return a specific project
+
+ CLI Examples:
+
+ .. code-block:: bash
+
+ salt '*' gerrit.project_get projectname
+ '''
+ gerrit_client = auth(**kwargs)
+ ret = {}
+
+ projects = gerrit_client.listProjects()
+ if not name in projects:
+ return {'Error': 'Error in retrieving project'}
+ ret[name] = {'name': name}
+ return ret
+
+
+def project_list(**connection_args):
+ '''
+ Return a list of available projects
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' gerrit.project_list
+ '''
+ gerrit_client = auth(**connection_args)
+ ret = {}
+
+ projects = gerrit_client.listProjects()
+
+ for project in projects:
+ ret[project] = {
+ 'name': project
+ }
+ return ret
+
+
+def query(change, **kwargs):
+ '''
+ Query gerrit
+
+ :param change: Query content
+
+ CLI Examples:
+
+ .. code-block:: bash
+
+ salt '*' gerrit.query 'status:open project:tools/gerrit limit:2'
+
+ '''
+ ret = {}
+ gerrit_client = auth(**kwargs)
+ msg = gerrit_client.query(change)
+ ret['query'] = msg
+ return ret
diff --git a/_states/gerrit.py b/_states/gerrit.py
new file mode 100644
index 0000000..8bbdb77
--- /dev/null
+++ b/_states/gerrit.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+'''
+Management of gerrit projects
+==============================
+
+:depends: - gerritlib Python module
+:configuration: See :py:mod:`salt.modules.gerrit` for setup instructions.
+
+.. code-block:: yaml
+
+ gerrit project:
+ gerrit.project_present:
+ - name: gerrit project
+
+'''
+
+
+def __virtual__():
+ '''
+ Only load if the gerrit module is in __salt__
+ '''
+ return 'gerrit' if 'gerrit.auth' in __salt__ else False
+
+
+def project_present(name, description=None, **kwargs):
+ '''
+ Ensures that the gerrit project exists
+
+ :param name: new project name
+ :param description: short project description
+ '''
+ ret = {'name': name,
+ 'changes': {},
+ 'result': True,
+ 'comment': 'Project "{0}" already exists'.format(name)}
+
+ # Check if project is already present
+ project = __salt__['gerrit.project_get'](name=name, **kwargs)
+
+ if 'Error' not in project:
+ #update project
+ pass
+ else:
+ # Create project
+ __salt__['gerrit.project_create'](name, **kwargs)
+ ret['comment'] = 'Project "{0}" has been added'.format(name)
+ ret['changes']['Project'] = 'Created'
+ return ret
diff --git a/gerrit/_modules/gerrit.py b/gerrit/_modules/gerrit.py
deleted file mode 100644
index 66cf0d3..0000000
--- a/gerrit/_modules/gerrit.py
+++ /dev/null
@@ -1,228 +0,0 @@
-# -*- coding: utf-8 -*-
-'''
-Module for handling gerrit calls.
-
-:optdepends: - gerritlib Python adapter
-:configuration: This module is not usable until the following are specified
- either in a pillar or in the minion's config file::
-
- gerrit.host: localhost
- gerrit.user: admin
- gerrit.keyfile: /tmp/key.pub
-
-'''
-
-from __future__ import absolute_import
-
-import logging
-import os
-
-LOG = logging.getLogger(__name__)
-
-# Import third party libs
-HAS_GERRIT = False
-try:
- from gerritlib import gerrit
- HAS_GERRIT = True
-except ImportError:
- pass
-
-
-def __virtual__():
- '''
- Only load this module if gerrit
- is installed on this minion.
- '''
- if HAS_GERRIT:
- return 'gerrit'
- return False
-
-__opts__ = {}
-
-
-def auth(**connection_args):
- '''
- Set up gerrit credentials
-
- Only intended to be used within gerrit-enabled modules
- '''
-
- prefix = "gerrit."
-
- # 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 + key, default))
-
- host = get('host', 'localhost')
- user = get('user', 'localhost')
- keyfile = get('keyfile', '/tmp/.ssh/id_rsa.pub')
-
- g = gerrit.Gerrit(host, user, keyfile=keyfile)
-
-
-def project_create(name, **kwargs):
- '''
- Create a gerrit project
-
- :param name: new project name
- :param path: custom repository name for new project. By default generated based on name
- :param namespace_id: namespace for the new project (defaults to user)
- :param description: short project description
- :param issues_enabled:
- :param merge_requests_enabled:
- :param wiki_enabled:
- :param snippets_enabled:
- :param public: if true same as setting visibility_level = 20
- :param visibility_level:
- :param import_url: https://gerrit.tcpcloud.eu/django/django-kedb.gerrit
-
- CLI Examples:
-
- .. code-block:: bash
-
- salt '*' gerrit.project_create namespace/nova description='nova project'
- salt '*' gerrit.project_create namespace/test enabled=False
-
- '''
- ret = {}
- gerrit = auth(**kwargs)
-
- project = _get_project(gerrit, name)
-
- if project and not "Error" in project:
- LOG.debug("Project {0} exists".format(name))
- ret[project.get('path_with_namespace')] = project
- return ret
-
- group_name, name = name.split('/')
- group = group_get(name=group_name)[group_name]
- kwargs['namespace_id'] = group.get('id')
- kwargs['name'] = name
- LOG.debug(kwargs)
-
- new = gerrit.createproject(**kwargs)
- if not new:
- return {'Error': 'Error creating project %s' % new}
- else:
- LOG.debug(new)
- ret[new.get('path_with_namespace')] = new
- return ret
-
-def project_delete(project, **kwargs):
- '''
- Delete a project (gerrit project-delete)
-
- :params project: Name or ID
-
- CLI Examples:
-
- .. code-block:: bash
-
- salt '*' gerrit.project_delete c965f79c4f864eaaa9c3b41904e67082
- salt '*' gerrit.project_delete project_id=c965f79c4f864eaaa9c3b41904e67082
- salt '*' gerrit.project_delete name=demo
- '''
- gerrit = auth(**kwargs)
-
- project = _get_project(gerrit, project)
-
- if not project:
- return {'Error': 'Unable to resolve project'}
-
- del_ret = gerrit.deleteproject(project["id"])
- ret = 'Project ID {0} deleted'.format(project["path_with_namespace"])
- ret += ' ({0})'.format(project["path_with_namespace"])
-
- return ret
-
-
-def project_get(project_id=None, name=None, **kwargs):
- '''
- Return a specific project
-
- CLI Examples:
-
- .. code-block:: bash
-
- salt '*' gerrit.project_get 323
- salt '*' gerrit.project_get project_id=323
- salt '*' gerrit.project_get name=namespace/repository
- '''
- gerrit = auth(**kwargs)
- ret = {}
- #object_list = project_list(kwargs)
-
- project = _get_project(gerrit, name or project_id)
- if not project:
- return {'Error': 'Error in retrieving project'}
- ret[project.get('name')] = project
- return ret
-
-
-def project_list(**connection_args):
- '''
- Return a list of available projects
-
- CLI Example:
-
- .. code-block:: bash
-
- salt '*' gerrit.project_list
- '''
- gerrit = auth(**connection_args)
- ret = {}
-
- projects = gerrit.listProjects()
-
- while len(projects) > 0:
- for project in projects:
- ret[project.get('path_with_namespace')] = project
- page += 1
- projects = gerrit.getprojectsall(page=page, per_page=PER_PAGE)
- return ret
-
-
-def group_list(group_name=None, **connection_args):
- '''
- Return a list of available groups
-
- CLI Example:
-
- .. code-block:: bash
-
- salt '*' gerrit.group_list
- '''
- gerrit = auth(**connection_args)
- ret = {}
- for group in gerrit.listProjects():
- ret[group.get('name')] = group
- return ret
-
-
-def group_get(id=None, name=None, **connection_args):
- '''
- Return a specific group
-
- CLI Examples:
-
- .. code-block:: bash
-
- salt '*' gerrit.group_get 323
- salt '*' gerrit.group_get name=namespace
-
- '''
- gerrit = auth(**connection_args)
- ret = {}
- if id == None:
- for group in gerrit.getgroups(group_id=None, page=1, per_page=100):
- if group.get('path') == name or group.get('name') == name:
- ret[group.get('path')] = group
- else:
- group = gerrit.getgroups(id)
- if group != False:
- ret[group.get('path')] = group
- if len(ret) == 0:
- return {'Error': 'Error in retrieving group'}
- return ret
-
diff --git a/gerrit/client.sls b/gerrit/client.sls
new file mode 100644
index 0000000..be7d39b
--- /dev/null
+++ b/gerrit/client.sls
@@ -0,0 +1,25 @@
+{% from "gerrit/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+gerrit_client_install:
+ pkg.installed:
+ - names: {{ client.pkgs }}
+
+/etc/salt/minion.d/_gerrit.conf:
+ file.managed:
+ - source: salt://gerrit/files/_gerrit.conf
+ - template: jinja
+
+/var/cache/salt/minion/gerrit_rsa:
+ file.managed:
+ - contents_pillar: gerrit:client:server:key
+
+{%- for project_name, project in client.project.iteritems() %}
+
+gerrit_client_project_{{ project_name }}:
+ gerrit.project_present:
+ - name: {{ project_name }}
+
+{%- endfor %}
+
+{%- endif %}
diff --git a/gerrit/files/_gerrit.conf b/gerrit/files/_gerrit.conf
new file mode 100644
index 0000000..76abb70
--- /dev/null
+++ b/gerrit/files/_gerrit.conf
@@ -0,0 +1,7 @@
+{%- from "gerrit/map.jinja" import client with context %}
+gerrit:
+ host: {{ client.server.host }}
+ {%- if client.server.user is defined %}
+ user: {{ client.server.user }}
+ keyfile: /var/cache/salt/minion/gerrit_rsa
+ {%- endif %}
\ No newline at end of file
diff --git a/gerrit/init.sls b/gerrit/init.sls
index 0fb21bf..f89cd94 100644
--- a/gerrit/init.sls
+++ b/gerrit/init.sls
@@ -3,4 +3,7 @@
{%- if pillar.gerrit.server is defined %}
- gerrit.server
{%- endif %}
+{%- if pillar.gerrit.client is defined %}
+- gerrit.client
+{%- endif %}
{%- endif %}
diff --git a/gerrit/map.jinja b/gerrit/map.jinja
index b72f407..07ee440 100644
--- a/gerrit/map.jinja
+++ b/gerrit/map.jinja
@@ -1,5 +1,5 @@
-{%- load_yaml as base_defaults %}
+{%- load_yaml as server_defaults %}
Debian:
pkgs:
- unzip
@@ -11,4 +11,12 @@
reindex_threads: 1
{%- endload %}
-{%- set server = salt['grains.filter_by'](base_defaults, merge=salt['pillar.get']('gerrit:server')) %}
+{%- set server = salt['grains.filter_by'](server_defaults, merge=salt['pillar.get']('gerrit:server')) %}
+
+{%- load_yaml as client_defaults %}
+Debian:
+ pkgs:
+ - python-gerritlib
+{%- endload %}
+
+{%- set client = salt['grains.filter_by'](client_defaults, merge=salt['pillar.get']('gerrit:client')) %}