Initial commit
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
new file mode 100644
index 0000000..a3a1729
--- /dev/null
+++ b/CHANGELOG.rst
@@ -0,0 +1,9 @@
+
+===============
+jenkins-formula
+===============
+
+0.1
+---
+
+- Initial commit to Community formula form
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..cc41a65
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+
+ Copyright (c) 2013 Salt Stack Formulas
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f5acedc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,130 @@
+
+# Jenkins continuos integration
+
+Jenkins is an application that monitors executions of repeated jobs, such as building a software project or jobs run by cron.
+
+## Sample pillars
+
+Jenkins masters
+
+Jenkins master with user
+
+ jenkins:
+ master:
+ enabled: true
+ http:
+ address: 0.0.0.0
+ port: 8080
+ protocol: http
+ plugins:
+ - name: git
+ - name: metadata
+ - name: envinject
+ - name: greenballs
+ - name: ansicolor
+ - name: build-pipeline-plugin
+ user:
+ admin:
+ api_token: api_token
+ password_hash: salt:hashed_pwd_see_usage
+ email: root@dmain.com
+ public_keys:
+ - key: ssh_public_key_of_current_root_user
+ slaves:
+ - name: slave1.domain.com
+ executors: 2
+
+Jenkins master with SSL
+
+ jenkins:
+ master:
+ enabled: true
+ http:
+ address: 0.0.0.0
+ port: 8080
+ protocol: https
+ ssl:
+ enabled: true
+ host: ci.domain.com
+ authority: Org_Service_CA
+ plugins:
+ - name: git
+ - name: metadata
+ - name: envinject
+ - name: greenballs
+ - name: ansicolor
+ - name: build-pipeline-plugin
+ slaves:
+ - name: slave1.domain.com
+ executors: 2
+
+### Jenkins job builder
+
+Jenkins job builder to configure master
+
+ jenkins:
+ job_builder:
+ enabled: true
+ source: git
+ address: https://git.openstack.org/openstack-infra/jenkins-job-builder
+ branch: master
+ config:
+ source: git
+ address: git@repo.domain.com:jenkins/jobs-org.git
+ branch: develop
+ master:
+ host: localhost
+ port: 8080
+ protocol: http
+ user: admin
+ password: fsdfsdf9438r4fessc9sd
+
+### Jenkins slaves
+
+Slave with sudo :o
+
+ jenkins:
+ slave:
+ enabled: true
+ sudo: true
+ master:
+ host: localhost
+ port: 8080
+ protocol: http
+ user:
+ name: admin
+ password: password
+
+Jenkins slave with keystone credentials
+
+ jenkins:
+ slave:
+ enabled: true
+ master:
+ host: localhost
+ port: 8080
+ protocol: http
+ user:
+ name: admin
+ password: password
+ keystone:
+
+## Usage
+
+User password generation. foo is password. bar is salt.
+
+ echo -n 'foo{bar}' | sha256sum
+
+## Read more
+
+* https://wiki.jenkins-ci.org/display/JENKINS/Use+Jenkins
+* https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+on+Ubuntu
+* https://github.com/jenkinsci/puppet-jenkins
+* https://wiki.jenkins-ci.org/display/JENKINS/Distributed+builds
+* http://ci.openstack.org/jenkins-job-builder/
+* http://ci.openstack.org/jjb.html
+* http://techs.enovance.com/6006/manage-jenkins-jobs-with-yaml
+* http://zeroturnaround.com/rebellabs/top-10-jenkins-featuresplugins/
+* https://wiki.jenkins-ci.org/display/JENKINS/Build+Pipeline+Plugin
+* https://wiki.jenkins-ci.org/display/JENKINS/LTS+Release+Line
+* https://gist.github.com/rowan-m/1026918
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..9a006c9
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,139 @@
+=======
+Jenkins
+=======
+
+Install and configure Jenkins master and slave.
+
+Available states
+================
+
+.. contents::
+ :local:
+
+``jenkins.master``
+------------------
+
+Setup jenkins master
+
+``jenkins.slave``
+-----------------
+
+Setup jenkins slave
+
+``jenkins.job_builder``
+-----------------------
+
+Setup jenkins job builder
+
+Available metadata
+==================
+
+.. contents::
+ :local:
+
+``metadata.jenkins.master.single``
+----------------------------------
+
+Setup single-node master
+
+
+``metadata.jenkins.slave.single``
+---------------------------------
+
+Setup Jenkins slave
+
+Configuration parameters
+========================
+
+
+Example reclass
+===============
+
+Master
+------
+
+.. code-block:: yaml
+
+ classes:
+ - service.jenkins.master
+
+ parameters:
+ _param:
+ jenkins_admin_token: xyz
+ jenkins_admin_password_hash: xyz
+ jenkins_admin_password: xyz
+ job_builder_config_address: git@github.com:xyz/myjobs.git
+ job_builder_config_branch: master
+ nginx:
+ server:
+ site:
+ jenkins:
+ enabled: true
+ type: nginx_proxy
+ name: jenkins
+ proxy:
+ host: 127.0.0.1
+ port: 8080
+ protocol: http
+ host:
+ name: jenkins.example.com
+ port: 80
+ jenkins:
+ master:
+ mode: EXCLUSIVE
+ slaves:
+ - name: slave01
+ label: pbuilder
+ executors: 2
+ - name: slave02
+ label: image_builder
+ mode: EXCLUSIVE
+ executors: 2
+ views:
+ - name: "Package builds"
+ regex: "debian-build-.*"
+ - name: "Contrail builds"
+ regex: "contrail-build-.*"
+ - name: "Aptly"
+ regex: "aptly-.*"
+ plugins:
+ - name: slack
+ - name: extended-choice-parameter
+ - name: rebuild
+ - name: test-stability
+
+Slave
+-----
+
+.. code-block:: yaml
+
+ classes:
+ - service.jenkins.slave.single
+ - service.java.environment
+
+ parameters:
+ _param:
+ java_environment_platform: openjdk
+ java_environment_version: 7
+
+ jenkins:
+ slave:
+ master:
+ host: jenkins.example.com
+ port: 80
+ user:
+ name: jenkins_slave
+ password: dexiech6AepohthaiHook2iesh7ol5ook4Ov3leid3yek6daid2ooNg3Ee2oKeYo
+ gpg:
+ keypair_id: A76882D3
+ public_key: |
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
+ ...
+ private_key: |
+ -----BEGIN PGP PRIVATE KEY BLOCK-----
+ ...
+
+Read more
+=========
+
+* https://wiki.jenkins-ci.org/display/JENKINS/Use+Jenkins
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..3b04cfb
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.2
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..5d7eafa
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,11 @@
+salt-formula-jenkins (0.2) trusty; urgency=medium
+
+ * First public release
+
+ -- Filip Pytloun <filip.pytloun@tcpcloud.eu> Tue, 06 Oct 2015 16:38:43 +0200
+
+salt-formula-jenkins (0.1) trusty; urgency=medium
+
+ * Initial release
+
+ -- Filip Pytloun <filip.pytloun@tcpcloud.eu> Thu, 13 Aug 2015 23:23:41 +0200
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..ec63514
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..c3dbb92
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,15 @@
+Source: salt-formula-jenkins
+Maintainer: Filip Pytloun <filip.pytloun@tcpcloud.eu>
+Section: admin
+Priority: optional
+Build-Depends: debhelper (>= 9)
+Standards-Version: 3.9.6
+Homepage: http://www.tcpcloud.eu
+Vcs-Browser: https://github.com/tcpcloud/salt-formula-jenkins
+Vcs-Git: https://github.com/tcpcloud/salt-formula-jenkins.git
+
+Package: salt-formula-jenkins
+Architecture: all
+Depends: ${misc:Depends}, salt-master, reclass
+Description: Jenkins Salt formula
+ Install and configure Jenkins master and slave.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..310c441
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,15 @@
+Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Upstream-Name: salt-formula-jenkins
+Upstream-Contact: Filip Pytloun <filip.pytloun@tcpcloud.eu>
+Source: https://github.com/tcpcloud/salt-formula-jenkins
+
+Files: *
+Copyright: 2014-2015 tcp cloud
+License: Apache-2.0
+ Copyright (C) 2014-2015 tcp cloud
+ .
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ .
+ On a Debian system you can find a copy of this license in
+ /usr/share/common-licenses/Apache-2.0.
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..d585829
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,3 @@
+README.rst
+CHANGELOG.rst
+VERSION
diff --git a/debian/install b/debian/install
new file mode 100644
index 0000000..7e6fb6f
--- /dev/null
+++ b/debian/install
@@ -0,0 +1,2 @@
+jenkins/* /usr/share/salt-formulas/env/jenkins/
+metadata/service/* /usr/share/salt-formulas/reclass/service/jenkins/
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..abde6ef
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,5 @@
+#!/usr/bin/make -f
+
+%:
+ dh $@
+
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..89ae9db
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (native)
diff --git a/jenkins/files/config.xml b/jenkins/files/config.xml
new file mode 100644
index 0000000..5ac2ef8
--- /dev/null
+++ b/jenkins/files/config.xml
@@ -0,0 +1,98 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<hudson>
+ <disabledAdministrativeMonitors/>
+ <version>1.0</version>
+ <numExecutors>2</numExecutors>
+ <mode>{{ pillar.jenkins.master.mode }}</mode>
+ <useSecurity>true</useSecurity>
+ <authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy"/>
+ <securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
+ <disableSignup>true</disableSignup>
+ <enableCaptcha>false</enableCaptcha>
+ </securityRealm>
+ <disableRememberMe>false</disableRememberMe>
+ <projectNamingStrategy class="jenkins.model.ProjectNamingStrategy$DefaultProjectNamingStrategy"/>
+ <workspaceDir>${ITEM_ROOTDIR}/workspace</workspaceDir>
+ <buildsDir>${ITEM_ROOTDIR}/builds</buildsDir>
+ <markupFormatter class="hudson.markup.RawHtmlMarkupFormatter" plugin="antisamy-markup-formatter@1.1">
+ <disableSyntaxHighlighting>false</disableSyntaxHighlighting>
+ </markupFormatter>
+ <jdks/>
+ <viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
+ <myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/>
+ <clouds/>
+ <slaves>
+ {%- if pillar.jenkins.master.slaves is defined %}
+ {%- for slave in pillar.jenkins.master.slaves %}
+ <slave>
+ <name>{{ slave.name }}</name>
+ <description></description>
+ <remoteFS>/var/lib/jenkins</remoteFS>
+ <numExecutors>{{ slave.executors }}</numExecutors>
+ <mode>{%- if slave.mode is defined %}{{ slave.mode }}{%- else %}NORMAL{%- endif %}</mode>
+ <retentionStrategy class="hudson.slaves.RetentionStrategy$Always"/>
+ <launcher class="hudson.slaves.JNLPLauncher"/>
+ <label>{%- if slave.label is defined %}{{ slave.label }}{%- endif %}</label>
+ <nodeProperties>
+ <hudson.slaves.EnvironmentVariablesNodeProperty>
+ <envVars serialization="custom">
+ <unserializable-parents/>
+ <tree-map>
+ <default>
+ <comparator class="hudson.util.CaseInsensitiveComparator"/>
+ </default>
+ <int>0</int>
+ </tree-map>
+ </envVars>
+ </hudson.slaves.EnvironmentVariablesNodeProperty>
+ <node-metadata plugin="metadata@1.0b">
+ <values class="linked-list"/>
+ </node-metadata>
+ </nodeProperties>
+ <userId>admin</userId>
+ </slave>
+ {%- endfor %}
+ {%- endif %}
+ </slaves>
+ <scmCheckoutRetryCount>0</scmCheckoutRetryCount>
+ <views>
+ <hudson.model.AllView>
+ <owner class="hudson" reference="../../.."/>
+ <name>All</name>
+ <filterExecutors>false</filterExecutors>
+ <filterQueue>false</filterQueue>
+ <properties class="hudson.model.View$PropertyList"/>
+ </hudson.model.AllView>
+ {%- if pillar.jenkins.master.views is defined %}
+ {%- for view in pillar.jenkins.master.views %}
+ <listView>
+ <owner class="hudson" reference="../../.."/>
+ <name>{{ view.name }}</name>
+ <filterExecutors>false</filterExecutors>
+ <filterQueue>false</filterQueue>
+ <properties class="hudson.model.View$PropertyList"/>
+ <jobNames>
+ <comparator class="hudson.util.CaseInsensitiveComparator"/>
+ </jobNames>
+ <jobFilters/>
+ <columns>
+ <hudson.views.StatusColumn/>
+ <hudson.views.WeatherColumn/>
+ <hudson.views.JobColumn/>
+ <hudson.views.LastSuccessColumn/>
+ <hudson.views.LastFailureColumn/>
+ <hudson.views.LastDurationColumn/>
+ <hudson.views.BuildButtonColumn/>
+ </columns>
+ <includeRegex>{{ view.regex }}</includeRegex>
+ <recurse>false</recurse>
+ </listView>
+ {%- endfor %}
+ {%- endif %}
+ </views>
+ <primaryView>All</primaryView>
+ <slaveAgentPort>0</slaveAgentPort>
+ <label>master</label>
+ <nodeProperties/>
+ <globalNodeProperties/>
+</hudson>
diff --git a/jenkins/files/config.xml.user b/jenkins/files/config.xml.user
new file mode 100644
index 0000000..9d442a4
--- /dev/null
+++ b/jenkins/files/config.xml.user
@@ -0,0 +1,42 @@
+{%- set user = salt['pillar.get']('jenkins:master:user:'+user_name) -%}
+<?xml version='1.0' encoding='UTF-8'?>
+<user>
+ <fullName>admin</fullName>
+ <properties>
+ <hudson.model.PaneStatusProperties>
+ <collapsed/>
+ </hudson.model.PaneStatusProperties>
+ <jenkins.security.ApiTokenProperty>
+ <apiToken>{{ user.api_token }}</apiToken>
+ </jenkins.security.ApiTokenProperty>
+ <com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty plugin="credentials@1.9.4">
+ <domainCredentialsMap class="hudson.util.CopyOnWriteMap$Hash"/>
+ </com.cloudbees.plugins.credentials.UserCredentialsProvider_-UserCredentialsProperty>
+ <hudson.model.MyViewsProperty>
+ <views>
+ <hudson.model.AllView>
+ <owner class="hudson.model.MyViewsProperty" reference="../../.."/>
+ <name>All</name>
+ <filterExecutors>false</filterExecutors>
+ <filterQueue>false</filterQueue>
+ <properties class="hudson.model.View$PropertyList"/>
+ </hudson.model.AllView>
+ </views>
+ </hudson.model.MyViewsProperty>
+ <hudson.search.UserSearchProperty>
+ <insensitiveSearch>false</insensitiveSearch>
+ </hudson.search.UserSearchProperty>
+ <hudson.security.HudsonPrivateSecurityRealm_-Details>
+ <passwordHash>{{ user.password_hash }}</passwordHash>
+ </hudson.security.HudsonPrivateSecurityRealm_-Details>
+ {%- if user.public_keys is defined %}
+ <org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl>
+ <authorizedKeys>{% for key in user.public_keys %}{{ key.key }}{% if not loop.last %}
+ {% endif %}{% endfor %}</authorizedKeys>
+ </org.jenkinsci.main.modules.cli.auth.ssh.UserPropertyImpl>
+ {% endif %}
+ <hudson.tasks.Mailer_-UserProperty plugin="mailer@1.8">
+ <emailAddress>{{ user.get("email", "root@local.domain") }}</emailAddress>
+ </hudson.tasks.Mailer_-UserProperty>
+ </properties>
+</user>
\ No newline at end of file
diff --git a/jenkins/files/init.d/jenkins-slave b/jenkins/files/init.d/jenkins-slave
new file mode 100644
index 0000000..9aa98f3
--- /dev/null
+++ b/jenkins/files/init.d/jenkins-slave
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides: jenkins-slave
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop:
+# Short-Description: Jenkins slave
+### END INIT INFO
+
+set -e
+
+# /etc/init.d/jenkins-slave: start and stop Jenkins slave
+
+if test -f /etc/default/jenkins-slave; then
+ . /etc/default/jenkins-slave
+else
+ echo "Configuration for jenkins-slave does not exist" 1>&2
+ exit 1
+fi
+
+. /lib/lsb/init-functions
+
+COMMAND="/usr/bin/java"
+COMMAND_ARGS="-jar slave.jar ${JENKINS_ARGS}"
+
+function check_running() {
+ start-stop-daemon -T --pidfile ${PIDFILE}
+ ret=$?
+ if [ $ret -ne 0 ]; then
+ log_end_msg 1 || true
+ exit $ret
+ fi
+}
+
+function start() {
+ # Get slave.jar from master
+ [ -f ${JENKINS_HOME}/slave.jar ] || wget -O ${JENKINS_HOME}/slave.jar -q ${JENKINS_URL}/jnlpJars/slave.jar
+
+ if start-stop-daemon -c ${JENKINS_USER} -d ${JENKINS_HOME} --background --start --quiet --oknodo -m --pidfile ${PIDFILE} --exec ${COMMAND} -- ${COMMAND_ARGS}; then
+ log_end_msg 0 || true
+ else
+ log_end_msg 1 || true
+ fi
+}
+
+function stop() {
+ if start-stop-daemon --stop --quiet --oknodo --pidfile ${PIDFILE}; then
+ log_end_msg 0 || true
+ else
+ log_end_msg 1 || true
+ fi
+}
+
+case "$1" in
+ start)
+ log_daemon_msg "Starting Jenkins slave" "jenkins-slave" || true
+ start
+ ;;
+ stop)
+ log_daemon_msg "Stopping Jenkins slave" "jenkins-slave" || true
+ stop
+ ;;
+ status)
+ status_of_proc -p ${PIDFILE} ${COMMAND} jenkins-slave && exit 0 || exit $?
+ ;;
+ restart)
+ log_daemon_msg "Restarting Jenkins slave" "jenkins-slave" || true
+ stop
+ start
+ ;;
+
+ *)
+ log_action_msg "Usage: /etc/init.d/jenkins-slave {start|stop|restart}" || true
+ exit 1
+ ;;
+esac
+
+exit 0
diff --git a/jenkins/files/jenkins b/jenkins/files/jenkins
new file mode 100644
index 0000000..f51ddb6
--- /dev/null
+++ b/jenkins/files/jenkins
@@ -0,0 +1,59 @@
+# defaults for jenkins continuous integration server
+
+# pulled in from the init script; makes things easier.
+NAME=jenkins
+
+# location of java
+JAVA=/usr/bin/java
+
+# arguments to pass to java
+#JAVA_ARGS="-Xmx256m"
+JAVA_ARGS="-Djava.net.preferIPv4Stack=true" # make jenkins listen on IPv4 address
+
+PIDFILE=/var/run/jenkins/jenkins.pid
+
+# user id to be invoked as (otherwise will run as root; not wise!)
+JENKINS_USER=jenkins
+
+# location of the jenkins war file
+JENKINS_WAR=/usr/share/jenkins/jenkins.war
+
+# jenkins home location
+JENKINS_HOME=/var/lib/jenkins
+
+# set this to false if you don't want Hudson to run by itself
+# in this set up, you are expected to provide a servlet container
+# to host jenkins.
+RUN_STANDALONE=true
+
+# log location. this may be a syslog facility.priority
+JENKINS_LOG=/var/log/jenkins/$NAME.log
+#HUDSON_LOG=daemon.info
+
+# OS LIMITS SETUP
+# comment this out to observe /etc/security/limits.conf
+# this is on by default because http://github.com/jenkinsci/jenkins/commit/2fb288474e980d0e7ff9c4a3b768874835a3e92e
+# reported that Ubuntu's PAM configuration doesn't include pam_limits.so, and as a result the # of file
+# descriptors are forced to 1024 regardless of /etc/security/limits.conf
+MAXOPENFILES=8192
+
+# port for HTTP connector (default 8080; disable with -1)
+HTTP_PORT={{ pillar.jenkins.master.http.port }}
+
+# port for AJP connector (disabled by default)
+AJP_PORT=-1
+
+# servlet context, important if you want to use apache proxying
+PREFIX=/jenkins
+
+# arguments to pass to jenkins.
+# --javahome=$JAVA_HOME
+# --httpPort=$HTTP_PORT (default 8080; disable with -1)
+# --httpsPort=$HTTP_PORT
+# --ajp13Port=$AJP_PORT
+# --argumentsRealm.passwd.$ADMIN_USER=[password]
+# --argumentsRealm.roles.$ADMIN_USER=admin
+# --webroot=~/.jenkins/war
+# --prefix=$PREFIX
+
+JENKINS_ARGS="--webroot=/var/cache/jenkins/war --httpPort=$HTTP_PORT --ajp13Port=$AJP_PORT"
diff --git a/jenkins/files/jenkins-slave b/jenkins/files/jenkins-slave
new file mode 100644
index 0000000..396aff3
--- /dev/null
+++ b/jenkins/files/jenkins-slave
@@ -0,0 +1,50 @@
+{%- from "jenkins/map.jinja" import slave with context %}
+# defaults for jenkins-slave component of the jenkins continuous integration
+# system
+
+# pulled in from the init script; makes things easier.
+NAME=jenkins-slave
+
+# location of java
+JAVA=/usr/bin/java
+
+# arguments to pass to java - optional
+#JAVA_ARGS="-Xmx256m"
+
+# for daemon to use
+PIDFILE=/var/run/$NAME.pid
+
+# user id to be invoked as (otherwise will run as root; not wise!)
+JENKINS_USER=jenkins
+
+# location of jenkins arch indep files
+JENKINS_ROOT=/usr/share/jenkins
+
+# jenkins home location
+JENKINS_HOME=/var/lib/jenkins
+
+# jenkins /run location
+JENKINS_RUN=/var/run/jenkins
+
+# URL of jenkins server to connect to
+JENKINS_URL="{{ slave.master.protocol }}://{{ slave.master.host }}:{{ slave.master.port }}"
+
+# Name of slave configuration to use at JENKINS_URL
+# Override if it need to be something other than the
+# hostname of the server the slave is running on.
+JENKINS_HOSTNAME="{{ slave.hostname }}"
+
+# Log file location for use in Debian init script
+JENKINS_SLAVE_LOG=/var/log/jenkins/$NAME.log
+
+# OS LIMITS SETUP
+# comment this out to observe /etc/security/limits.conf
+# this is on by default because http://github.com/feniix/hudson/commit/d13c08ea8f5a3fa730ba174305e6429b74853927
+# reported that Ubuntu's PAM configuration doesn't include pam_limits.so, and as a result the # of file
+# descriptors are forced to 1024 regardless of /etc/security/limits.confa
+# NOTE - Ubuntu Users - this is not used by the upstart configuration - please use an upstart overrides file
+# to change the OS limits setup.
+MAXOPENFILES=8192
+
+# Arguments to pass to jenkins slave on startup
+JENKINS_ARGS="-jnlpUrl $JENKINS_URL/computer/$JENKINS_HOSTNAME/slave-agent.jnlp -jnlpCredentials {{ slave.user.name }}:{{ slave.user.password }}"
diff --git a/jenkins/files/jenkins_jobs.ini b/jenkins/files/jenkins_jobs.ini
new file mode 100644
index 0000000..d71f07d
--- /dev/null
+++ b/jenkins/files/jenkins_jobs.ini
@@ -0,0 +1,7 @@
+[job_builder]
+recursive=True
+
+[jenkins]
+user={{ pillar.jenkins.job_builder.master.user }}
+password={{ pillar.jenkins.job_builder.master.password }}
+url={{ pillar.jenkins.job_builder.master.protocol }}://{{ pillar.jenkins.job_builder.master.host }}:{{ pillar.jenkins.job_builder.master.port }}
diff --git a/jenkins/files/keystonerc b/jenkins/files/keystonerc
new file mode 100644
index 0000000..d9d2e38
--- /dev/null
+++ b/jenkins/files/keystonerc
@@ -0,0 +1,5 @@
+{%- set server = pillar.jenkins.slave.keystone %}
+export OS_USERNAME="{{ server.user }}"
+export OS_PASSWORD="{{ server.password }}"
+export OS_TENANT_NAME="{{ server.tenant }}"
+export OS_AUTH_URL="{{ server.url }}"
diff --git a/jenkins/files/pbuilderrc b/jenkins/files/pbuilderrc
new file mode 100644
index 0000000..1d67250
--- /dev/null
+++ b/jenkins/files/pbuilderrc
@@ -0,0 +1,54 @@
+{%- from "jenkins/map.jinja" import slave with context %}
+{%- if slave.pbuilder is defined %}
+
+{%- if slave.pbuilder.mirrorsite is defined %}
+MIRRORSITE="{{ slave.pbuilder.mirrorsite }}"
+{%- endif %}
+
+{%- if slave.pbuilder.components is defined %}
+COMPONENTS="{{ slave.pbuilder.components }}"
+{%- endif %}
+
+{%- set keyring = slave.pbuilder.get('keyring', '/etc/apt/trusted.gpg') %}
+DEBOOTSTRAPOPTS=(${DEBOOTSTRAPOPTS[@]} "--keyring={{ keyring }}")
+APTKEYRINGS=(${APTKEYRINGS[@]} "{{ keyring }}")
+
+{%- if slave.pbuilder.aptcache is defined %}
+APTCACHE="{{ slave.pbuilder.aptcache }}"
+{%- endif %}
+
+{%- if slave.pbuilder.aptcachehardlink is defined %}
+APTCACHEHARDLINK="{{ 'yes' if slave.pbuilder.aptcachehardlink else 'no' }}"
+{%- endif %}
+
+{%- if slave.pbuilder.buildplace is defined %}
+BUILDPLACE="{{ slave.pbuilder.buildplace }}"
+{%- endif %}
+
+{%- if slave.pbuilder.buildresult is defined %}
+BUILDRESULT="{{ slave.pbuilder.buildresult }}"
+{%- endif %}
+
+{%- if slave.pbuilder.ccachedir is defined %}
+CCACHEDIR="{{ slave.pbuilder.ccachedir }}"
+{%- endif %}
+
+{%- if slave.pbuilder.usenetwork is defined %}
+USENETWORK="{{ 'yes' if slave.pbuilder.usenetwork else 'no' }}"
+{%- endif %}
+
+{%- if slave.pbuilder.parallel is defined %}
+
+{%- if slave.pbuilder.parallel %}
+{# Automatically set jobs to no. of cpus #}
+JOBS=$(grep -c processor /proc/cpuinfo)
+{%- else %}
+JOBS={{ slave.pbuilder.parallel }}
+{%- endif %}
+
+DEB_BUILD_OPTIONS="parallel=${JOBS} $DEB_BUILD_OPTIONS"
+
+{%- endif %}
+
+BINDMOUNTS="/var/cache/pbuilder/build"
+{%- endif %}
diff --git a/jenkins/files/sudoer b/jenkins/files/sudoer
new file mode 100644
index 0000000..a06260b
--- /dev/null
+++ b/jenkins/files/sudoer
@@ -0,0 +1,5 @@
+# jenkins user with passwordless sudo functionality.
+
+jenkins ALL=(ALL) NOPASSWD:ALL
+
+Defaults:jenkins !requiretty
diff --git a/jenkins/files/sudoer_debian_glue b/jenkins/files/sudoer_debian_glue
new file mode 100644
index 0000000..988682d
--- /dev/null
+++ b/jenkins/files/sudoer_debian_glue
@@ -0,0 +1,4 @@
+# allow jenkins to use cowbuilder, preserve important environment variables
+
+jenkins ALL=NOPASSWD: /usr/sbin/cowbuilder, /usr/sbin/chroot
+Defaults env_keep+="DEB_* DIST ARCH ADT"
diff --git a/jenkins/init.sls b/jenkins/init.sls
new file mode 100644
index 0000000..985416e
--- /dev/null
+++ b/jenkins/init.sls
@@ -0,0 +1,11 @@
+
+include:
+{% if pillar.jenkins.master is defined %}
+- jenkins.master
+{% endif %}
+{% if pillar.jenkins.job_builder is defined %}
+- jenkins.job_builder
+{% endif %}
+{% if pillar.jenkins.slave is defined %}
+- jenkins.slave
+{% endif %}
diff --git a/jenkins/job_builder.sls b/jenkins/job_builder.sls
new file mode 100644
index 0000000..d1525ba
--- /dev/null
+++ b/jenkins/job_builder.sls
@@ -0,0 +1,83 @@
+{% from "jenkins/map.jinja" import job_builder with context %}
+{%- if pillar.jenkins.job_builder.enabled %}
+
+include:
+- git
+
+{%- if not job_builder.pkgs %}
+# Install job builder with pip if we don't have package
+
+include:
+- python
+
+jenkins_job_builder_install:
+ pip.installed:
+ - names:
+ - jenkins-job-builder
+ - require:
+ - pkg: jenkins_job_builder_packages
+
+{%- else %}
+
+jenkins_job_builder_install:
+ pkg.installed:
+ - names: {{ job_builder.pkgs }}
+ - require:
+ - pkg: jenkins_job_builder_packages
+
+jenkins_job_builder_packages:
+ pkg.installed:
+ - names:
+ - python-yaml
+ - python-jenkins
+ - python-pip
+ - python-pbr
+ - require:
+ - pkg: python_packages
+
+{%- endif %}
+
+/srv/jenkins:
+ file.directory:
+ - user: root
+ - group: root
+ - mode: 755
+ - makedirs: true
+
+{{ job_builder.conf_dir }}:
+ file.directory:
+ - user: root
+ - group: root
+ - mode: 755
+ - makedirs: true
+
+{{ job_builder.config_file }}:
+ file.managed:
+ - source: salt://jenkins/files/jenkins_jobs.ini
+ - user: root
+ - group: root
+ - mode: 400
+ - template: jinja
+ - require:
+ - file: /etc/jenkins_jobs
+
+{{ pillar.jenkins.job_builder.config.address }}:
+ git.latest:
+ - target: /srv/jenkins/job_builder_config
+ - rev: {{ pillar.jenkins.job_builder.config.branch }}
+ - require:
+ - file: /srv/jenkins
+
+jenkins_job_builder_jobs_update:
+ cmd.run:
+ - name: jenkins-jobs update /srv/jenkins/job_builder_config
+ - require:
+ - git: {{ pillar.jenkins.job_builder.config.address }}
+ - file: {{ job_builder.config_file }}
+ {%- if not job_builder.pkgs %}
+ - pkg: jenkins_job_builder_install
+ {%- else %}
+ - pip: jenkins_job_builder_install
+ {%- endif %}
+
+{%- endif %}
diff --git a/jenkins/map.jinja b/jenkins/map.jinja
new file mode 100644
index 0000000..5d446ca
--- /dev/null
+++ b/jenkins/map.jinja
@@ -0,0 +1,49 @@
+
+{% set master = salt['grains.filter_by']({
+ 'Debian': {
+ 'pkgs': ['jenkins'],
+ 'service': 'jenkins',
+ 'config': '/etc/default/jenkins',
+ },
+ 'RedHat': {
+ 'pkgs': ['jenkins'],
+ 'service': 'jenkins',
+ 'config': '/etc/sysconfig/jenkins',
+ },
+}, merge=salt['pillar.get']('jenkins:master')) %}
+
+{% set job_builder = salt['grains.filter_by']({
+ 'Debian': {
+ 'pkgs': ['jenkins-job-builder', 'jenkins-jobs-slack'],
+ 'config_file': '/etc/jenkins_jobs/jenkins_jobs.ini',
+ 'conf_dir': '/etc/jenkins_jobs',
+ },
+ 'RedHat': {
+ 'pkgs': ['jenkins-job-builder', 'jenkins-jobs-slack'],
+ 'config_file': '/etc/jenkins_jobs/jenkins_jobs.ini',
+ 'conf_dir': '/etc/jenkins_jobs',
+ },
+}, merge=salt['pillar.get']('jenkins:job_builder')) %}
+
+{% if pillar.system is defined %}
+{%- set hostname = pillar.system.name %}
+{%- else %}
+{%- set hostname = pillar.linux.system.name+'.'+pillar.linux.system.domain %}
+{%- endif %}
+
+{% set slave = salt['grains.filter_by']({
+ 'Debian': {
+ 'pkgs': ['jenkins-slave'],
+ 'init_script': '/etc/init.d/jenkins-slave',
+ 'service': 'jenkins-slave',
+ 'hostname': hostname,
+ 'config': '/etc/default/jenkins-slave',
+ },
+ 'RedHat': {
+ 'pkgs': ['jenkins-slave'],
+ 'init_script': '/etc/init.d/jenkins-slave',
+ 'hostname': hostname,
+ 'service': 'jenkins-slave',
+ 'config': '/etc/sysconfig/jenkins-slave',
+ },
+}, merge=salt['pillar.get']('jenkins:slave')) %}
diff --git a/jenkins/master/init.sls b/jenkins/master/init.sls
new file mode 100644
index 0000000..8fbf128
--- /dev/null
+++ b/jenkins/master/init.sls
@@ -0,0 +1,58 @@
+{% from "jenkins/map.jinja" import master with context %}
+
+{%- if master.enabled %}
+
+include:
+- java
+- jenkins.master.users
+{%- if master.plugins is defined %}
+- jenkins.master.plugins
+{%- endif %}
+
+jenkins_packages:
+ pkg.installed:
+ - names: {{ master.pkgs }}
+ - require:
+ - pkg: java_packages
+
+jenkins_{{ master.config }}:
+ file.managed:
+ - name: {{ master.config }}
+ - source: salt://jenkins/files/jenkins
+ - user: root
+ - group: root
+ - template: jinja
+ - require:
+ - pkg: jenkins_packages
+
+/var/lib/jenkins/config.xml:
+ file.managed:
+ - source: salt://jenkins/files/config.xml
+ - user: jenkins
+ - group: nogroup
+ - template: jinja
+ - require:
+ - pkg: jenkins_packages
+
+{%- if master.get('sudo', false) %}
+
+/etc/sudoers.d/99-jenkins-user:
+ file.managed:
+ - source: salt://jenkins/files/sudoer
+ - template: jinja
+ - user: root
+ - group: root
+ - mode: 440
+ - require:
+ - service: jenkins_master_service
+
+{%- endif %}
+
+jenkins_master_service:
+ service.running:
+ - name: {{ master.service }}
+ - watch:
+ - file: jenkins_{{ master.config }}
+ - file: /var/lib/jenkins/config.xml
+
+{%- endif %}
diff --git a/jenkins/master/plugins.sls b/jenkins/master/plugins.sls
new file mode 100644
index 0000000..49fb6a0
--- /dev/null
+++ b/jenkins/master/plugins.sls
@@ -0,0 +1,28 @@
+{% from "jenkins/map.jinja" import master with context %}
+
+/var/lib/jenkins/updates:
+ file.directory:
+ - user: jenkins
+ - group: nogroup
+
+setup_jenkins_cli:
+ cmd.run:
+ - names:
+ - sleep 30
+ - wget http://localhost:{{ master.http.port }}/jnlpJars/jenkins-cli.jar
+ - unless: "[ -f /root/jenkins-cli.jar ]"
+ - cwd: /root
+ - require:
+ - service: jenkins_master_service
+
+{%- for plugin in master.plugins %}
+
+install_jenkins_plugin_{{ plugin.name }}:
+ cmd.run:
+ - name: java -jar jenkins-cli.jar -s http://localhost:{{ master.http.port }} install-plugin --username admin --password {{ master.user.admin.password }} {{ plugin.name }}
+ - unless: "[ -d /var/lib/jenkins/plugins/{{ plugin.name }} ]"
+ - cwd: /root
+ - require:
+ - cmd: setup_jenkins_cli
+
+{%- endfor %}
diff --git a/jenkins/master/users.sls b/jenkins/master/users.sls
new file mode 100644
index 0000000..cd29822
--- /dev/null
+++ b/jenkins/master/users.sls
@@ -0,0 +1,20 @@
+{% from "jenkins/map.jinja" import master with context %}
+
+{%- for user_name, user in master.user.iteritems() %}
+
+/var/lib/jenkins/users/{{ user_name }}:
+ file.directory:
+ - makedirs: true
+
+/var/lib/jenkins/users/{{ user_name }}/config.xml:
+ file.managed:
+ - source: salt://jenkins/files/config.xml.user
+ - template: jinja
+ - require:
+ - file: /var/lib/jenkins/users/{{ user_name }}
+ - defaults:
+ user_name: "{{ user_name }}"
+ - watch_in:
+ - service: jenkins_master_service
+
+{%- endfor %}
diff --git a/jenkins/slave/gpg.sls b/jenkins/slave/gpg.sls
new file mode 100644
index 0000000..b23001b
--- /dev/null
+++ b/jenkins/slave/gpg.sls
@@ -0,0 +1,44 @@
+{% from "jenkins/map.jinja" import slave with context %}
+
+jenkins_gpg_key_dir:
+ file.directory:
+ - name: /var/lib/jenkins/.gnupg
+ - user: jenkins
+ - group: jenkins
+ - mode: 700
+
+gpg_priv_key:
+ file.managed:
+ - name: /var/lib/jenkins/.gnupg/secret.gpg
+ - contents_pillar: jenkins:slave:gpg:private_key
+ - user: jenkins
+ - group: jenkins
+ - mode: 600
+ - require:
+ - file: jenkins_gpg_key_dir
+
+gpg_pub_key:
+ file.managed:
+ - name: /var/lib/jenkins/.gnupg/public.gpg
+ - contents_pillar: jenkins:slave:gpg:public_key
+ - user: jenkins
+ - group: jenkins
+ - mode: 644
+ - require:
+ - file: jenkins_gpg_key_dir
+
+import_gpg_pub_key:
+ cmd.run:
+ - name: gpg --no-tty --import /var/lib/jenkins/.gnupg/public.gpg
+ - user: jenkins
+ - unless: gpg --no-tty --list-keys | grep '{{ slave.gpg.keypair_id }}'
+ - require:
+ - file: jenkins_gpg_key_dir
+
+import_gpg_priv_key:
+ cmd.run:
+ - name: gpg --no-tty --allow-secret-key-import --import /var/lib/jenkins/.gnupg/secret.gpg
+ - user: jenkins
+ - unless: gpg --no-tty --list-secret-keys | grep '{{ slave.gpg.keypair_id }}'
+ - require:
+ - file: jenkins_gpg_key_dir
diff --git a/jenkins/slave/init.sls b/jenkins/slave/init.sls
new file mode 100644
index 0000000..e34d0ec
--- /dev/null
+++ b/jenkins/slave/init.sls
@@ -0,0 +1,94 @@
+{% from "jenkins/map.jinja" import slave with context %}
+
+{%- if slave.enabled %}
+
+include:
+- java
+{%- if slave.pbuilder is defined %}
+- jenkins.slave.pbuilder
+{%- endif %}
+{%- if slave.gpg is defined %}
+- jenkins.slave.gpg
+{%- endif %}
+{%- if slave.keystone is defined %}
+- jenkins.slave.keystone
+{%- endif %}
+
+{% if slave.pkgs %}
+
+jenkins_slave_package:
+ pkg.installed:
+ - names: {{ slave.pkgs }}
+ - require:
+ - pkg: java_packages
+
+{% else %}
+
+# No jenkins-slave package, use magic init script instead
+{{ slave.init_script }}:
+ file.managed:
+ - source: salt://jenkins/files/init.d/jenkins-slave
+ - user: root
+ - group: root
+ - mode: 755
+ - template: jinja
+
+{% endif %}
+
+{{ slave.config }}:
+ file.managed:
+ - source: salt://jenkins/files/jenkins-slave
+ - user: root
+ - group: root
+ - template: jinja
+ - require:
+ {% if slave.pkgs %}
+ - pkg: jenkins_slave_package
+ {% else %}
+ - file: {{ slave.init_script }}
+ {% endif %}
+
+jenkins_slave_service:
+ service.running:
+ - name: {{ slave.service }}
+ - watch:
+ - file: {{ slave.config }}
+ - require:
+ {% if slave.pkgs %}
+ - pkg: jenkins_slave_package
+ {% else %}
+ - file: {{ slave.init_script }}
+ {% endif %}
+
+{%- if pillar.linux.system.user.jenkins is not defined %}
+
+jenkins_slave_user:
+ user.present:
+ - name: jenkins
+ - shell: /bin/bash
+ - home: /var/lib/jenkins
+ - require_in:
+ {%- if slave.gpg is defined %}
+ - file: jenkins_gpg_key_dir
+ {%- endif %}
+ {%- if slave.pbuilder is defined %}
+ - file: /var/lib/jenkins/pbuilder
+ {%- endif %}
+
+{%- endif %}
+
+{%- if slave.get('sudo', false) %}
+
+/etc/sudoers.d/99-jenkins-user:
+ file.managed:
+ - source: salt://jenkins/files/sudoer
+ - template: jinja
+ - user: root
+ - group: root
+ - mode: 440
+ - require:
+ - service: jenkins_slave_service
+
+{%- endif %}
+
+{%- endif %}
diff --git a/jenkins/slave/keystone.sls b/jenkins/slave/keystone.sls
new file mode 100644
index 0000000..d308f76
--- /dev/null
+++ b/jenkins/slave/keystone.sls
@@ -0,0 +1,19 @@
+{% from "jenkins/map.jinja" import slave with context %}
+
+/var/lib/jenkins/keystonerc:
+ file.managed:
+ - source: salt://jenkins/files/keystonerc
+ - user: jenkins
+ - group: jenkins
+ - mode: 0400
+ - template: jinja
+ - require:
+ - service: jenkins_slave_service
+
+jenkins_slave_openstack_clients:
+ pkg.installed:
+ - names:
+ - python-keystoneclient
+ - python-novaclient
+ - python-neutronclient
+ - python-glanceclient
diff --git a/jenkins/slave/pbuilder.sls b/jenkins/slave/pbuilder.sls
new file mode 100644
index 0000000..b45947c
--- /dev/null
+++ b/jenkins/slave/pbuilder.sls
@@ -0,0 +1,66 @@
+{% from "jenkins/map.jinja" import slave with context %}
+
+jenkins_debian_glue_packages:
+ pkg.latest:
+ - names:
+ - reprepro
+ - cowbuilder
+ - jenkins-debian-glue
+ - git-buildpackage
+ - debhelper
+
+/srv/repository:
+ file:
+ - directory
+ - user: jenkins
+ - mode: 755
+ - makedirs: true
+ - require:
+ - service: jenkins_slave_service
+
+/etc/sudoers.d/98-jenkins-debian-glue:
+ file.managed:
+ - source: salt://jenkins/files/sudoer_debian_glue
+ - template: jinja
+ - user: root
+ - group: root
+ - mode: 440
+ - require:
+ - service: jenkins_slave_service
+
+/etc/pbuilderrc:
+ file.managed:
+ - source: salt://jenkins/files/pbuilderrc
+ - template: jinja
+ - user: root
+ - group: root
+ - mode: 644
+ - require:
+ - pkg: jenkins_debian_glue_packages
+
+/var/cache/pbuilder:
+ file.symlink:
+ - target: /var/lib/jenkins/pbuilder
+ - require:
+ - file: /var/lib/jenkins/pbuilder
+ - require_in:
+ - pkg: jenkins_debian_glue_packages
+
+/var/lib/jenkins/pbuilder:
+ file:
+ - directory
+ - user: jenkins
+ - group: jenkins
+ - mode: 755
+ - makedirs: true
+
+{%- if slave.pbuilder.ccachedir is defined %}
+{{ slave.pbuilder.ccachedir }}:
+ file.directory:
+ - user: root
+ - group: root
+ - mode: 777
+ - makedirs: true
+ - require:
+ - file: /var/cache/pbuilder
+{%- endif %}
diff --git a/metadata/service/master/single.yml b/metadata/service/master/single.yml
new file mode 100644
index 0000000..549d004
--- /dev/null
+++ b/metadata/service/master/single.yml
@@ -0,0 +1,43 @@
+applications:
+- jenkins
+parameters:
+ jenkins:
+ master:
+ enabled: true
+ sudo: false
+ mode: "NORMAL"
+ http:
+ network: any
+ port: 8080
+ protocol: http
+ plugins:
+ - name: git
+ - name: metadata
+ - name: envinject
+ - name: ansicolor
+ - name: greenballs
+ - name: gitlab-hook
+ - name: build-pipeline-plugin
+ - name: copyartifact
+ - name: ws-cleanup
+ - name: parameterized-trigger
+ user:
+ admin:
+ api_token: ${_param:jenkins_admin_token}
+ password: ${_param:jenkins_admin_password}
+ password_hash: ${_param:jenkins_admin_password_hash}
+ email: root@dmain.com
+ job_builder:
+ enabled: true
+ source: git
+ branch: master
+ config:
+ source: git
+ address: ${_param:job_builder_config_address}
+ branch: ${_param:job_builder_config_branch}
+ master:
+ host: localhost
+ port: 8080
+ protocol: http
+ user: admin
+ password: ${_param:jenkins_admin_password}
diff --git a/metadata/service/slave/single.yml b/metadata/service/slave/single.yml
new file mode 100644
index 0000000..cc9690c
--- /dev/null
+++ b/metadata/service/slave/single.yml
@@ -0,0 +1,16 @@
+applications:
+- jenkins
+parameters:
+ jenkins:
+ slave:
+ enabled: true
+ pkgs: false
+ sudo: false
+ scripts: []
+ master:
+ host: 127.0.0.1
+ port: 8080
+ protocol: http
+ user:
+ name: admin
+ password: ${_secret:jenkins_admin_password}