How to install and configure Jenkins using Chef Custom Resource
Here in this article we will try to install and configure a basic Jenkins server using Chef Custom resource.
Test Environment
CentOS 7 with ChefDK installed
Before going into the concept of creating a custom resource let’s see what are the default repository listing for my centos machine and try creating a cookbook with a default recipe to install jenkins and see what happens.
Below is the list of repositories that are currently configured on my default CentOS 7 machine.
sudo yum repolist
Output:
Loaded plugins: fastestmirror, langpacks
Loading mirror speeds from cached hostfile
* base: mirror.math.princeton.edu
* extras: mirrors.mit.edu
* rpmforge: repoforge.spinellicreations.com
* updates: www.gtlib.gatech.edu
repo id repo name status
base/7/x86_64 CentOS-7 - Base 9,363
extras/7/x86_64 CentOS-7 - Extras 451
rpmforge RHEL 7 - RPMforge.net - dag 4,718
updates/7/x86_64 CentOS-7 - Updates 2,146
repolist: 16,678
Let me generate a cookbook named ‘jenkins’ and update the default recipe in it to install package named jenkins.
chef generate cookbook jenkins
File: default.rb
#
# Cookbook Name:: jenkins
# Recipe:: default
#
# Copyright (c) 2017 The Authors, All Rights Reserved.
package 'jenkins' do
action :install
end
Now, lets try to run the default recipe inside the cookbook ‘jenkins’ to install jenkins locally on the CentOS 7 machine.
sudo chef-client --local-mode --runlist 'recipe[jenkins::default]'
Output:
[2017-09-11T11:21:46-07:00] WARN: No config file found or specified on command line, using command line options.
Starting Chef Client, version 12.12.15
resolving cookbooks for run list: ["jenkins::default"]
Synchronizing Cookbooks:
- jenkins (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 1 resources
Recipe: jenkins::default
* yum_package[jenkins] action install
* No candidate version available for jenkins
================================================================================
Error executing action `install` on resource 'yum_package[jenkins]'
================================================================================
Chef::Exceptions::Package
...
...
Running handlers:
[2017-09-11T11:23:24-07:00] ERROR: Running exception handlers
Running handlers complete
[2017-09-11T11:23:24-07:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated in 01 minutes 36 seconds
[2017-09-11T11:23:24-07:00] FATAL: Stacktrace dumped to /root/.chef/local-mode-cache/cache/chef-stacktrace.out
[2017-09-11T11:23:24-07:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2017-09-11T11:23:24-07:00] ERROR: yum_package[jenkins] (jenkins::default line 7) had an error: Chef::Exceptions::Package: No candidate version available for jenkins
[2017-09-11T11:23:25-07:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
As you can see from the highlighted lines in RED, Chef client failed to run the default recipe because it is unable to find any package named jenkins to install from the default repositories that are pre-configured in the machine.
To resolve these errors, we are going first create a repo file with the repository url for jenkins package using template resource, then we are going to create a custom resource named manageJenkins which we can use similar to resources like file, package, service and call the custom resource from the default cookbook recipe to install the Jenkins package from the repository that was configure in the first step.
Lets start with the step by step procedure as outlined below to achieve our goal or purpose.
Procedure
Step1: Setup the Jenkins repository
First, we need to generate a template file for jenkins repoistory content.
sudo chef generate template jenkins.repository
Update the default jenkins.repository.erb file with the repo content pointing to jenkins repository as show below.
File: jenkins.repository.erb
[jenkins]
name=Jenkins
baseurl=http://pkg.jenkins.io/redhat
gpgcheck=1
Now, lets configure the jenkins repository locally by using template resource in the default cookbook recipe as show below.
File: default.rb
#
# Cookbook Name:: jenkins
# Recipe:: default
#
# Copyright (c) 2017 The Authors, All Rights Reserved.
template '/etc/yum.repos.d/jenkins.repo' do
source 'jenkins.repository.erb'
owner 'root'
group 'root'
mode '0755'
end
As you can see we have deleted the old content from the recipe wherein we were trying to install jenkins package using package resource. The file is now updated with the template resource to configure the jenkins repository.
Now, lets run the recipe and see what happens.
Before default recipe execution
sudo ls -ltr /etc/yum.repos.d/
Output:
total 44
-rw-r--r--. 1 root root 1128 Mar 20 2013 rpmforge.repo
-rw-r--r--. 1 root root 728 Mar 20 2013 mirrors-rpmforge-testing
-rw-r--r--. 1 root root 717 Mar 20 2013 mirrors-rpmforge-extras
-rw-r--r--. 1 root root 739 Mar 20 2013 mirrors-rpmforge
-rw-r--r--. 1 root root 1952 Dec 9 2015 CentOS-Vault.repo
-rw-r--r--. 1 root root 1331 Dec 9 2015 CentOS-Sources.repo
-rw-r--r--. 1 root root 630 Dec 9 2015 CentOS-Media.repo
-rw-r--r--. 1 root root 290 Dec 9 2015 CentOS-fasttrack.repo
-rw-r--r--. 1 root root 649 Dec 9 2015 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 1309 Dec 9 2015 CentOS-CR.repo
-rw-r--r--. 1 root root 1664 Dec 9 2015 CentOS-Base.repo
Executing the recipe now as shown below.
sudo chef-client --local-mode --runlist 'recipe[jenkins::default]'
Output:
[2017-09-11T11:45:48-07:00] WARN: No config file found or specified on command line, using command line options.
Starting Chef Client, version 12.12.15
resolving cookbooks for run list: ["jenkins::default"]
Synchronizing Cookbooks:
- jenkins (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 1 resources
Recipe: jenkins::default
* template[/etc/yum.repos.d/jenkins.repo] action create
- create new file /etc/yum.repos.d/jenkins.repo
- update content in file /etc/yum.repos.d/jenkins.repo from none to 201d31
--- /etc/yum.repos.d/jenkins.repo 2017-09-11 11:45:51.833807412 -0700
+++ /etc/yum.repos.d/.chef-jenkins.repo20170911-7866-8n2km5 2017-09-11 11:45:51.750805465 -0700
@@ -1 +1,5 @@
+[jenkins]
+name=Jenkins
+baseurl=http://pkg.jenkins.io/redhat
+gpgcheck=1
- change mode from '' to '0755'
- change owner from '' to 'root'
- change group from '' to 'root'
- restore selinux security context
Running handlers:
Running handlers complete
Chef Client finished, 1/1 resources updated in 03 seconds
After default recipe execution
Output:
total 48
-rw-r--r--. 1 root root 1128 Mar 20 2013 rpmforge.repo
-rw-r--r--. 1 root root 728 Mar 20 2013 mirrors-rpmforge-testing
-rw-r--r--. 1 root root 717 Mar 20 2013 mirrors-rpmforge-extras
-rw-r--r--. 1 root root 739 Mar 20 2013 mirrors-rpmforge
-rw-r--r--. 1 root root 1952 Dec 9 2015 CentOS-Vault.repo
-rw-r--r--. 1 root root 1331 Dec 9 2015 CentOS-Sources.repo
-rw-r--r--. 1 root root 630 Dec 9 2015 CentOS-Media.repo
-rw-r--r--. 1 root root 290 Dec 9 2015 CentOS-fasttrack.repo
-rw-r--r--. 1 root root 649 Dec 9 2015 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root 1309 Dec 9 2015 CentOS-CR.repo
-rw-r--r--. 1 root root 1664 Dec 9 2015 CentOS-Base.repo
-rwxr-xr-x. 1 root root 71 Sep 11 11:45 jenkins.repo
Our repository is now configure with the help of template resource. Let get onto our next chef creating custom resource.
Step2: Create a custom resource
As a first i am create a lightweight resource provider named ‘manageJenkins’ using the below command.
sudo chef generate lwrp manageJenkins
Output:
Recipe: code_generator::lwrp
* directory[/home/skytap/chefspace/cookbooks/jenkins/resources] action create
- create new directory /home/skytap/chefspace/cookbooks/jenkins/resources
- restore selinux security context
* template[/home/skytap/chefspace/cookbooks/jenkins/resources/manageJenkins.rb] action create
- create new file /home/skytap/chefspace/cookbooks/jenkins/resources/manageJenkins.rb
- update content in file /home/skytap/chefspace/cookbooks/jenkins/resources/manageJenkins.rb from none to e3b0c4
(diff output suppressed by config)
- restore selinux security context
* directory[/home/skytap/chefspace/cookbooks/jenkins/providers] action create
- create new directory /home/skytap/chefspace/cookbooks/jenkins/providers
- restore selinux security context
* template[/home/skytap/chefspace/cookbooks/jenkins/providers/manageJenkins.rb] action create
- create new file /home/skytap/chefspace/cookbooks/jenkins/providers/manageJenkins.rb
- update content in file /home/skytap/chefspace/cookbooks/jenkins/providers/manageJenkins.rb from none to e3b0c4
(diff output suppressed by config)
- restore selinux security context
Once our custom resource files are create, lets update the custom resource with below content. Here i am giving my custom resource a name called ‘manageJenkins’ and updating it with two action items that are install and uninstall.
In ‘install’ action we are going to install jenkins using the package resource and then enable and start up the jenkins service.
In ‘uninstall’ action we are going to remove the jenkins package from the machine.
File: manageJenkins.rb
Output:
resource_name : manageJenkins
action :install do
package 'jenkins'
service 'jenkins' do
action [:enable, :start]
end
end
action :uninstall do
package 'jenkins' do
action :remove
end
end
The next step is to call the custom resource from our cookbooks default recipe.
Step3: Use the Custom resource in the default recipe
Here is our updated default.rb file with custom resource reference.
File: default.rb
#
# Cookbook Name:: jenkins
# Recipe:: default
#
# Copyright (c) 2017 The Authors, All Rights Reserved.
template '/etc/yum.repos.d/jenkins.repo' do
source 'jenkins.repository.erb'
owner 'root'
group 'root'
mode '0755'
end
manageJenkins 'install' do
action :install
end
After updating the default recipe as above, we can tried to run the recipe with the command in Step4 but it failed with below error.
Error:
================================================================================
Error executing action `install` on resource 'yum_package[jenkins]'
================================================================================
Chef::Exceptions::Exec
----------------------
yum -d0 -e0 -y install jenkins-2.78-1.1 returned 1:
STDOUT: Public key for jenkins-2.78-1.1.noarch.rpm is not installed
STDERR: warning: /var/cache/yum/x86_64/7/jenkins/packages/jenkins-2.78-1.1.noarch.rpm: Header V4 DSA/SHA1 Signature, key ID d50582e6: NOKEY
Public key for jenkins-2.78-1.1.noarch.rpm is not installed
To recover from the above error, we have to update the template file with gpgkey as below.
Here is the updated custom resource file.
File: jenkins.repository.erb
Output:
[jenkins]
name=Jenkins
baseurl=http://pkg.jenkins.io/redhat
gpgkey=https://pkg.jenkins.io/redhat/jenkins.io.key
gpgcheck=1
Yes, with the above change you should be able to successfully install jenkins and startup the service. Sample output is show in below.
Step4: Run the Cookbook in local mode
Let’s now run our cookbook with the recipe “jenkins” in local mode as shown below.
sudo chef-client --local-mode --runlist 'recipe[jenkins]'
Output:
[2017-09-09T04:15:20-07:00] WARN: No config file found or specified on command line, using command line options.
Starting Chef Client, version 12.12.15
resolving cookbooks for run list: ["jenkins"]
Synchronizing Cookbooks:
- jenkins (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks...
Converging 1 resources
Recipe: jenkins::default
* manageJenkins[install] action install
* yum_package[jenkins] action install
- install version 2.77-1.1 of package jenkins
* service[jenkins] action enable (up to date)
* service[jenkins] action start
- start service service[jenkins]
As a last step, we need to validate if jenkins is actually installed or not.
Step5: Validate the Jenkins installation
Now let’s check the status of jenkins service.
sudo systemctl status jenkins
Output:
● jenkins.service - LSB: Jenkins Automation Server
Loaded: loaded (/etc/rc.d/init.d/jenkins)
Active: active (running) since Sat 2017-09-09 04:20:40 PDT; 3min 34s ago
Docs: man:systemd-sysv-generator(8)
Process: 9410 ExecStart=/etc/rc.d/init.d/jenkins start (code=exited, status=0/SUCCESS)
CGroup: /system.slice/jenkins.service
└─9425 /etc/alternatives/java -Dcom.sun.akuma.Daemon=daemonized -Djava.awt.headless=true -DJENKINS_HOME=/var/lib/jenkins -jar ...
Sep 09 04:20:35 host-1 systemd[1]: Starting LSB: Jenkins Automation Server...
Sep 09 04:20:36 host-1 runuser[9411]: pam_unix(runuser:session): session opened for user jenkins by (uid=0)
Sep 09 04:20:39 host-1 runuser[9411]: pam_unix(runuser:session): session closed for user jenkins
Sep 09 04:20:40 host-1 jenkins[9410]: Starting Jenkins [ OK ]
Sep 09 04:20:40 host-1 systemd[1]: Started LSB: Jenkins Automation Server.
Access Jenkins using below url.
URL - http://localhost:8080/
In this article we haven’t touched on securing the jenkins instance, but when you access the above URL, it show as message stating that your jenkins instances configured with administrator password by default for security reasons, so you can login with the default password shown on the page which is also logged in the log file mentioned in the message.
Hope you enjoyed reading this article. Thank you..
1 COMMENT