jenkins-capistrano 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
-