diff --git a/README.rdoc b/README.rdoc index 329c84d..cbf91f6 100644 --- a/README.rdoc +++ b/README.rdoc @@ -34,7 +34,7 @@ Where the jenkins_login recipe is simply: jenkins_cli "login --username #{node[:jenkins][:username]} --password #{node[:jenkins][:password]}" -= ATTRIBUTES: += ATTRIBUTES: * jenkins[:mirror] - Base URL for downloading Jenkins (server) * jenkins[:java_home] - Java install path, used for for cli commands @@ -53,7 +53,7 @@ Where the jenkins_login recipe is simply: * jenkins[:node][:launcher] - Node launch method, "jnlp", "ssh" or "command" * jenkins[:node][:availability] - "always" keeps node on-line, "demand" off-lines when idle * jenkins[:node][:in_demand_delay] - number of minutes for which jobs must be waiting in the queue before attempting to launch this slave. -* jenkins[:node][:idle_delay] - number of minutes that this slave must remain idle before taking it off-line. +* jenkins[:node][:idle_delay] - number of minutes that this slave must remain idle before taking it off-line. * jenkins[:node][:env] - "Node Properties" -> "Environment Variables" * jenkins[:node][:user] - user the slave runs as * jenkins[:node][:ssh_host] - Hostname or IP Jenkins should connect to when launching an SSH slave @@ -63,7 +63,7 @@ Where the jenkins_login recipe is simply: * jenkins[:node][:ssh_private_key] - jenkins master defaults to: `~/.ssh/id_rsa` (created by the default recipe) * jenkins[:node][:jvm_options] - SSH slave JVM options * jenkins[:iptables_allow] - if iptables is enabled, add a rule passing 'jenkins[:server][:port]' -* jenkins[:http_proxy][:variant] - use `nginx` or `apache2` to proxy traffic to jenkins backend (`nil` by default) +* jenkins[:nginx][:http_proxy][:variant] - use `nginx` or `apache2` to proxy traffic to jenkins backend (`nil` by default) * jenkins[:http_proxy][:www_redirect] - add a redirect rule for 'www.*' URL requests ("disable" by default) * jenkins[:http_proxy][:listen_ports] - list of HTTP ports for the HTTP proxy to listen on ([80] by default) * jenkins[:http_proxy][:host_name] - primary vhost name for the HTTP proxy to respond to (`node[:fqdn]` by default) @@ -169,6 +169,7 @@ This is a downstream fork of Doug MacEachern's Hudson cookbook (https://github.c Author:: Doug MacEachern () +Contributor:: AJ Christensen Contributor:: Fletcher Nichol Contributor:: Roman Kamyk Contributor:: Darko Fabijan diff --git a/attributes/default.rb b/attributes/default.rb index 112e1fc..42caf88 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -21,7 +21,8 @@ # limitations under the License. # -default[:jenkins][:mirror] = "http://updates.jenkins-ci.org" +default[:jenkins][:mirror] = "http://mirrors.jenkins-ci.org" +default[:jenkins][:package_url] = "http://pkg.jenkins-ci.org" default[:jenkins][:java_home] = ENV['JAVA_HOME'] default[:jenkins][:server][:home] = "/var/lib/jenkins" @@ -38,7 +39,7 @@ default[:jenkins][:server][:host] = node[:fqdn] default[:jenkins][:server][:url] = "http://#{node[:jenkins][:server][:host]}:#{node[:jenkins][:server][:port]}" -default[:jenkins][:iptables_allow] = "enable" +default[:jenkins][:iptables_allow] = "disable" #download the latest version of plugins, bypassing update center #example: ["git", "URLSCM", ...] @@ -120,3 +121,5 @@ default[:jenkins][:http_proxy][:host_name] = nil default[:jenkins][:http_proxy][:host_aliases] = [] default[:jenkins][:http_proxy][:client_max_body_size] = "1024m" +default[:jenkins][:http_proxy][:basic_auth_username] = "jenkins" +default[:jenkins][:http_proxy][:basic_auth_password] = "jenkins" diff --git a/files/default/node_info.groovy b/files/default/node_info.groovy index 785f511..36a8744 100644 --- a/files/default/node_info.groovy +++ b/files/default/node_info.groovy @@ -11,9 +11,9 @@ # 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. diff --git a/libraries/manage_node.rb b/libraries/manage_node.rb index 5ba291c..859b015 100644 --- a/libraries/manage_node.rb +++ b/libraries/manage_node.rb @@ -11,9 +11,9 @@ # 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. diff --git a/metadata.rb b/metadata.rb index c52f3ce..dba2560 100644 --- a/metadata.rb +++ b/metadata.rb @@ -1,7 +1,9 @@ -maintainer "Fletcher Nichol" -maintainer_email "fnichol@nichol.ca" +maintainer "AJ Christensen" +maintainer_email "aj@junglist.gen.nz" license "Apache 2.0" description "Installs and configures Jenkins CI server & slaves" long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc')) -version "0.5" -%w(runit java iptables).each { |cb| depends cb } +version "0.6" + +%w(runit java).each { |cb| depends cb } +%w(iptables yum apt).each { |cb| recommends cb } diff --git a/providers/execute.rb b/providers/execute.rb index f04d4ea..aee7f3b 100644 --- a/providers/execute.rb +++ b/providers/execute.rb @@ -34,7 +34,7 @@ def action_run args[:not_if] = @new_resource.not_if if @new_resource.not_if args[:timeout] = @new_resource.timeout if @new_resource.timeout args[:cwd] = @new_resource.cwd if @new_resource.cwd - + status, stdout, stderr = output_of_command(args[:command], args) if status.exitstatus == 0 @new_resource.block.call(stdout) if @new_resource.block @@ -46,5 +46,3 @@ def action_run handle_command_failures(status, command_output, args) end end - - diff --git a/providers/job.rb b/providers/job.rb index dfd0dce..11a87b1 100644 --- a/providers/job.rb +++ b/providers/job.rb @@ -22,7 +22,9 @@ # def job_url - "#{@new_resource.url}/job/#{@new_resource.job_name}/config.xml" + job_url = "#{@new_resource.url}/job/#{@new_resource.job_name}/config.xml" + Chef::Log.debug "[jenkins_job] job_url: #{job_url}" + job_url end def new_job_url diff --git a/recipes/default.rb b/recipes/default.rb index 615738e..a5480d9 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -3,6 +3,7 @@ # Based on hudson # Recipe:: default # +# Author:: AJ Christensen # Author:: Doug MacEachern # Author:: Fletcher Nichol # @@ -60,81 +61,44 @@ node[:jenkins][:server][:plugins].each do |name| remote_file "#{node[:jenkins][:server][:home]}/plugins/#{name}.hpi" do - source "#{node[:jenkins][:mirror]}/latest/#{name}.hpi" + source "#{node[:jenkins][:mirror]}/plugins/#{name}/latest/#{name}.hpi" backup false owner node[:jenkins][:server][:user] group node[:jenkins][:server][:group] - action :nothing - end - - http_request "HEAD #{node[:jenkins][:mirror]}/latest/#{name}.hpi" do - message "" - url "#{node[:jenkins][:mirror]}/latest/#{name}.hpi" - action :head - if File.exists?("#{node[:jenkins][:server][:home]}/plugins/#{name}.hpi") - headers "If-Modified-Since" => File.mtime("#{node[:jenkins][:server][:home]}/plugins/#{name}.hpi").httpdate - end - notifies :create, resources(:remote_file => "#{node[:jenkins][:server][:home]}/plugins/#{name}.hpi"), :immediately end end case node.platform when "ubuntu", "debian" - # See http://jenkins-ci.org/debian/ - - case node.platform - when "debian" - remote = "#{node[:jenkins][:mirror]}/latest/debian/jenkins.deb" - package_provider = Chef::Provider::Package::Dpkg - - package "daemon" - # These are both dependencies of the jenkins deb package - package "jamvm" - package "openjdk-6-jre" - - package "psmisc" - key_url = "http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key" - - remote_file "#{tmp}/jenkins-ci.org.key" do - source "#{key_url}" - end - - execute "add-jenkins-key" do - command "apt-key add #{tmp}/jenkins-ci.org.key" - action :nothing - end - - when "ubuntu" - include_recipe "apt" - include_recipe "java" - - apt_repository "jenkins" do - uri "http://pkg.jenkins-ci.org/debian" - distribution "binary/" - components [""] - key "http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key" - action :add - end - end + include_recipe "apt" + include_recipe "java" pid_file = "/var/run/jenkins/jenkins.pid" install_starts_service = true - + apt_repository "jenkins" do + uri "#{node.jenkins.package_url}/debian" + components %w[binary/] + key "http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key" + action :add + end when "centos", "redhat" - #see http://jenkins-ci.org/redhat/ - key_url = "http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key" + include_recipe "yum" - remote = "#{node[:jenkins][:mirror]}/latest/redhat/jenkins.rpm" - package_provider = Chef::Provider::Package::Rpm pid_file = "/var/run/jenkins.pid" install_starts_service = false - execute "add-jenkins-key" do - command "rpm --import #{key_url}" - action :nothing + yum_key "jenkins" do + url "#{node.jenkins.package_url}/redhat/jenkins-ci.org.key" + action :add end + yum_repository "jenkins" do + description "repository for jenkins" + url "#{node.jenkins.package_url}/redhat/" + key "jenkins" + action :add + end end #"jenkins stop" may (likely) exit before the process is actually dead @@ -154,6 +118,12 @@ action :nothing end +service "jenkins" do + supports [ :stop, :start, :restart, :status ] + status_command "test -f #{pid_file} && kill -0 `cat #{pid_file}`" + action :nothing +end + ruby_block "block_until_operational" do block do until IO.popen("netstat -lnt").entries.select { |entry| @@ -167,68 +137,27 @@ url = URI.parse("#{node.jenkins.server.url}/job/test/config.xml") res = Chef::REST::RESTRequest.new(:GET, url, nil).call break if res.kind_of?(Net::HTTPSuccess) or res.kind_of?(Net::HTTPNotFound) - Chef::Log.debug "service[jenkins] not responding OK to GET /job/test/config.xml #{res.inspect}" + Chef::Log.debug "service[jenkins] not responding OK to GET / #{res.inspect}" sleep 1 end end action :nothing end -service "jenkins" do - supports [ :stop, :start, :restart, :status ] - #"jenkins status" will exit(0) even when the process is not running - status_command "test -f #{pid_file} && kill -0 `cat #{pid_file}`" - action :nothing -end - -if node.platform == "ubuntu" - execute "setup-jenkins" do - command "echo w00t" - notifies :stop, "service[jenkins]", :immediately - notifies :create, "ruby_block[netstat]", :immediately #wait a moment for the port to be released - notifies :install, "package[jenkins]", :immediately - unless install_starts_service - notifies :start, "service[jenkins]", :immediately - end - notifies :create, "ruby_block[block_until_operational]", :immediately - creates "/usr/share/jenkins/jenkins.war" - end -else - local = File.join(tmp, File.basename(remote)) - - remote_file local do - source remote - backup false - notifies :stop, "service[jenkins]", :immediately - notifies :create, "ruby_block[netstat]", :immediately #wait a moment for the port to be released - notifies :run, "execute[add-jenkins-key]", :immediately - notifies :install, "package[jenkins]", :immediately - unless install_starts_service - notifies :start, "service[jenkins]", :immediately - end - if node[:jenkins][:server][:use_head] #XXX remove when CHEF-1848 is merged - action :nothing - end - end - - http_request "HEAD #{remote}" do - only_if { node[:jenkins][:server][:use_head] } #XXX remove when CHEF-1848 is merged - message "" - url remote - action :head - if File.exists?(local) - headers "If-Modified-Since" => File.mtime(local).httpdate - end - notifies :create, "remote_file[#{local}]", :immediately +log "jenkins: install and start" do + notifies :install, "package[jenkins]", :immediately + notifies :start, "service[jenkins]", :immediately unless install_starts_service + notifies :create, "ruby_block[block_until_operational]", :immediately + not_if do + File.exists? "/usr/share/jenkins/jenkins.war" end end -#this is defined after http_request/remote_file because the package -#providers will throw an exception if `source' doesn't exist +template "/etc/default/jenkins" + package "jenkins" do - provider package_provider - source local if node.platform != "ubuntu" action :nothing + notifies :create, "template[/etc/default/jenkins]", :immediately end # restart if this run only added new plugins @@ -246,6 +175,8 @@ }.size > 0 end end + + action :nothing end # Front Jenkins with an HTTP server @@ -255,3 +186,14 @@ when "apache2" include_recipe "jenkins::proxy_apache2" end + +if node.jenkins.iptables_allow == "enable" + include_recipe "iptables" + iptables_rule "port_jenkins" do + if node[:jenkins][:iptables_allow] == "enable" + enable true + else + enable false + end + end +end diff --git a/recipes/node_jnlp.rb b/recipes/node_jnlp.rb index 6b1098a..cad8523 100644 --- a/recipes/node_jnlp.rb +++ b/recipes/node_jnlp.rb @@ -11,9 +11,9 @@ # 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. diff --git a/recipes/node_ssh.rb b/recipes/node_ssh.rb index c6d892e..8e70405 100644 --- a/recipes/node_ssh.rb +++ b/recipes/node_ssh.rb @@ -11,9 +11,9 @@ # 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. diff --git a/recipes/node_windows.rb b/recipes/node_windows.rb index 6b3ce64..b8d7b71 100644 --- a/recipes/node_windows.rb +++ b/recipes/node_windows.rb @@ -11,9 +11,9 @@ # 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. diff --git a/recipes/proxy_apache2.rb b/recipes/proxy_apache2.rb index 288add2..4e6808e 100644 --- a/recipes/proxy_apache2.rb +++ b/recipes/proxy_apache2.rb @@ -21,9 +21,6 @@ include_recipe "apache2" -package_provider = Chef::Provider::Package::Apt -package "libapache2-mod-proxy-html" - apache_module "proxy" apache_module "proxy_http" apache_module "vhost_alias" @@ -37,6 +34,14 @@ host_name = node[:jenkins][:http_proxy][:host_name] || node[:fqdn] +template "#{node.apache.dir}/htpasswd" do + variables( :username => node.jenkins.http_proxy.basic_auth_username, + :password => node.jenkins.http_proxy.basic_auth_password) + owner node.apache.user + group node.apache.user + mode 0600 +end + template "#{node[:apache][:dir]}/sites-available/jenkins" do source "apache_jenkins.erb" owner 'root' diff --git a/resources/node.rb b/resources/node.rb index e64617d..f8c5ae6 100644 --- a/resources/node.rb +++ b/resources/node.rb @@ -51,4 +51,3 @@ def initialize(name, run_context=nil) super @action = :create end - diff --git a/templates/default/apache_jenkins.erb b/templates/default/apache_jenkins.erb index 1930ba1..b05d87a 100644 --- a/templates/default/apache_jenkins.erb +++ b/templates/default/apache_jenkins.erb @@ -29,4 +29,12 @@ ProxyPreserveHost on ProxyPass / http://localhost:<%= node[:jenkins][:server][:port] %>/ ProxyPassReverse / http://localhost:<%= node[:jenkins][:server][:port] %>/ + + + AuthType basic + AuthName "Jenkins" + AuthBasicProvider file + AuthUserFile <%= File.join(node.apache.dir, "htpasswd") %> + require valid-user + diff --git a/templates/default/htpasswd.erb b/templates/default/htpasswd.erb new file mode 100644 index 0000000..d604aef --- /dev/null +++ b/templates/default/htpasswd.erb @@ -0,0 +1 @@ +<%= @username -%>:<%= @password.crypt("Zz") %> diff --git a/templates/default/hudson-slave.xml b/templates/default/hudson-slave.xml deleted file mode 100644 index c8dbe11..0000000 --- a/templates/default/hudson-slave.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - jenkinsslave - Jenkins Slave - This service runs a slave for Jenkins continuous integration system. -(Installed by Chef) - - - java - -Xrs -jar "<%= @jenkins_home %>\slave.jar" -jnlpUrl <%= @jnlp_url %> - - rotate - diff --git a/templates/default/jenkins.erb b/templates/default/jenkins.erb new file mode 100644 index 0000000..d759156 --- /dev/null +++ b/templates/default/jenkins.erb @@ -0,0 +1,55 @@ +# 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=<%= node.jenkins.server.user %> + +# location of the jenkins war file +JENKINS_WAR=/usr/share/jenkins/jenkins.war + +# jenkins home location +JENKINS_HOME=<%= node.jenkins.server.home %> + +# 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_HOST=<%= node.jenkins.server.host %> +HTTP_PORT=<%= node.jenkins.server.port %> + +# port for AJP connector (disabled by default) +AJP_PORT=-1 + +# 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.$ADMIN_USER=admin +# --webroot=~/.jenkins/war +JENKINS_ARGS="--webroot=/var/run/jenkins/war --httpListenAddress=$HTTP_HOST --httpPort=$HTTP_PORT --ajp13Port=$AJP_PORT" diff --git a/templates/default/port_jenkins.erb b/templates/default/port_jenkins.erb index 74e526b..5ec2081 100644 --- a/templates/default/port_jenkins.erb +++ b/templates/default/port_jenkins.erb @@ -1,2 +1,2 @@ # jenkins --A FWR -p tcp -m tcp --dport <%= node[:jenkins][:server][:port] %> -j ACCEPT +-A FWR -p tcp -m tcp --dport <%= node[:jenkins][:server][:firewall_port] %> -j ACCEPT