jenkins_api_client 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -10,6 +10,13 @@ rvm:
10
10
  - ruby-head
11
11
  - jruby-head
12
12
  - 1.8.7
13
+ - ree
14
+ matrix:
15
+ allow_failures:
16
+ - rvm: jruby-18mode
17
+ - rvm: jruby-19mode
18
+ - rvm: jruby-head
19
+ - rvm: ree
13
20
  script: bundle exec rake unit_tests
14
21
  notifications:
15
22
  email: false
data/CHANGELOG.md CHANGED
@@ -4,10 +4,17 @@ CHANGELOG
4
4
  upcoming
5
5
  --------
6
6
 
7
+ v0.10.0 [24-APR-2013]
8
+ ----------------------
9
+ * new function to execute jenkins CLI `cli_exec`. Credit: @missedone
10
+ * Add ability to use http proxy. Credit: @woodbusy
11
+ * prompt the user for credentials when using irb login script. @woodbusy
12
+ * bugfix for job.console_output. Credit: @drnic
13
+ * add ssl support. Credit: @madisp
14
+
7
15
  v0.9.1 [01-APR-2013]
8
16
  ---------------------
9
- * Removed the dependency of ActiveSupport and Builder as they were not being
10
- * used.
17
+ * Removed the dependency of ActiveSupport and Builder as they were not being used.
11
18
 
12
19
  v0.9.0 [10-MAR-2013]
13
20
  ---------------------
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ gem "nokogiri"
4
4
  gem "thor", ">= 0.16.0"
5
5
  gem "json", ">= 0"
6
6
  gem "terminal-table", ">= 1.4.0"
7
+ gem "mixlib-shellout", "~> 1.1.0"
7
8
 
8
9
  group :development do
9
10
  gem "bundler", ">= 1.0"
data/README.md CHANGED
@@ -147,6 +147,21 @@ initial_jobs.each do |job|
147
147
  end
148
148
  ```
149
149
 
150
+ ### Running Jenkins CLI
151
+ To running [Jenkins CLI](https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+CLI)
152
+
153
+ ```ruby
154
+ @client = JenkinsApi::Client.new(:server_ip => '0.0.0.0',
155
+ :username => 'somename', :password => 'secret password')
156
+ # The following call will return the version of Jenkins instance
157
+ puts @client.exec_cli("version")
158
+ ```
159
+
160
+ Before you run the CLI, please make sure the following requirements are fulfilled:
161
+ * JRE/JDK 6 (or above) is installed, and 'java' is on the $PATH environment variable
162
+ * The ```jenkins_api_client/java_deps/jenkins-cli.jar``` is required as the client to run the CLI. You can retrieve the available commands via accessing the URL: ```http://<server>:<port>/cli```
163
+ * (Optional) required if you run the Groovy Script through CLI, make sure the *user* have the privilige to run script
164
+
150
165
  ### Using with command line
151
166
  Command line interface is supported only from version 0.2.0.
152
167
  See help using <tt>jenkinscli help</tt>
data/Rakefile CHANGED
@@ -40,3 +40,5 @@ RSpec::Core::RakeTask.new(:test) do |spec|
40
40
  spec.pattern = FileList['spec/*/*.rb']
41
41
  spec.rspec_opts = ['--color', '--format documentation']
42
42
  end
43
+
44
+ task :default => [:unit_tests]
Binary file
@@ -0,0 +1,100 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "jenkins_api_client"
8
+ s.version = "0.9.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Kannan Manickam"]
12
+ s.date = "2013-04-16"
13
+ s.description = "\nThis is a simple and easy-to-use Jenkins Api client with features focused on\nautomating Job configuration programaticaly and so forth"
14
+ s.email = ["arangamani.kannan@gmail.com"]
15
+ s.executables = ["jenkinscli"]
16
+ s.files = [
17
+ ".gitignore",
18
+ ".jenkins.yml",
19
+ ".travis.yml",
20
+ "CHANGELOG.md",
21
+ "Gemfile",
22
+ "LICENCE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "bin/jenkinscli",
26
+ "config/login.yml.example",
27
+ "java_deps/jenkins-cli.jar",
28
+ "lib/jenkins_api_client.rb",
29
+ "lib/jenkins_api_client/build_queue.rb",
30
+ "lib/jenkins_api_client/cli/base.rb",
31
+ "lib/jenkins_api_client/cli/helper.rb",
32
+ "lib/jenkins_api_client/cli/job.rb",
33
+ "lib/jenkins_api_client/cli/node.rb",
34
+ "lib/jenkins_api_client/cli/system.rb",
35
+ "lib/jenkins_api_client/client.rb",
36
+ "lib/jenkins_api_client/exceptions.rb",
37
+ "lib/jenkins_api_client/job.rb",
38
+ "lib/jenkins_api_client/node.rb",
39
+ "lib/jenkins_api_client/system.rb",
40
+ "lib/jenkins_api_client/version.rb",
41
+ "lib/jenkins_api_client/view.rb",
42
+ "scripts/login_with_irb.rb",
43
+ "spec/func_tests/client_spec.rb",
44
+ "spec/func_tests/job_spec.rb",
45
+ "spec/func_tests/node_spec.rb",
46
+ "spec/func_tests/spec_helper.rb",
47
+ "spec/func_tests/system_spec.rb",
48
+ "spec/func_tests/view_spec.rb",
49
+ "spec/unit_tests/build_queue_spec.rb",
50
+ "spec/unit_tests/client_spec.rb",
51
+ "spec/unit_tests/fixtures/files/computer_sample.xml",
52
+ "spec/unit_tests/fixtures/files/job_sample.xml",
53
+ "spec/unit_tests/job_spec.rb",
54
+ "spec/unit_tests/node_spec.rb",
55
+ "spec/unit_tests/spec_helper.rb",
56
+ "spec/unit_tests/system_spec.rb",
57
+ "spec/unit_tests/view_spec.rb"
58
+ ]
59
+ s.homepage = "https://github.com/arangamani/jenkins_api_client"
60
+ s.require_paths = ["lib"]
61
+ s.rubygems_version = "1.8.25"
62
+ s.summary = "Jenkins JSON API Client"
63
+
64
+ if s.respond_to? :specification_version then
65
+ s.specification_version = 3
66
+
67
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
68
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
69
+ s.add_runtime_dependency(%q<thor>, [">= 0.16.0"])
70
+ s.add_runtime_dependency(%q<json>, [">= 0"])
71
+ s.add_runtime_dependency(%q<terminal-table>, [">= 1.4.0"])
72
+ s.add_runtime_dependency(%q<mixlib-shellout>, ["~> 1.1.0"])
73
+ s.add_development_dependency(%q<bundler>, [">= 1.0"])
74
+ s.add_development_dependency(%q<jeweler>, [">= 1.6.4"])
75
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
76
+ s.add_development_dependency(%q<rspec>, [">= 0"])
77
+ else
78
+ s.add_dependency(%q<nokogiri>, [">= 0"])
79
+ s.add_dependency(%q<thor>, [">= 0.16.0"])
80
+ s.add_dependency(%q<json>, [">= 0"])
81
+ s.add_dependency(%q<terminal-table>, [">= 1.4.0"])
82
+ s.add_dependency(%q<mixlib-shellout>, ["~> 1.1.0"])
83
+ s.add_dependency(%q<bundler>, [">= 1.0"])
84
+ s.add_dependency(%q<jeweler>, [">= 1.6.4"])
85
+ s.add_dependency(%q<simplecov>, [">= 0"])
86
+ s.add_dependency(%q<rspec>, [">= 0"])
87
+ end
88
+ else
89
+ s.add_dependency(%q<nokogiri>, [">= 0"])
90
+ s.add_dependency(%q<thor>, [">= 0.16.0"])
91
+ s.add_dependency(%q<json>, [">= 0"])
92
+ s.add_dependency(%q<terminal-table>, [">= 1.4.0"])
93
+ s.add_dependency(%q<mixlib-shellout>, ["~> 1.1.0"])
94
+ s.add_dependency(%q<bundler>, [">= 1.0"])
95
+ s.add_dependency(%q<jeweler>, [">= 1.6.4"])
96
+ s.add_dependency(%q<simplecov>, [">= 0"])
97
+ s.add_dependency(%q<rspec>, [">= 0"])
98
+ end
99
+ end
100
+
@@ -22,6 +22,9 @@
22
22
 
23
23
  module JenkinsApi
24
24
  class Client
25
+ # This classes communicates with the Build Queue API exposed by Jenkins at
26
+ # "/queue" that gives information about jobs/tasks in the queue and their
27
+ # details.
25
28
  class BuildQueue
26
29
 
27
30
  # Initializes a new BuildQueue object.
@@ -27,8 +27,10 @@ require "#{File.dirname(__FILE__)}/job.rb"
27
27
  require "#{File.dirname(__FILE__)}/system.rb"
28
28
 
29
29
  module JenkinsApi
30
+ # This is the base module for all command line interface for Jenkins API.
30
31
  module CLI
31
-
32
+ # This is the base class for the command line interface which adds other
33
+ # classes as subcommands to the CLI.
32
34
  class Base < Thor
33
35
 
34
36
  class_option :username, :aliases => "-u", :desc => "Name of Jenkins user"
@@ -46,10 +48,12 @@ module JenkinsApi
46
48
  map "-v" => :version
47
49
 
48
50
  desc "version", "Shows current version"
51
+ # CLI command that returns the version of Jenkins API Client
49
52
  def version
50
53
  puts JenkinsApi::Client::VERSION
51
54
  end
52
55
 
56
+ # Register the CLI::Node class as "node" subcommand to CLI
53
57
  register(
54
58
  CLI::Node,
55
59
  'node',
@@ -57,6 +61,7 @@ module JenkinsApi
57
61
  'Provides functions to access the node interface of Jenkins CI server'
58
62
  )
59
63
 
64
+ # Register the CLI::Job class as "job" subcommand to CLI
60
65
  register(
61
66
  CLI::Job,
62
67
  'job',
@@ -64,6 +69,7 @@ module JenkinsApi
64
69
  'Provides functions to access the job interface of Jenkins CI server'
65
70
  )
66
71
 
72
+ # Register the CLI::System class as "system" subcommand to CLI
67
73
  register(
68
74
  CLI::System,
69
75
  'system',
@@ -24,7 +24,15 @@ require 'fileutils'
24
24
 
25
25
  module JenkinsApi
26
26
  module CLI
27
+ # This is the helper class that sets up the credentials from the command
28
+ # line parameters given and initializes the Jenkins API Client.
27
29
  class Helper
30
+ # Sets up the credentials and initializes the Jenkins API Client
31
+ #
32
+ # @param [Hash] options Options obtained from the command line
33
+ #
34
+ # @return [JenkinsApi::Client] A new Client object
35
+ #
28
36
  def self.setup(options)
29
37
  if options[:username] && options[:server_ip] && \
30
38
  (options[:password] || options[:password_base64])
@@ -25,7 +25,7 @@ require 'thor/group'
25
25
 
26
26
  module JenkinsApi
27
27
  module CLI
28
-
28
+ # This class provides various command line operations related to jobs.
29
29
  class Job < Thor
30
30
  include Thor::Actions
31
31
 
@@ -33,6 +33,8 @@ module JenkinsApi
33
33
  method_option :status, :aliases => "-t", :desc => "Status to filter"
34
34
  method_option :filter, :aliases => "-f",
35
35
  :desc => "Regular expression to filter jobs"
36
+ # CLI command to list all jobs in Jenkins or the ones matched by status
37
+ # or a regular expression
36
38
  def list
37
39
  @client = Helper.setup(parent_options)
38
40
  if options[:filter] && options[:status]
@@ -48,24 +50,37 @@ module JenkinsApi
48
50
  end
49
51
 
50
52
  desc "recreate JOB", "Recreate a specified job"
53
+ # CLI command to recreate a job on Jenkins
51
54
  def recreate(job)
52
55
  @client = Helper.setup(parent_options)
53
56
  @client.job.recreate(job)
54
57
  end
55
58
 
56
59
  desc "build JOB", "Build a job"
60
+ # CLI command to build a job given the name of the job
61
+ #
62
+ # @param [String] job Name of the job
63
+ #
57
64
  def build(job)
58
65
  @client = Helper.setup(parent_options)
59
66
  @client.job.build(job)
60
67
  end
61
68
 
62
69
  desc "status JOB", "Get the current build status of a job"
70
+ # CLI command to get the status of a job
71
+ #
72
+ # @param [String] job Name of the job
73
+ #
63
74
  def status(job)
64
75
  @client = Helper.setup(parent_options)
65
76
  puts @client.job.get_current_build_status(job)
66
77
  end
67
78
 
68
79
  desc "delete JOB", "Delete the job"
80
+ # CLI command to delete a job
81
+ #
82
+ # @param [String] job Name of the job
83
+ #
69
84
  def delete(job)
70
85
  @client = Helper.setup(parent_options)
71
86
  puts @client.job.delete(job)
@@ -74,6 +89,10 @@ module JenkinsApi
74
89
  desc "console JOB", "Print the progressive console output of a job"
75
90
  method_option :sleep, :aliases => "-z",
76
91
  :desc => "Time to wait between querying the API for console output"
92
+ # CLI command to obtain console output for a job
93
+ #
94
+ # @param [String] job Name of the job
95
+ #
77
96
  def console(job)
78
97
  @client = Helper.setup(parent_options)
79
98
  # If debug is enabled, disable it. It shouldn't interfere
@@ -101,6 +120,10 @@ module JenkinsApi
101
120
 
102
121
  desc "restrict JOB", "Restricts a job to a specific node"
103
122
  method_option :node, :aliases => "-n", :desc => "Node to be restricted to"
123
+ # CLI command to restrict a job to a node
124
+ #
125
+ # @param [String] job Name of the job
126
+ #
104
127
  def restrict(job)
105
128
  @client = Helper.setup(parent_options)
106
129
  if options[:node]
@@ -26,6 +26,7 @@ require 'terminal-table'
26
26
 
27
27
  module JenkinsApi
28
28
  module CLI
29
+ # This class provides various command line operations for the Node class.
29
30
  class Node < Thor
30
31
  include Thor::Actions
31
32
  include Terminal
@@ -33,6 +34,8 @@ module JenkinsApi
33
34
  desc "list", "List all nodes"
34
35
  method_option :filter, :aliases => "-f",
35
36
  :desc => "Regular expression to filter jobs"
37
+ # CLI command that lists all nodes/slaves available in Jenkins or the
38
+ # ones matching the filter provided
36
39
  def list
37
40
  @client = Helper.setup(parent_options)
38
41
  if options[:filter]
@@ -43,6 +46,7 @@ module JenkinsApi
43
46
  end
44
47
 
45
48
  desc "print_general_attributes", "Prints general attributes of nodes"
49
+ # CLI command that prints the general attribtues of nodes
46
50
  def print_general_attributes
47
51
  @client = Helper.setup(parent_options)
48
52
  general_attributes = Client::Node::GENERAL_ATTRIBUTES
@@ -55,6 +59,10 @@ module JenkinsApi
55
59
  end
56
60
 
57
61
  desc "print_node_attributes NODE", "Prints attributes specific to a node"
62
+ # CLI command to print the attributes specific to a node
63
+ #
64
+ # @param [String] node Name of the node
65
+ #
58
66
  def print_node_attributes(node)
59
67
  @client = Helper.setup(parent_options)
60
68
  node_attributes = Client::Node::NODE_ATTRIBUTES
@@ -68,6 +76,10 @@ module JenkinsApi
68
76
  end
69
77
 
70
78
  desc "print_node_properties NODE", "Prints properties of a node"
79
+ # CLI command to print the properties of a specific node
80
+ #
81
+ # @param [String] node Name of the node
82
+ #
71
83
  def print_node_properties(node)
72
84
  @client = Helper.setup(parent_options)
73
85
  node_properties = Client::Node::NODE_PROPERTIES
@@ -25,22 +25,26 @@ require 'thor/group'
25
25
 
26
26
  module JenkinsApi
27
27
  module CLI
28
+ # This class provides various command line operations to System class.
28
29
  class System < Thor
29
30
  include Thor::Actions
30
31
 
31
32
  desc "quietdown", "Puts the Jenkins server in Quiet down mode"
33
+ # CLI command that puts Jenkins in Quiet Down mode
32
34
  def quietdown
33
35
  @client = Helper.setup(parent_options)
34
36
  @client.system.quiet_down
35
37
  end
36
38
 
37
39
  desc "cancel_quietdown", "Cancels the Quiet down mode of Jenkins server"
40
+ # CLI command that cancels Jenkins from Quiet Down mode
38
41
  def cancel_quietdown
39
42
  @client = Helper.setup(parent_options)
40
43
  @client.system.cancel_quiet_down
41
44
  end
42
45
 
43
46
  desc "reload", "Reload Jenkins server"
47
+ # CLI command to reload Jenkins configuration from disk
44
48
  def reload
45
49
  @client = Helper.setup(parent_options)
46
50
  @client.system.reload
@@ -49,6 +53,7 @@ module JenkinsApi
49
53
  desc "restart", "Restarts the Jenkins server"
50
54
  method_option :force, :type => :boolean, :aliases => "-s",
51
55
  :desc => "Force restart"
56
+ # CLI command to (force) restart Jenkins
52
57
  def restart
53
58
  @client = Helper.setup(parent_options)
54
59
  force = options[:force] ? true : false
@@ -24,24 +24,34 @@ require 'rubygems'
24
24
  require 'json'
25
25
  require 'net/http'
26
26
  require 'nokogiri'
27
- #require 'active_support/core_ext'
28
- #require 'active_support/builder'
29
27
  require 'base64'
28
+ require "mixlib/shellout"
30
29
 
30
+ # The main module that contains the Client class and all subclasses that
31
+ # communicate with the Jenkins's Remote Access API.
31
32
  module JenkinsApi
33
+ # This is the client class that acts as the bridge between the subclasses and
34
+ # Jnekins. This class contains methods that performs GET and POST requests
35
+ # for various operations.
32
36
  class Client
33
37
  attr_accessor :debug, :timeout
38
+ # Default port to be used to connect to Jenkins
34
39
  DEFAULT_SERVER_PORT = 8080
40
+ # Default timeout in seconds to be used while performing operations
35
41
  DEFAULT_TIMEOUT = 120
42
+ # Parameters that are permitted as options while initializing the client
36
43
  VALID_PARAMS = [
37
44
  "server_ip",
38
45
  "server_port",
46
+ "proxy_ip",
47
+ "proxy_port",
39
48
  "jenkins_path",
40
49
  "username",
41
50
  "password",
42
51
  "password_base64",
43
52
  "debug",
44
- "timeout"
53
+ "timeout",
54
+ "ssl"
45
55
  ].freeze
46
56
 
47
57
  # Initialize a Client object with Jenkins CI server credentials
@@ -51,6 +61,12 @@ module JenkinsApi
51
61
  # * the +:server_port+ param is the port on which the Jenkins listens
52
62
  # * the +:username+ param is the username used for connecting to the server
53
63
  # * the +:password+ param is the password for connecting to the CI server
64
+ # * the +:ssl+ param indicates if Jenkins is accessible over HTTPS
65
+ # (defaults to false)
66
+ #
67
+ # @return [JenkinsApi::Client] a client object to Jenkins API
68
+ #
69
+ # @raise [ArgumentError] when required options are not provided.
54
70
  #
55
71
  def initialize(args)
56
72
  args.each do |key, value|
@@ -58,18 +74,25 @@ module JenkinsApi
58
74
  instance_variable_set("@#{key}", value)
59
75
  end
60
76
  end if args.is_a? Hash
61
- raise "Server IP is required to connect to Jenkins" unless @server_ip
62
- unless @username && (@password || @password_base64)
63
- raise "Credentials are required to connect to te Jenkins Server"
64
- end
65
- @server_port = DEFAULT_SERVER_PORT unless @server_port
66
- @timeout = DEFAULT_TIMEOUT unless @timeout
67
- @debug = false unless @debug
77
+ unless @server_ip
78
+ raise ArgumentError, "Server IP is required to connect to Jenkins"
79
+ end
80
+ unless @username && (@password || @password_base64)
81
+ raise ArgumentError, "Credentials are required to connect to Jenkins"
82
+ end
83
+ if @proxy_ip.nil? ^ @proxy_port.nil?
84
+ raise ArgumentError, "Proxy IP and port must both be specified or" +
85
+ " both left nil"
86
+ end
87
+ @server_port = DEFAULT_SERVER_PORT unless @server_port
88
+ @timeout = DEFAULT_TIMEOUT unless @timeout
89
+ @ssl ||= false
90
+ @debug = false unless @debug
68
91
 
69
- # Base64 decode inserts a newline character at the end. As a workaround
70
- # added chomp to remove newline characters. I hope nobody uses newline
71
- # characters at the end of their passwords :)
72
- @password = Base64.decode64(@password_base64).chomp if @password_base64
92
+ # Base64 decode inserts a newline character at the end. As a workaround
93
+ # added chomp to remove newline characters. I hope nobody uses newline
94
+ # characters at the end of their passwords :)
95
+ @password = Base64.decode64(@password_base64).chomp if @password_base64
73
96
  end
74
97
 
75
98
  # This method toggles the debug parameter in run time
@@ -80,56 +103,91 @@ module JenkinsApi
80
103
 
81
104
  # Creates an instance to the Job class by passing a reference to self
82
105
  #
106
+ # @return [JenkinsApi::Client::Job] An object to Job subclass
107
+ #
83
108
  def job
84
109
  JenkinsApi::Client::Job.new(self)
85
110
  end
86
111
 
87
112
  # Creates an instance to the System class by passing a reference to self
88
113
  #
114
+ # @return [JenkinsApi::Client::System] An object to System subclass
115
+ #
89
116
  def system
90
117
  JenkinsApi::Client::System.new(self)
91
118
  end
92
119
 
93
120
  # Creates an instance to the Node class by passing a reference to self
94
121
  #
122
+ # @return [JenkinsApi::Client::Node] An object to Node subclass
123
+ #
95
124
  def node
96
125
  JenkinsApi::Client::Node.new(self)
97
126
  end
98
127
 
99
128
  # Creates an instance to the View class by passing a reference to self
100
129
  #
130
+ # @return [JenkinsApi::Client::View] An object to View subclass
131
+ #
101
132
  def view
102
133
  JenkinsApi::Client::View.new(self)
103
134
  end
104
135
 
105
136
  # Creates an instance to the BuildQueue by passing a reference to self
106
137
  #
138
+ # @return [JenkinsApi::Client::BuildQueue] An object to BuildQueue subclass
139
+ #
107
140
  def queue
108
141
  JenkinsApi::Client::BuildQueue.new(self)
109
142
  end
110
143
 
111
144
  # Returns a string representing the class name
112
145
  #
146
+ # @return [String] string representation of class name
147
+ #
113
148
  def to_s
114
149
  "#<JenkinsApi::Client>"
115
150
  end
116
151
 
152
+ # Connects to the Jenkins server, sends the specified request and returns
153
+ # the response.
154
+ #
155
+ # @param [Net::HTTPRequest] request The request object to send
156
+ #
157
+ # @return [Net::HTTPResponse] Response from Jenkins
158
+ def make_http_request( request )
159
+ Net::HTTP.start(
160
+ @server_ip, @server_port, @proxy_ip, @proxy_port, :use_ssl => @ssl
161
+ ) do |http|
162
+ return http.request(request)
163
+ end
164
+ end
165
+ protected :make_http_request
166
+
117
167
  # Obtains the root of Jenkins server. This function is used to see if
118
168
  # Jenkins is running
169
+ #
170
+ # @return [Net::HTTP::Response] Response from Jenkins for "/"
171
+ #
119
172
  def get_root
120
- http = Net::HTTP.start(@server_ip, @server_port)
121
173
  request = Net::HTTP::Get.new("/")
122
174
  request.basic_auth @username, @password
123
- http.request(request)
175
+ make_http_request(request)
124
176
  end
125
177
 
126
178
  # Sends a GET request to the Jenkins CI server with the specified URL
127
179
  #
128
- # @param [String] url_prefix
180
+ # @param [String] url_prefix The prefix to use in the URL
181
+ # @param [String] tree A specific JSON tree to optimize the API call
182
+ # @param [String] url_suffix The suffix to be used in the URL
183
+ # @param [Boolean] raw_response Return complete Response object instead of
184
+ # JSON body of response
185
+ #
186
+ # @return [String, JSON] JSON response from Jenkins
129
187
  #
130
- def api_get_request(url_prefix, tree = nil, url_suffix ="/api/json")
188
+ def api_get_request(url_prefix, tree = nil, url_suffix ="/api/json",
189
+ raw_response = false)
131
190
  url_prefix = "#{@jenkins_path}#{url_prefix}"
132
- http = Net::HTTP.start(@server_ip, @server_port)
133
191
  to_get = ""
134
192
  if tree
135
193
  to_get = "#{url_prefix}#{url_suffix}?#{tree}"
@@ -140,55 +198,62 @@ module JenkinsApi
140
198
  request = Net::HTTP::Get.new(to_get)
141
199
  puts "[INFO] GET #{to_get}" if @debug
142
200
  request.basic_auth @username, @password
143
- response = http.request(request)
144
- handle_exception(response, "body", url_suffix =~ /json/)
201
+ response = make_http_request(request)
202
+ if raw_response
203
+ response
204
+ else
205
+ handle_exception(response, "body", url_suffix =~ /json/)
206
+ end
145
207
  end
146
208
 
147
209
  # Sends a POST message to the Jenkins CI server with the specified URL
148
210
  #
149
- # @param [String] url_prefix
150
- # @param [Hash] form_data form data to send with POST request
211
+ # @param [String] url_prefix The prefix to be used in the URL
212
+ # @param [Hash] form_data Form data to send with POST request
213
+ #
214
+ # @return [String] Response code form Jenkins Response
151
215
  #
152
216
  def api_post_request(url_prefix, form_data = nil)
153
217
  url_prefix = URI.escape("#{@jenkins_path}#{url_prefix}")
154
- http = Net::HTTP.start(@server_ip, @server_port)
155
218
  request = Net::HTTP::Post.new("#{url_prefix}")
156
219
  puts "[INFO] PUT #{url_prefix}" if @debug
157
220
  request.basic_auth @username, @password
158
221
  request.content_type = 'application/json'
159
222
  request.set_form_data(form_data) unless form_data.nil?
160
- response = http.request(request)
223
+ response = make_http_request(request)
161
224
  handle_exception(response)
162
225
  end
163
226
 
164
227
  # Obtains the configuration of a component from the Jenkins CI server
165
228
  #
166
- # @param [String] url_prefix
229
+ # @param [String] url_prefix The prefix to be used in the URL
230
+ #
231
+ # @return [String] XML configuration obtained from Jenkins
167
232
  #
168
233
  def get_config(url_prefix)
169
234
  url_prefix = URI.escape("#{@jenkins_path}#{url_prefix}")
170
- http = Net::HTTP.start(@server_ip, @server_port)
171
235
  request = Net::HTTP::Get.new("#{url_prefix}/config.xml")
172
236
  puts "[INFO] GET #{url_prefix}/config.xml" if @debug
173
237
  request.basic_auth @username, @password
174
- response = http.request(request)
238
+ response = make_http_request(request)
175
239
  handle_exception(response, "body")
176
240
  end
177
241
 
178
242
  # Posts the given xml configuration to the url given
179
243
  #
180
- # @param [String] url_prefix
181
- # @param [String] xml
244
+ # @param [String] url_prefix The prefix to be used in the URL
245
+ # @param [String] xml The XML configuration to be sent to Jenkins
246
+ #
247
+ # @return [String] Response code returned from Jenkins
182
248
  #
183
249
  def post_config(url_prefix, xml)
184
250
  url_prefix = URI.escape("#{@jenkins_path}#{url_prefix}")
185
- http = Net::HTTP.start(@server_ip, @server_port)
186
251
  request = Net::HTTP::Post.new("#{url_prefix}")
187
252
  puts "[INFO] PUT #{url_prefix}" if @debug
188
253
  request.basic_auth @username, @password
189
254
  request.body = xml
190
255
  request.content_type = 'application/xml'
191
- response = http.request(request)
256
+ response = make_http_request(request)
192
257
  handle_exception(response)
193
258
  end
194
259
 
@@ -219,8 +284,61 @@ module JenkinsApi
219
284
  response["Date"]
220
285
  end
221
286
 
287
+ # Execute the Jenkins CLI
288
+ #
289
+ # @param command [String] command name
290
+ # @param args [Array] the arguments for the command
291
+ #
292
+ # @return [String] command output from the CLI
293
+ #
294
+ # @raise [Exceptions::CLIException] if there are issues in running the
295
+ # commands using CLI
296
+ #
297
+ def exec_cli(command, args = [])
298
+ base_dir = File.dirname(__FILE__)
299
+ server_url = "http://#{@server_ip}:#{@server_port}/#{@jenkins_path}"
300
+ cmd = "java -jar #{base_dir}/../../java_deps/jenkins-cli.jar" +
301
+ " -s #{server_url} #{command}" +
302
+ " --username #{@username} --password #{@password} " +
303
+ args.join(' ')
304
+ java_cmd = Mixlib::ShellOut.new(cmd)
305
+
306
+ # Run the command
307
+ java_cmd.run_command
308
+ if java_cmd.stderr.empty?
309
+ java_cmd.stdout.chomp
310
+ else
311
+ # The stderr has a stack trace of the Java program. We'll already have
312
+ # a stack trace for Ruby. So just display a descriptive message for the
313
+ # error thrown by the CLI.
314
+ raise Exceptions::CLIException.new(java_cmd.stderr.split("\n").first)
315
+ end
316
+ end
317
+
222
318
  private
223
319
 
320
+ # Private method that handles the exception and raises with proper error
321
+ # message with the type of exception and returns the required values if no
322
+ # exceptions are raised.
323
+ #
324
+ # @param [Net::HTTP::Response] response Response from Jenkins
325
+ # @param [String] to_send What should be returned as a response. Allowed
326
+ # values: "code" and "body".
327
+ # @param [Boolean] send_json Boolean value used to determine whether to
328
+ # load the JSON or send the response as is.
329
+ #
330
+ # @return [String, JSON] Response returned whether loaded JSON or raw
331
+ # string
332
+ #
333
+ # @raise [Exceptions::UnauthorizedException] When invalid credentials are
334
+ # provided to connect to Jenkins
335
+ # @raise [Exceptions::NotFoundException] When the requested page on Jenkins
336
+ # is found
337
+ # @raise [Exceptions::InternelServerErrorException] When Jenkins returns a
338
+ # 500 Internel Server Error
339
+ # @raise [Exceptions::ApiException] Any other exception returned from
340
+ # Jenkins that are not categorized in the API Client.
341
+ #
224
342
  def handle_exception(response, to_send = "code", send_json = false)
225
343
  msg = "HTTP Code: #{response.code}, Response Body: #{response.body}"
226
344
  case response.code.to_i