jenkins_api_client 0.9.1 → 0.10.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/.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