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.
Files changed (47) hide show
  1. data/.gitignore +73 -16
  2. data/Gemfile.lock +80 -0
  3. data/README.md +169 -56
  4. data/Vagrantfile +23 -0
  5. data/example/Gemfile +3 -1
  6. data/example/README.md +13 -17
  7. data/example/config/deploy.rb +8 -12
  8. data/example/config/deploy/develop.rb +5 -3
  9. data/example/config/deploy/production.rb +13 -3
  10. data/example/config/deploy/staging.rb +13 -4
  11. data/example/config/jenkins/nodes/develop/dev-slave01.xml.erb +33 -0
  12. data/example/config/jenkins/nodes/production/prod-slave01.xml.erb +33 -0
  13. data/example/config/jenkins/nodes/production/prod-slave02.xml.erb +33 -0
  14. data/example/config/jenkins/nodes/production/prod-slave03.xml.erb +33 -0
  15. data/example/config/jenkins/nodes/staging/stg-slave01.xml.erb +33 -0
  16. data/example/config/jenkins/nodes/staging/stg-slave02.xml.erb +33 -0
  17. data/example/config/jenkins/nodes/staging/stg-slave03.xml.erb +33 -0
  18. data/example/script/bootstrap +1 -2
  19. data/features/config_jobs.feature +162 -0
  20. data/features/config_nodes.feature +121 -0
  21. data/features/config_views.feature +136 -0
  22. data/features/help.feature +83 -0
  23. data/features/step_definitions/jenkins_steps.rb +19 -0
  24. data/features/support/env.rb +5 -0
  25. data/features/support/jenkins_helper.rb +113 -0
  26. data/jenkins-capistrano.gemspec +4 -3
  27. data/lib/jenkins-capistrano.rb +2 -215
  28. data/lib/jenkins-capistrano/configurator.rb +87 -0
  29. data/lib/jenkins-capistrano/tasks.rb +112 -0
  30. data/lib/jenkins-capistrano/template.rb +20 -0
  31. data/lib/jenkins-capistrano/version.rb +1 -1
  32. metadata +87 -41
  33. checksums.yaml +0 -7
  34. data/example/config/jenkins/jobs/.gitkeep +0 -0
  35. data/example/config/jenkins/nodes/develop/dev-slave01.json +0 -17
  36. data/example/config/jenkins/nodes/production/prod-slave01.json +0 -17
  37. data/example/config/jenkins/nodes/production/prod-slave02.json +0 -17
  38. data/example/config/jenkins/nodes/production/prod-slave03.json +0 -17
  39. data/example/config/jenkins/nodes/staging/stg-slave01.json +0 -17
  40. data/example/config/jenkins/nodes/staging/stg-slave02.json +0 -17
  41. data/example/config/jenkins/nodes/staging/stg-slave03.json +0 -17
  42. data/lib/jenkins-capistrano/client.rb +0 -66
  43. data/lib/jenkins-capistrano/client/job.rb +0 -47
  44. data/lib/jenkins-capistrano/client/node.rb +0 -103
  45. data/lib/jenkins-capistrano/client/plugin_manager.rb +0 -51
  46. data/lib/jenkins-capistrano/client/update_center.rb +0 -43
  47. 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
-