jenkins_api_client 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +3 -0
  2. data/.jenkins.yml +9 -0
  3. data/.travis.yml +11 -15
  4. data/CHANGELOG.md +15 -0
  5. data/Gemfile +2 -2
  6. data/README.md +7 -9
  7. data/Rakefile +27 -14
  8. data/lib/jenkins_api_client.rb +36 -6
  9. data/lib/jenkins_api_client/build_queue.rb +213 -0
  10. data/lib/jenkins_api_client/cli/base.rb +10 -6
  11. data/lib/jenkins_api_client/cli/helper.rb +13 -4
  12. data/lib/jenkins_api_client/cli/job.rb +6 -9
  13. data/lib/jenkins_api_client/cli/node.rb +6 -4
  14. data/lib/jenkins_api_client/cli/system.rb +2 -1
  15. data/lib/jenkins_api_client/client.rb +31 -25
  16. data/lib/jenkins_api_client/job.rb +248 -95
  17. data/lib/jenkins_api_client/node.rb +128 -10
  18. data/lib/jenkins_api_client/system.rb +4 -2
  19. data/lib/jenkins_api_client/version.rb +2 -2
  20. data/lib/jenkins_api_client/view.rb +17 -4
  21. data/scripts/login_with_irb.rb +4 -3
  22. data/spec/func_tests/client_spec.rb +90 -0
  23. data/spec/func_tests/job_spec.rb +348 -0
  24. data/spec/func_tests/node_spec.rb +174 -0
  25. data/spec/{spec_helper.rb → func_tests/spec_helper.rb} +2 -2
  26. data/spec/func_tests/system_spec.rb +55 -0
  27. data/spec/func_tests/view_spec.rb +53 -0
  28. data/spec/unit_tests/client_spec.rb +211 -0
  29. data/spec/unit_tests/fixtures/files/computer_sample.xml +17 -0
  30. data/spec/unit_tests/fixtures/files/job_sample.xml +16 -0
  31. data/spec/unit_tests/job_spec.rb +355 -0
  32. data/spec/unit_tests/node_spec.rb +192 -0
  33. data/spec/unit_tests/spec_helper.rb +8 -0
  34. data/spec/unit_tests/system_spec.rb +54 -0
  35. data/spec/unit_tests/view_spec.rb +127 -0
  36. metadata +34 -23
  37. data/spec/client_spec.rb +0 -52
  38. data/spec/job_spec.rb +0 -158
  39. data/spec/node_spec.rb +0 -48
  40. data/spec/system_spec.rb +0 -46
@@ -37,7 +37,7 @@ module JenkinsApi
37
37
  "busyExecutors",
38
38
  "displayName",
39
39
  "totalExecutors"
40
- ]
40
+ ].freeze
41
41
 
42
42
  # Properties of a node.
43
43
  # The following methods are defined to be called on the node object
@@ -57,7 +57,7 @@ module JenkinsApi
57
57
  "manualLaunchAllowed",
58
58
  "offline",
59
59
  "temporarilyOffline"
60
- ]
60
+ ].freeze
61
61
 
62
62
  # Node specific attributes.
63
63
  # The following methods are defined using define_method.
@@ -79,7 +79,7 @@ module JenkinsApi
79
79
  "monitorData",
80
80
  "offlineCause",
81
81
  "oneOffExecutors"
82
- ]
82
+ ].freeze
83
83
 
84
84
  # Initializes a new node object
85
85
  #
@@ -89,10 +89,91 @@ module JenkinsApi
89
89
  @client = client
90
90
  end
91
91
 
92
+ # Gives the string representation of the Object
93
+ #
92
94
  def to_s
93
95
  "#<JenkinsApi::Client::Node>"
94
96
  end
95
97
 
98
+ # Creates a new node with the specified parameters
99
+ #
100
+ # @param [Hash] params parameters for creating a dump slave
101
+ # * +:name+ name of the slave
102
+ # * +:description+ description of the new slave
103
+ # * +:executors+ number of executors
104
+ # * +:remote_fs+ Remote FS root
105
+ # * +:labels+ comma separated list of labels
106
+ # * +:mode+ mode of the slave: normal, exclusive
107
+ # * +:slave_host+ Hostname/IP of the slave
108
+ # * +:slave_port+ Slave port
109
+ # * +:private_key_file+ Private key file of master
110
+ #
111
+ def create_dump_slave(params)
112
+
113
+ if list.include?(params[:name])
114
+ raise "The specified slave '#{params[:name]}' already exists."
115
+ end
116
+
117
+ unless params[:name] && params[:slave_host] && params[:private_key_file]
118
+ raise "Name, slave host, and private key file are required for" +
119
+ " creating a slave."
120
+ end
121
+
122
+ default_params = {
123
+ :description => "Automatically created through jenkins_api_client",
124
+ :executors => 2,
125
+ :remote_fs => "/var/jenkins",
126
+ :labels => params[:name],
127
+ :slave_port => 22,
128
+ :mode => "normal"
129
+ }
130
+
131
+ params = default_params.merge(params)
132
+ labels = params[:labels].split(/\s*,\s*/).join(" ")
133
+ mode = params[:mode].upcase
134
+
135
+ post_params = {
136
+ "name" => params[:name],
137
+ "type" => "hudson.slaves.DumbSlave$DescriptorImpl",
138
+ "json" => {
139
+ "name" => params[:name],
140
+ "nodeDescription" => params[:description],
141
+ "numExecutors" => params[:executors],
142
+ "remoteFS" => params[:remote_fs],
143
+ "labelString" => labels,
144
+ "mode" => mode,
145
+ "type" => "hudson.slaves.DumbSlave$DescriptorImpl",
146
+ "retentionStrategy" => {
147
+ "stapler-class" => "hudson.slaves.RetentionStrategy$Always"
148
+ },
149
+ "nodeProperties" => {
150
+ "stapler-class-bag" => "true"
151
+ },
152
+ "launcher" => {
153
+ "stapler-class" => "hudson.plugins.sshslaves.SSHLauncher",
154
+ "host" => params[:slave_host],
155
+ "port" => params[:slave_port],
156
+ "username" => params[:slave_user],
157
+ "privatekey" => params[:private_key_file],
158
+ }
159
+ }.to_json
160
+ }
161
+
162
+ @client.api_post_request("/computer/doCreateItem", post_params)
163
+ end
164
+
165
+ # Deletes the specified node
166
+ #
167
+ # @params [String] node_name Name of the node to delete
168
+ #
169
+ def delete(node_name)
170
+ if list.include?(node_name)
171
+ @client.api_post_request("/computer/#{node_name}/doDelete")
172
+ else
173
+ raise "The specified node '#{node_name}' doesn't exist in Jenkins."
174
+ end
175
+ end
176
+
96
177
  # This method lists all nodes
97
178
  #
98
179
  # @param [String] filter a regex to filter node names
@@ -101,9 +182,11 @@ module JenkinsApi
101
182
  def list(filter = nil, ignorecase = true)
102
183
  node_names = []
103
184
  response_json = @client.api_get_request("/computer")
104
- response_json["computer"].each { |computer|
105
- node_names << computer["displayName"] if computer["displayName"] =~ /#{filter}/i
106
- }
185
+ response_json["computer"].each do |computer|
186
+ if computer["displayName"] =~ /#{filter}/i
187
+ node_names << computer["displayName"]
188
+ end
189
+ end
107
190
  node_names
108
191
  end
109
192
 
@@ -113,9 +196,9 @@ module JenkinsApi
113
196
  #
114
197
  def index(node_name)
115
198
  response_json = @client.api_get_request("/computer")
116
- response_json["computer"].each_with_index { |computer, index|
199
+ response_json["computer"].each_with_index do |computer, index|
117
200
  return index if computer["displayName"] == node_name
118
- }
201
+ end
119
202
  end
120
203
 
121
204
  # Defines methods for general node attributes.
@@ -132,7 +215,8 @@ module JenkinsApi
132
215
  NODE_PROPERTIES.each do |meth_suffix|
133
216
  define_method("is_#{meth_suffix}?") do |node_name|
134
217
  response_json = @client.api_get_request("/computer")
135
- response_json["computer"][index(node_name)]["#{meth_suffix}"] =~ /False/i ? false : true
218
+ resp = response_json["computer"][index(node_name)]["#{meth_suffix}"]
219
+ resp =~ /False/i ? false : true
136
220
  end
137
221
  end
138
222
 
@@ -144,6 +228,40 @@ module JenkinsApi
144
228
  end
145
229
  end
146
230
 
231
+ # Changes the mode of a slave node in Jenkins
232
+ #
233
+ # @param [String] node_name name of the node to change mode for
234
+ # @param [String] mode mode to change to
235
+ #
236
+ def change_mode(node_name, mode)
237
+ mode = mode.upcase
238
+ xml = get_config(node_name)
239
+ n_xml = Nokogiri::XML(xml)
240
+ desc = n_xml.xpath("//mode").first
241
+ desc.content = "#{mode.upcase}"
242
+ xml_modified = n_xml.to_xml
243
+ post_config(node_name, xml_modified)
244
+ end
245
+
246
+ # Obtains the configuration of node from Jenkins server
247
+ #
248
+ # @param [String] node_name name of the node
249
+ #
250
+ def get_config(node_name)
251
+ node_name = "(master)" if node_name == "master"
252
+ @client.get_config("/computer/#{node_name}/config.xml")
253
+ end
254
+
255
+ # Posts the given config.xml to the Jenkins node
256
+ #
257
+ # @param [String] node_name name of the node
258
+ # @param [String] xml Config.xml of the node
259
+ #
260
+ def post_config(node_name, xml)
261
+ node_name = "(master)" if node_name == "master"
262
+ @client.post_config("/computer/#{node_name}/config.xml", xml)
263
+ end
264
+
147
265
  end
148
266
  end
149
- end
267
+ end
@@ -54,7 +54,8 @@ module JenkinsApi
54
54
 
55
55
  # Restarts the Jenkins server
56
56
  #
57
- # @param [Bool] force whether to force restart or wait till all jobs are completed.
57
+ # @param [Bool] force whether to force restart or wait till all
58
+ # jobs are completed.
58
59
  #
59
60
  def restart(force = false)
60
61
  if force
@@ -64,7 +65,8 @@ module JenkinsApi
64
65
  end
65
66
  end
66
67
 
67
- # This method waits till the server becomes ready after a start or restart.
68
+ # This method waits till the server becomes ready after a start
69
+ # or restart.
68
70
  #
69
71
  def wait_for_ready
70
72
  Timeout::timeout(120) do
@@ -23,8 +23,8 @@
23
23
  module JenkinsApi
24
24
  class Client
25
25
  MAJOR = 0
26
- MINOR = 6
27
- TINY = 2
26
+ MINOR = 7
27
+ TINY = 0
28
28
  PRE = nil
29
29
  VERSION = [MAJOR, MINOR, TINY, PRE].compact.join('.')
30
30
  end
@@ -43,7 +43,10 @@ module JenkinsApi
43
43
  # @param [String] view_name
44
44
  #
45
45
  def create(view_name)
46
- @client.api_post_request("/createView?name=#{view_name}&mode=hudson.model.ListView&json={\"name\":\"#{view_name}\",\"mode\":\"hudson.model.ListView\"}")
46
+ post_msg = "/createView?name=#{view_name}&"
47
+ post_msg << "mode=hudson.model.ListView&json={\"name\":\"#{view_name}}"
48
+ post_msg << "\",\"mode\":\"hudson.model.ListView\"}"
49
+ @client.api_post_request(post_msg)
47
50
  end
48
51
 
49
52
  # Delete a view
@@ -63,7 +66,11 @@ module JenkinsApi
63
66
  view_names = []
64
67
  response_json = @client.api_get_request("/")
65
68
  response_json["views"].each { |view|
66
- view_names << view["name"] if view["name"] =~ /#{filter}/i
69
+ if ignorecase
70
+ view_names << view["name"] if view["name"] =~ /#{filter}/i
71
+ else
72
+ view_names << view["name"] if view["name"] =~ /#{filter}/
73
+ end
67
74
  }
68
75
  view_names
69
76
  end
@@ -80,8 +87,12 @@ module JenkinsApi
80
87
  #
81
88
  # @param [String] view_name
82
89
  #
90
+ # @return [Array] job_names list of jobs in the specified view
91
+ #
83
92
  def list_jobs(view_name)
84
93
  job_names = []
94
+ raise "The view #{view_name} doesn't exists on the server"\
95
+ unless exists?(view_name)
85
96
  response_json = @client.api_get_request("/view/#{view_name}")
86
97
  response_json["jobs"].each do |job|
87
98
  job_names << job["name"]
@@ -95,7 +106,8 @@ module JenkinsApi
95
106
  # @param [String] job_name
96
107
  #
97
108
  def add_job(view_name, job_name)
98
- @client.api_post_request("/view/#{view_name}/addJobToView?name=#{job_name}")
109
+ post_msg = "/view/#{view_name}/addJobToView?name=#{job_name}"
110
+ @client.api_post_request(post_msg)
99
111
  end
100
112
 
101
113
  # Remove a job from view
@@ -104,7 +116,8 @@ module JenkinsApi
104
116
  # @param [String] job_name
105
117
  #
106
118
  def remove_job(view_name, job_name)
107
- @client.api_post_request("/view/#{view_name}/removeJobFromView?name=#{job_name}")
119
+ post_msg = "/view/#{view_name}/removeJobFromView?name=#{job_name}"
120
+ @client.api_post_request(post_msg)
108
121
  end
109
122
 
110
123
  # Obtain the configuration stored in config.xml of a specific view
@@ -1,8 +1,9 @@
1
1
  # This script provides an easier way to login to Jenkins server API.
2
- # It logs you in with the credentials and server details you proided and then starts an IRB
3
- # session so you can interactively play with the API.
2
+ # It logs you in with the credentials and server details you proided and then
3
+ # starts an IRB session so you can interactively play with the API.
4
4
 
5
- require File.expand_path('../../lib/jenkins_api_client', __FILE__)
5
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
6
+ require 'jenkins_api_client'
6
7
  require 'yaml'
7
8
  require 'irb'
8
9
 
@@ -0,0 +1,90 @@
1
+ #
2
+ # Specifying JenkinsApi::Client class capabilities
3
+ # Author: Kannan Manickam <arangamani.kannan@gmail.com>
4
+ #
5
+
6
+ require File.expand_path('../spec_helper', __FILE__)
7
+ require 'yaml'
8
+
9
+ describe JenkinsApi::Client do
10
+ context "Given valid credentials and server information are given" do
11
+ before(:all) do
12
+ @creds_file = '~/.jenkins_api_client/spec.yml'
13
+ # Grabbing just the server IP in a variable so we can check
14
+ # for wrong credentials
15
+ @server_ip = YAML.load_file(
16
+ File.expand_path(@creds_file, __FILE__)
17
+ )[:server_ip]
18
+ begin
19
+ @client = JenkinsApi::Client.new(
20
+ YAML.load_file(File.expand_path(@creds_file, __FILE__))
21
+ )
22
+ rescue Exception => e
23
+ puts "WARNING: Credentials are not set properly."
24
+ puts e.message
25
+ end
26
+ end
27
+
28
+ describe "InstanceMethods" do
29
+
30
+ describe "#debug" do
31
+ it "Should be able to toggle the debug value" do
32
+ value = @client.debug
33
+ @client.toggle_debug.should_not == value
34
+ end
35
+ end
36
+
37
+ describe "#initialize" do
38
+ it "Should be able to initialize with valid credentials" do
39
+ client1 = JenkinsApi::Client.new(
40
+ YAML.load_file(File.expand_path(@creds_file, __FILE__))
41
+ )
42
+ client1.class.should == JenkinsApi::Client
43
+ end
44
+
45
+ it "Should accept a YAML argument when creating a new client" do
46
+ client3 = JenkinsApi::Client.new(
47
+ YAML.load_file(File.expand_path(@creds_file, __FILE__))
48
+ )
49
+ client3.class.should == JenkinsApi::Client
50
+ end
51
+
52
+ it "Should fail if wrong credentials are given" do
53
+ begin
54
+ client2 = JenkinsApi::Client.new(:server_ip => @server_ip,
55
+ :username => 'stranger',
56
+ :password => 'hacked')
57
+ client2.job.list_all
58
+ rescue Exception => e
59
+ e.class.should == JenkinsApi::Exceptions::UnautherizedException
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#job" do
65
+ it "Should return a job object on call" do
66
+ @client.job.class.should == JenkinsApi::Client::Job
67
+ end
68
+ end
69
+
70
+ describe "#node" do
71
+ it "Should return a node object on call" do
72
+ @client.node.class.should == JenkinsApi::Client::Node
73
+ end
74
+ end
75
+
76
+ describe "#view" do
77
+ it "Should return a view object on call" do
78
+ @client.view.class.should == JenkinsApi::Client::View
79
+ end
80
+ end
81
+
82
+ describe "#system" do
83
+ it "Should return a system object on call" do
84
+ @client.system.class.should == JenkinsApi::Client::System
85
+ end
86
+ end
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,348 @@
1
+ #
2
+ # Specifying JenkinsApi::Client::Job class capabilities
3
+ # Author: Kannan Manickam <arangamani.kannan@gmail.com>
4
+ #
5
+
6
+ require File.expand_path('../spec_helper', __FILE__)
7
+ require 'yaml'
8
+
9
+ describe JenkinsApi::Client::Job do
10
+ context "With properly initialized client" do
11
+ before(:all) do
12
+ @helper = JenkinsApiSpecHelper::Helper.new
13
+ @creds_file = '~/.jenkins_api_client/spec.yml'
14
+ @job_name_prefix = 'awesome_rspec_test_job'
15
+ @filter = "^#{@job_name_prefix}.*"
16
+ @job_name = ''
17
+ begin
18
+ @client = JenkinsApi::Client.new(
19
+ YAML.load_file(File.expand_path(@creds_file, __FILE__))
20
+ )
21
+ rescue Exception => e
22
+ puts "WARNING: Credentials are not set properly."
23
+ puts e.message
24
+ end
25
+ # Creating 10 jobs to run the spec tests on
26
+ begin
27
+ 10.times do |num|
28
+ xml = @helper.create_job_xml
29
+ job = "#{@job_name_prefix}_#{num}"
30
+ @job_name = job if num == 0
31
+ @client.job.create(job, xml).to_i.should == 200
32
+ end
33
+ rescue Exception => e
34
+ puts "WARNING: Can't create jobs for preparing to spec tests"
35
+ end
36
+ end
37
+
38
+ describe "InstanceMethods" do
39
+
40
+ describe "#initialize" do
41
+ it "Initializes without any exception" do
42
+ expect(
43
+ lambda { job = JenkinsApi::Client::Job.new(@client) }
44
+ ).not_to raise_error
45
+ end
46
+ it "Raises an error if a reference of client is not passed" do
47
+ expect(
48
+ lambda { job = JenkinsApi::Client::Job.new() }
49
+ ).to raise_error
50
+ end
51
+ end
52
+
53
+ describe "#create" do
54
+ it "Should be able to create a job by getting an xml" do
55
+ xml = @helper.create_job_xml
56
+ @client.job.create("qwerty_nonexistent_job", xml).to_i.should == 200
57
+ end
58
+ end
59
+
60
+ describe "#create_freestyle" do
61
+ it "Should be able to create a simple freestyle job" do
62
+ params = {
63
+ :name => "test_job_name_using_params"
64
+ }
65
+ @client.job.create_freestyle(params).to_i.should == 200
66
+ @client.job.delete("test_job_name_using_params").to_i.should == 302
67
+ end
68
+ it "Should be able to create a freestyle job with shell command" do
69
+ params = {
70
+ :name => "test_job_using_params_shell",
71
+ :shell_command => "echo this is a free style project"
72
+ }
73
+ @client.job.create_freestyle(params).to_i.should == 200
74
+ @client.job.delete("test_job_using_params_shell").to_i.should == 302
75
+ end
76
+ it "Should accept Git SCM provider" do
77
+ params = {
78
+ :name => "test_job_with_git_scm",
79
+ :scm_provider => "git",
80
+ :scm_url => "git://github.com./arangamani/jenkins_api_client.git",
81
+ :scm_branch => "master"
82
+ }
83
+ @client.job.create_freestyle(params).to_i.should == 200
84
+ @client.job.delete("test_job_with_git_scm").to_i.should == 302
85
+ end
86
+ it "Should accept subversion SCM provider" do
87
+ params = {
88
+ :name => "test_job_with_subversion_scm",
89
+ :scm_provider => "subversion",
90
+ :scm_url => "http://svn.freebsd.org/base/",
91
+ :scm_branch => "master"
92
+ }
93
+ @client.job.create_freestyle(params).to_i.should == 200
94
+ @client.job.delete("test_job_with_subversion_scm").to_i.should == 302
95
+ end
96
+ it "Should accept CVS SCM provider with branch" do
97
+ params = {
98
+ :name => "test_job_with_cvs_scm_branch",
99
+ :scm_provider => "cvs",
100
+ :scm_url => "http://cvs.NetBSD.org",
101
+ :scm_module => "src",
102
+ :scm_branch => "MAIN"
103
+ }
104
+ @client.job.create_freestyle(params).to_i.should == 200
105
+ @client.job.delete("test_job_with_cvs_scm_branch").to_i.should == 302
106
+ end
107
+ it "Should accept CVS SCM provider with tag" do
108
+ params = {
109
+ :name => "test_job_with_cvs_scm_tag",
110
+ :scm_provider => "cvs",
111
+ :scm_url => "http://cvs.NetBSD.org",
112
+ :scm_module => "src",
113
+ :scm_tag => "MAIN"
114
+ }
115
+ @client.job.create_freestyle(params).to_i.should == 200
116
+ @client.job.delete("test_job_with_cvs_scm_tag").to_i.should == 302
117
+ end
118
+ it "Should fail if unsupported SCM is specified" do
119
+ params = {
120
+ :name => "test_job_unsupported_scm",
121
+ :scm_provider => "non-existent",
122
+ :scm_url => "http://non-existent.com/non-existent.non",
123
+ :scm_branch => "master"
124
+ }
125
+ expect(
126
+ lambda{ @client.job.create_freestyle(params) }
127
+ ).to raise_error
128
+ end
129
+ it "Should accept restricted_node option" do
130
+ params = {
131
+ :name => "test_job_restricted_node",
132
+ :restricted_node => "master"
133
+ }
134
+ @client.job.create_freestyle(params).to_i.should == 200
135
+ @client.job.delete("test_job_restricted_node").to_i.should == 302
136
+ end
137
+ it "Should accept block_build_when_downstream_building option" do
138
+ params = {
139
+ :name => "test_job_block_build_when_downstream_building",
140
+ :block_build_when_downstream_building => true,
141
+ }
142
+ @client.job.create_freestyle(params).to_i.should == 200
143
+ @client.job.delete(
144
+ "test_job_block_build_when_downstream_building"
145
+ ).to_i.should == 302
146
+ end
147
+ it "Should accept block_build_when_upstream_building option" do
148
+ params = {
149
+ :name => "test_job_block_build_when_upstream_building",
150
+ :block_build_when_upstream_building => true
151
+ }
152
+ @client.job.create_freestyle(params).to_i.should == 200
153
+ @client.job.delete(
154
+ "test_job_block_build_when_upstream_building"
155
+ ).to_i.should == 302
156
+ end
157
+ it "Should accept concurrent_build option" do
158
+ params = {
159
+ :name => "test_job_concurrent_build",
160
+ :concurrent_build => true
161
+ }
162
+ @client.job.create_freestyle(params).to_i.should == 200
163
+ @client.job.delete("test_job_concurrent_build").to_i.should == 302
164
+ end
165
+ it "Should accept child projects option" do
166
+ params = {
167
+ :name => "test_job_child_projects",
168
+ :child_projects => @job_name,
169
+ :child_threshold => "success"
170
+ }
171
+ @client.job.create_freestyle(params).to_i.should == 200
172
+ @client.job.delete("test_job_child_projects").to_i.should == 302
173
+ end
174
+ it "Should accept notification_email option" do
175
+ params = {
176
+ :name => "test_job_notification_email",
177
+ :notification_email => "kannan@testdomain.com"
178
+ }
179
+ @client.job.create_freestyle(params).to_i.should == 200
180
+ @client.job.delete("test_job_notification_email").to_i.should == 302
181
+ end
182
+ end
183
+
184
+ describe "#recreate" do
185
+ it "Should be able to re-create a job" do
186
+ @client.job.recreate("qwerty_nonexistent_job").to_i.should == 200
187
+ end
188
+ end
189
+
190
+ describe "#change_description" do
191
+ it "Should be able to change the description of a job" do
192
+ @client.job.change_description("qwerty_nonexistent_job",
193
+ "The description has been changed by the spec test"
194
+ ).to_i.should == 200
195
+ end
196
+ end
197
+
198
+ describe "#delete" do
199
+ it "Should be able to delete a job" do
200
+ @client.job.delete("qwerty_nonexistent_job").to_i.should == 302
201
+ end
202
+ end
203
+
204
+ describe "#list_all" do
205
+ it "Should list all jobs" do
206
+ @client.job.list_all.class.should == Array
207
+ end
208
+ end
209
+
210
+ describe "#list" do
211
+ it "Should return job names based on the filter" do
212
+ names = @client.job.list(@filter)
213
+ names.class.should == Array
214
+ names.each { |name|
215
+ name.should match /#{@filter}/i
216
+ }
217
+ end
218
+ end
219
+
220
+ describe "#list_by_status" do
221
+ it "Should be able to list jobs by status" do
222
+ names = @client.job.list_by_status('success')
223
+ names.class.should == Array
224
+ names.each do |name|
225
+ status = @client.job.get_current_build_status(name)
226
+ status.should == 'success'
227
+ end
228
+ end
229
+ end
230
+
231
+ describe "#list_all_with_details" do
232
+ it "Should return all job names with details" do
233
+ @client.job.list_all_with_details.class.should == Array
234
+ end
235
+ end
236
+
237
+ describe "#list_details" do
238
+ it "Should list details of a particular job" do
239
+ job_name = @client.job.list(@filter)[0]
240
+ job_name.class.should == String
241
+ @client.job.list_details(job_name).class.should == Hash
242
+ end
243
+ end
244
+
245
+ describe "#get_upstream_projects" do
246
+ it "Should list upstream projects of the specified job" do
247
+ @client.job.get_upstream_projects(@job_name).class.should == Array
248
+ end
249
+ end
250
+
251
+ describe "#get_downstream_projects" do
252
+ it "Should list downstream projects of the specified job" do
253
+ @client.job.get_downstream_projects(@job_name).class.should == Array
254
+ end
255
+ end
256
+
257
+ describe "#get_builds" do
258
+ it "Should get builds of a specified job" do
259
+ @client.job.get_builds(@job_name).class.should == Array
260
+ end
261
+ end
262
+
263
+ describe "#get_current_build_status" do
264
+ it "Should obtain the current build status for the specified job" do
265
+ build_status = @client.job.get_current_build_status(@job_name)
266
+ build_status.class.should == String
267
+ valid_build_status = ["not_run",
268
+ "aborted",
269
+ "success",
270
+ "failure",
271
+ "unstable",
272
+ "running"]
273
+ valid_build_status.include?(build_status).should be_true
274
+ end
275
+ end
276
+
277
+ describe "#build" do
278
+ it "Should build the specified job" do
279
+ @client.job.get_current_build_status(
280
+ @job_name
281
+ ).should_not == "running"
282
+ response = @client.job.build(@job_name)
283
+ response.to_i.should == 302
284
+ # Sleep for 6 seconds so we don't hit the Jenkins quiet period (5
285
+ # seconds)
286
+ sleep 6
287
+ @client.job.get_current_build_status(@job_name).should == "running"
288
+ while @client.job.get_current_build_status(@job_name) == "running" do
289
+ # Waiting for this job to finish so it doesn't affect other tests
290
+ sleep 10
291
+ end
292
+ end
293
+ end
294
+
295
+ describe "#stop" do
296
+ it "Should be able to abort a recent build of a running job" do
297
+ @client.job.get_current_build_status(
298
+ @job_name
299
+ ).should_not == "running"
300
+ @client.job.build(@job_name)
301
+ sleep 6
302
+ @client.job.get_current_build_status(@job_name).should == "running"
303
+ sleep 5
304
+ @client.job.stop_build(@job_name).to_i.should == 302
305
+ sleep 5
306
+ @client.job.get_current_build_status(@job_name).should == "aborted"
307
+ end
308
+ end
309
+
310
+ describe "#restrict_to_node" do
311
+ it "Should be able to restrict a job to a node" do
312
+ @client.job.restrict_to_node(@job_name, 'master').to_i.should == 200
313
+ # Run it again to make sure that the replace existing node works
314
+ @client.job.restrict_to_node(@job_name, 'master').to_i.should == 200
315
+ end
316
+ end
317
+
318
+ describe "#chain" do
319
+ it "Should be able to chain all jobs" do
320
+ # Filter jobs to be chained
321
+ jobs = @client.job.list(@filter)
322
+ jobs.class.should == Array
323
+ start_jobs = @client.job.chain(jobs, 'success', ["all"])
324
+ start_jobs.class.should == Array
325
+ start_jobs.length.should == 1
326
+ end
327
+ it "Should be able to chain jobs based on the specified criteria" do
328
+ jobs = @client.job.list(@filter)
329
+ jobs.class.should == Array
330
+ start_jobs = @client.job.chain(jobs,
331
+ 'failure', ["not_run", "aborted", 'failure'], 3
332
+ )
333
+ start_jobs.class.should == Array
334
+ start_jobs.length.should == 3
335
+ end
336
+ end
337
+
338
+ end
339
+
340
+ after(:all) do
341
+ job_names = @client.job.list(@filter)
342
+ job_names.each { |job_name|
343
+ @client.job.delete(job_name)
344
+ }
345
+ end
346
+
347
+ end
348
+ end