jenkins-capistrano 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +73 -16
- data/Gemfile.lock +80 -0
- data/README.md +169 -56
- data/Vagrantfile +23 -0
- data/example/Gemfile +3 -1
- data/example/README.md +13 -17
- data/example/config/deploy.rb +8 -12
- data/example/config/deploy/develop.rb +5 -3
- data/example/config/deploy/production.rb +13 -3
- data/example/config/deploy/staging.rb +13 -4
- data/example/config/jenkins/nodes/develop/dev-slave01.xml.erb +33 -0
- data/example/config/jenkins/nodes/production/prod-slave01.xml.erb +33 -0
- data/example/config/jenkins/nodes/production/prod-slave02.xml.erb +33 -0
- data/example/config/jenkins/nodes/production/prod-slave03.xml.erb +33 -0
- data/example/config/jenkins/nodes/staging/stg-slave01.xml.erb +33 -0
- data/example/config/jenkins/nodes/staging/stg-slave02.xml.erb +33 -0
- data/example/config/jenkins/nodes/staging/stg-slave03.xml.erb +33 -0
- data/example/script/bootstrap +1 -2
- data/features/config_jobs.feature +162 -0
- data/features/config_nodes.feature +121 -0
- data/features/config_views.feature +136 -0
- data/features/help.feature +83 -0
- data/features/step_definitions/jenkins_steps.rb +19 -0
- data/features/support/env.rb +5 -0
- data/features/support/jenkins_helper.rb +113 -0
- data/jenkins-capistrano.gemspec +4 -3
- data/lib/jenkins-capistrano.rb +2 -215
- data/lib/jenkins-capistrano/configurator.rb +87 -0
- data/lib/jenkins-capistrano/tasks.rb +112 -0
- data/lib/jenkins-capistrano/template.rb +20 -0
- data/lib/jenkins-capistrano/version.rb +1 -1
- metadata +87 -41
- checksums.yaml +0 -7
- data/example/config/jenkins/jobs/.gitkeep +0 -0
- data/example/config/jenkins/nodes/develop/dev-slave01.json +0 -17
- data/example/config/jenkins/nodes/production/prod-slave01.json +0 -17
- data/example/config/jenkins/nodes/production/prod-slave02.json +0 -17
- data/example/config/jenkins/nodes/production/prod-slave03.json +0 -17
- data/example/config/jenkins/nodes/staging/stg-slave01.json +0 -17
- data/example/config/jenkins/nodes/staging/stg-slave02.json +0 -17
- data/example/config/jenkins/nodes/staging/stg-slave03.json +0 -17
- data/lib/jenkins-capistrano/client.rb +0 -66
- data/lib/jenkins-capistrano/client/job.rb +0 -47
- data/lib/jenkins-capistrano/client/node.rb +0 -103
- data/lib/jenkins-capistrano/client/plugin_manager.rb +0 -51
- data/lib/jenkins-capistrano/client/update_center.rb +0 -43
- data/lib/jenkins-capistrano/client/view.rb +0 -40
@@ -1,103 +0,0 @@
|
|
1
|
-
|
2
|
-
module Jenkins
|
3
|
-
class Client
|
4
|
-
module Node
|
5
|
-
|
6
|
-
def node_names
|
7
|
-
self.class.get("/computer/api/json")['computer'].map {|computer| computer['displayName'] }
|
8
|
-
end
|
9
|
-
|
10
|
-
def add_node(name, opts = {})
|
11
|
-
options = default_node_options.merge(opts)
|
12
|
-
options[:name] = name
|
13
|
-
options[:labels] = options[:labels].split(/\s*,\s*/).join(' ') if options[:labels]
|
14
|
-
options[:env_vars] = options[:env_vars].map { |k, v| { :key => k, :value => v } }
|
15
|
-
|
16
|
-
response = post_form("/computer/doCreateItem", node_form_fields(options))
|
17
|
-
case response
|
18
|
-
when Net::HTTPFound
|
19
|
-
{ :name => name, :slave_host => options[:slave_host] }
|
20
|
-
else
|
21
|
-
raise ServerError, parse_error_message(response)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def update_node(name, opts = {})
|
26
|
-
options = default_node_options.merge(opts)
|
27
|
-
options[:name] = name
|
28
|
-
options[:labels] = options[:labels].split(/\s*,\s*/).join(' ') if options[:labels]
|
29
|
-
options[:env_vars] = options[:env_vars].map { |k, v| { :key => k, :value => v } }
|
30
|
-
|
31
|
-
response = post_form("/computer/#{CGI::escape(name)}/configSubmit", node_form_fields(options))
|
32
|
-
case response
|
33
|
-
when Net::HTTPFound
|
34
|
-
{ :name => name, :slave_host => options[:slave_host] }
|
35
|
-
else
|
36
|
-
raise ServerError, parse_error_message(response)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def config_node(name, opts = {})
|
41
|
-
node_names.include?(name) ? update_node(name, opts) : add_node(name, opts)
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
def post_form(path, fields)
|
46
|
-
url = URI.parse("#{self.class.base_uri}/#{path}")
|
47
|
-
req = Net::HTTP::Post.new(url.path)
|
48
|
-
|
49
|
-
basic_auth = self.class.default_options[:basic_auth]
|
50
|
-
req.basic_auth basic_auth[:username], basic_auth[:password] if basic_auth
|
51
|
-
|
52
|
-
req.set_form_data(fields)
|
53
|
-
http = Net::HTTP.new(url.host, url.port)
|
54
|
-
http.request(req)
|
55
|
-
end
|
56
|
-
|
57
|
-
def default_node_options
|
58
|
-
{
|
59
|
-
:slave_port => 22,
|
60
|
-
:slave_user => 'jenkins',
|
61
|
-
:master_key => "/var/lib/jenkins/.ssh/id_rsa",
|
62
|
-
:slave_fs => "/data/jenkins-slave/",
|
63
|
-
:description => "Automatically created by capistrano-jenkins",
|
64
|
-
:executors => 2,
|
65
|
-
:exclusive => true
|
66
|
-
}
|
67
|
-
end
|
68
|
-
|
69
|
-
def node_form_fields(options = {})
|
70
|
-
{
|
71
|
-
"name" => options[:name],
|
72
|
-
"type" => "hudson.slaves.DumbSlave$DescriptorImpl",
|
73
|
-
"json" => {
|
74
|
-
"name" => options[:name],
|
75
|
-
"type" => "hudson.slaves.DumbSlave$DescriptorImpl",
|
76
|
-
"nodeDescription" => options[:description],
|
77
|
-
"numExecutors" => options[:executors],
|
78
|
-
"remoteFS" => options[:slave_fs],
|
79
|
-
"labelString" => options[:labels],
|
80
|
-
"mode" => options[:exclusive] ? "EXCLUSIVE" : "NORMAL",
|
81
|
-
"retentionStrategy" => { "stapler-class" => "hudson.slaves.RetentionStrategy$Always" },
|
82
|
-
"launcher" => {
|
83
|
-
"stapler-class" => "hudson.plugins.sshslaves.SSHLauncher",
|
84
|
-
"host" => options[:slave_host],
|
85
|
-
"port" => options[:slave_port],
|
86
|
-
"username" => options[:slave_user],
|
87
|
-
"privatekey" => options[:master_key],
|
88
|
-
"javaPath" => options[:java_path],
|
89
|
-
"jvmOptions" => options[:jvm_options]
|
90
|
-
},
|
91
|
-
"nodeProperties" => {
|
92
|
-
"stapler-class-bag" => "true",
|
93
|
-
"hudson-slaves-EnvironmentVariablesNodeProperty" => {
|
94
|
-
"env" => options[:env_vars]
|
95
|
-
}
|
96
|
-
}
|
97
|
-
}.to_json
|
98
|
-
}
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
@@ -1,51 +0,0 @@
|
|
1
|
-
|
2
|
-
module Jenkins
|
3
|
-
class Client
|
4
|
-
module PluginManager
|
5
|
-
|
6
|
-
def plugin_names
|
7
|
-
self.class.get("/pluginManager/api/json?tree=plugins[shortName]")['plugins'].map {|plugin| plugin['name'] }
|
8
|
-
end
|
9
|
-
|
10
|
-
def prevalidate_plugin_config(plugins)
|
11
|
-
config = generate_config(plugins)
|
12
|
-
res = self.class.post("/pluginManager/prevalidateConfig", xml_body(config))
|
13
|
-
raise ServerError, parse_error_message(res) unless res.code.to_i == 200
|
14
|
-
# why does HTTParty parses the response as xml?
|
15
|
-
JSON.parse(res.body)
|
16
|
-
end
|
17
|
-
|
18
|
-
def install_plugin(plugins, timeout = 60)
|
19
|
-
config = generate_config(plugins)
|
20
|
-
res = self.class.post("/pluginManager/installNecessaryPlugins", xml_body(config))
|
21
|
-
raise ServerError, parse_error_message(res) unless res.code.to_i == 302
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
def xml_body(xml_str)
|
26
|
-
{
|
27
|
-
:body => xml_str,
|
28
|
-
:format => :xml,
|
29
|
-
:headers => { 'content-type' => 'application/xml' }
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
33
|
-
def generate_config(config)
|
34
|
-
plugins = config.map do |v|
|
35
|
-
plugin = case
|
36
|
-
when v.instance_of?(String)
|
37
|
-
v.include?('@') ? v : v + '@*'
|
38
|
-
when v.instance_of?(Hash)
|
39
|
-
"#{v['name']}@#{v['version']}"
|
40
|
-
else
|
41
|
-
raise "Unknown value for plugin config: #{v}"
|
42
|
-
end
|
43
|
-
"<installation plugin='#{plugin}' />"
|
44
|
-
end.join("\n")
|
45
|
-
"<installations>#{plugins}</installations>"
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
@@ -1,43 +0,0 @@
|
|
1
|
-
|
2
|
-
module Jenkins
|
3
|
-
class Client
|
4
|
-
module UpdateCenter
|
5
|
-
|
6
|
-
def installation_jobs
|
7
|
-
job = self.class.get("/updateCenter/api/json?tree=jobs[id,type,status[success],plugin[name,version]]")['jobs']
|
8
|
-
job.reduce([]) do |mem, job|
|
9
|
-
if job['type'] == 'InstallationJob'
|
10
|
-
mem << {
|
11
|
-
'id' => job['id'],
|
12
|
-
'type' => job['type'],
|
13
|
-
'status' => job['status']['success'],
|
14
|
-
'name' => job['plugin']['name'],
|
15
|
-
'version' => job['plugin']['version']
|
16
|
-
}
|
17
|
-
end
|
18
|
-
mem
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def wait_for_complete(timeout = 60 * 5)
|
23
|
-
due = Time.now + timeout
|
24
|
-
loop do
|
25
|
-
complete = installation_jobs.reduce(true) do |comp, job|
|
26
|
-
comp & (block_given? ? yield(job) : job['status'] == true)
|
27
|
-
end
|
28
|
-
break if complete
|
29
|
-
raise TimeoutError, "Installation timeout: #{timeout}" if Time.now > due
|
30
|
-
sleep 1
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def restart_required?
|
35
|
-
res = self.class.get("/pluginManager/api/json?tree=restartRequiredForCompletion")
|
36
|
-
raise ServerError, parse_error_message(res) unless res.code.to_i == 200
|
37
|
-
res['restartRequiredForCompletion'] == true
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
@@ -1,40 +0,0 @@
|
|
1
|
-
|
2
|
-
module Jenkins
|
3
|
-
class Client
|
4
|
-
module View
|
5
|
-
|
6
|
-
def view_names
|
7
|
-
self.class.get("/api/json")['views'].map {|view| view['name'] }
|
8
|
-
end
|
9
|
-
|
10
|
-
def create_view(name, config)
|
11
|
-
res = self.class.post("/createView/?name=#{CGI.escape(name)}", xml_body(config))
|
12
|
-
raise ServerError, parse_error_message(res) unless res.code.to_i == 200
|
13
|
-
rescue => e
|
14
|
-
raise ServerError, "Failed to create view: #{name}, make sure you have specified auth info properly"
|
15
|
-
end
|
16
|
-
|
17
|
-
def update_view(name, config)
|
18
|
-
res = self.class.post("/view/#{CGI.escape(name)}/config.xml", xml_body(config))
|
19
|
-
raise ServerError, parse_error_message(res) unless res.code.to_i == 200
|
20
|
-
rescue => e
|
21
|
-
raise ServerError, "Failed to create view: #{name}, make sure you have specified auth info properly"
|
22
|
-
end
|
23
|
-
|
24
|
-
def create_or_update_view(name, config)
|
25
|
-
view_names.include?(name) ? update_view(name, config) : create_view(name, config)
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
def xml_body(xml_str)
|
30
|
-
{
|
31
|
-
:body => xml_str,
|
32
|
-
:format => :xml,
|
33
|
-
:headers => { 'content-type' => 'application/xml' }
|
34
|
-
}
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|