artifactory_api 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +37 -0
- data/README.md +6 -0
- data/Rakefile +43 -0
- data/lib/artifactory_api.rb +8 -0
- data/lib/artifactory_api/artifacts.rb +35 -0
- data/lib/artifactory_api/builds.rb +57 -0
- data/lib/artifactory_api/client.rb +242 -0
- data/lib/artifactory_api/exceptions.rb +70 -0
- data/lib/artifactory_api/version.rb +14 -0
- data/spec/builds_spec.rb +81 -0
- data/spec/client_spec.rb +83 -0
- data/spec/spec_helper.rb +12 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 292f834fe01f7e90f6e0b8e2f0d67afab066f9fc
|
4
|
+
data.tar.gz: 492a47063e8101ad28a9218d234f198c1446dbb8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2ada15a767456c235450b4e2b1109e6cbbe2d2173d64361dd2f598b2f9d28c45d2d0407bc8c7376021c4d43361400f638dfb10e3b049e641faee16e84c344e88
|
7
|
+
data.tar.gz: 65e54220c99d42e288141a5ba3722a85e6875e2269efa9120bb3ce9ac95e991150c1c795e4fbc05a4a617ba4dd259f08c4e6ce7e5aaabcc412d9b207d9f9d7cf
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
PATH
|
2
|
+
remote: ../artifactory_api
|
3
|
+
specs:
|
4
|
+
artifactory_api (0.1.4)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
builder (3.2.2)
|
10
|
+
diff-lcs (1.2.5)
|
11
|
+
rake (10.1.1)
|
12
|
+
rspec (3.2.0)
|
13
|
+
rspec-core (~> 3.2.0)
|
14
|
+
rspec-expectations (~> 3.2.0)
|
15
|
+
rspec-mocks (~> 3.2.0)
|
16
|
+
rspec-core (3.2.0)
|
17
|
+
rspec-support (~> 3.2.0)
|
18
|
+
rspec-expectations (3.2.0)
|
19
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
20
|
+
rspec-support (~> 3.2.0)
|
21
|
+
rspec-mocks (3.2.0)
|
22
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
23
|
+
rspec-support (~> 3.2.0)
|
24
|
+
rspec-support (3.2.1)
|
25
|
+
rubygems-tasks (0.2.4)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
java
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
artifactory_api!
|
33
|
+
builder
|
34
|
+
bundler (~> 1.8.0)
|
35
|
+
rake (~> 10.1.0)
|
36
|
+
rspec
|
37
|
+
rubygems-tasks (~> 0.2)
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# encoding: utf-8
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'bundler'
|
9
|
+
rescue LoadError => e
|
10
|
+
warn e.message
|
11
|
+
warn "Run `gem install bundler` to install Bundler."
|
12
|
+
exit -1
|
13
|
+
end
|
14
|
+
|
15
|
+
begin
|
16
|
+
Bundler.setup(:development)
|
17
|
+
rescue Bundler::BundlerError => e
|
18
|
+
warn e.message
|
19
|
+
warn "Run `bundle install` to install missing gems."
|
20
|
+
exit e.status_code
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake'
|
24
|
+
|
25
|
+
require 'rubygems/tasks'
|
26
|
+
Gem::Tasks.new
|
27
|
+
|
28
|
+
# require 'cucumber/rake/task'
|
29
|
+
#
|
30
|
+
# Cucumber::Rake::Task.new do |t|
|
31
|
+
# t.cucumber_opts = %w[--format pretty]
|
32
|
+
# end
|
33
|
+
|
34
|
+
task :default => [:test]
|
35
|
+
task :spec => :test
|
36
|
+
|
37
|
+
require 'rspec/core'
|
38
|
+
require 'rspec/core/rake_task'
|
39
|
+
|
40
|
+
RSpec::Core::RakeTask.new(:test) do |spec|
|
41
|
+
spec.pattern = FileList['spec/**/*.rb']
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ArtifactoryApi
|
2
|
+
class Client
|
3
|
+
class Artifacts
|
4
|
+
def initialize(client)
|
5
|
+
@client = client
|
6
|
+
@logger = @client.logger
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
"#<ArtifactoryApi::Clients::Builds>"
|
11
|
+
end
|
12
|
+
|
13
|
+
def deploy_artifact repo, path, file
|
14
|
+
url = "/#{repo}#{path}"
|
15
|
+
@client.api_put_request url, file
|
16
|
+
end
|
17
|
+
|
18
|
+
def retrieve_artifact repo, path
|
19
|
+
url = "/#{repo}#{path}"
|
20
|
+
response = @client.api_get_request url, raw_response=true
|
21
|
+
response.body
|
22
|
+
end
|
23
|
+
|
24
|
+
def artifact_info repo, path
|
25
|
+
url = "/api/storage/#{repo}#{path}"
|
26
|
+
@client.api_get_request url
|
27
|
+
end
|
28
|
+
|
29
|
+
def copy_artifact from_repo, from_path, to_repo, to_path
|
30
|
+
url = "/api/copy/#{from_repo}#{from_path}?to=/#{to_repo}#{to_path}"
|
31
|
+
@client.api_post_request url
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
module ArtifactoryApi
|
3
|
+
class Client
|
4
|
+
class Builds
|
5
|
+
def initialize(client)
|
6
|
+
@client = client
|
7
|
+
@logger = @client.logger
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#<ArtifactoryApi::Client::Builds"
|
12
|
+
end
|
13
|
+
|
14
|
+
#Returns an array of hashes, containing a "name" key and a "last_built" key
|
15
|
+
#The api returns build names with a starting slash, this will remove them.
|
16
|
+
def list_all
|
17
|
+
response_json = @client.api_get_request("/api/build")
|
18
|
+
|
19
|
+
return nil unless response_json
|
20
|
+
|
21
|
+
response_json["builds"].map do |build|
|
22
|
+
{
|
23
|
+
:name => build["uri"].sub(/^\//,''),
|
24
|
+
:uri => build["uri"],
|
25
|
+
:lastStarted => build["lastStarted"]
|
26
|
+
}
|
27
|
+
end.sort{ |x,y| x[:name] <=> y[:name]}
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_runs_for_build build
|
32
|
+
response_json = @client.api_get_request("/api/build/#{build}")
|
33
|
+
return nil unless response_json
|
34
|
+
|
35
|
+
response_json["buildsNumbers"].map do |build|
|
36
|
+
{
|
37
|
+
:number => build["uri"].sub(/^\//,''),
|
38
|
+
:uri => build["uri"],
|
39
|
+
:started => build["started"]
|
40
|
+
}
|
41
|
+
end.sort{|x,y| x[:number].to_i <=> y[:number].to_i}
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_run_info build,run
|
45
|
+
response_json = @client.api_get_request("/api/build/#{build}/#{run}")
|
46
|
+
return nil unless response_json
|
47
|
+
result = response_json["buildInfo"]
|
48
|
+
result[:number] = result["number"]
|
49
|
+
result[:name] = result["name"]
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
def diffs_for_build_run build, to_run, from_run
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'base64'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'net/http'
|
6
|
+
require 'net/https'
|
7
|
+
|
8
|
+
module ArtifactoryApi
|
9
|
+
class Client
|
10
|
+
attr_accessor :logger
|
11
|
+
|
12
|
+
DEFAULT_SERVER_PORT = 80
|
13
|
+
|
14
|
+
VALID_PARAMS = [
|
15
|
+
"server_url",
|
16
|
+
"server_ip",
|
17
|
+
"server_port",
|
18
|
+
"artifactory_path",
|
19
|
+
"username",
|
20
|
+
"password",
|
21
|
+
"password_base64",
|
22
|
+
"log_location",
|
23
|
+
"log_level",
|
24
|
+
"ssl",
|
25
|
+
"follow_redirects"
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
def initialize(args)
|
29
|
+
args.each do |key, value|
|
30
|
+
if value && VALID_PARAMS.include?(key.to_s)
|
31
|
+
instance_variable_set("@#{key}", value)
|
32
|
+
end
|
33
|
+
end if args.is_a? Hash
|
34
|
+
|
35
|
+
# Server IP or Server URL must be specified
|
36
|
+
unless @server_ip || @server_url
|
37
|
+
raise ArgumentError, "Server IP or Server URL is required to connect" +
|
38
|
+
" to Artifactory"
|
39
|
+
end
|
40
|
+
|
41
|
+
# Username/password are optional as some artifactory servers do not require
|
42
|
+
# authentication
|
43
|
+
if @username && !(@password || @password_base64)
|
44
|
+
raise ArgumentError, "If username is provided, password is required"
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get info from the server_url, if we got one
|
48
|
+
if @server_url
|
49
|
+
server_uri = URI.parse(@server_url)
|
50
|
+
@server_ip = server_uri.host
|
51
|
+
@server_port = server_uri.port
|
52
|
+
@ssl = server_uri.scheme == "https"
|
53
|
+
@artifactory_path = server_uri.path
|
54
|
+
end
|
55
|
+
|
56
|
+
@artifactory_path ||= ""
|
57
|
+
@artifactory_path.gsub!(/\/$/, "") # remove trailing slash if there is one
|
58
|
+
|
59
|
+
@server_port = DEFAULT_SERVER_PORT unless @server_port
|
60
|
+
@ssl ||= false
|
61
|
+
|
62
|
+
# Setting log options
|
63
|
+
@log_location = STDOUT unless @log_location
|
64
|
+
@log_level = Logger::INFO unless @log_level
|
65
|
+
@logger = Logger.new(@log_location)
|
66
|
+
@logger.level = @log_level
|
67
|
+
|
68
|
+
# Base64 decode inserts a newline character at the end. As a workaround
|
69
|
+
# added chomp to remove newline characters. I hope nobody uses newline
|
70
|
+
# characters at the end of their passwords :)
|
71
|
+
@password = Base64.decode64(@password_base64).chomp if @password_base64
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
def builds
|
76
|
+
ArtifactoryApi::Client::Builds.new(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
def artifacts
|
80
|
+
ArtifactoryApi::Client::Artifacts.new(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns a string representing the class name
|
84
|
+
#
|
85
|
+
# @return [String] string representation of class name
|
86
|
+
#
|
87
|
+
def to_s
|
88
|
+
"#<ArtifactoryApi::Client>"
|
89
|
+
end
|
90
|
+
|
91
|
+
# Connects to the Artifactory server, sends the specified request and returns
|
92
|
+
# the response.
|
93
|
+
#
|
94
|
+
# @param [Net::HTTPRequest] request The request object to send
|
95
|
+
# @param [Boolean] follow_redirect whether to follow redirects or not
|
96
|
+
#
|
97
|
+
# @return [Net::HTTPResponse] Response from Jenkins
|
98
|
+
#
|
99
|
+
def make_http_request(request, follow_redirect = @follow_redirects)
|
100
|
+
request.basic_auth @username, @password if @username
|
101
|
+
|
102
|
+
http = Net::HTTP.new(@server_ip, @server_port)
|
103
|
+
|
104
|
+
if @ssl
|
105
|
+
http.use_ssl = true
|
106
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
107
|
+
end
|
108
|
+
|
109
|
+
response = http.request(request)
|
110
|
+
case response
|
111
|
+
when Net::HTTPRedirection then
|
112
|
+
# If we got a redirect request, follow it (if flag set), but don't
|
113
|
+
# go any deeper (only one redirect supported - don't want to follow
|
114
|
+
# our tail)
|
115
|
+
if follow_redirect
|
116
|
+
redir_uri = URI.parse(response['location'])
|
117
|
+
response = make_http_request(
|
118
|
+
Net::HTTP::Get.new(redir_uri.path, false)
|
119
|
+
)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
return response
|
123
|
+
end
|
124
|
+
|
125
|
+
protected :make_http_request
|
126
|
+
|
127
|
+
|
128
|
+
# Sends a GET request to the Artifactory server with the specified URL
|
129
|
+
#
|
130
|
+
# @param [String] url_prefix The prefix to use in the URL
|
131
|
+
# @param [Boolean] raw_response Return complete Response object instead of
|
132
|
+
# JSON body of response
|
133
|
+
#
|
134
|
+
# @return [String, JSON] JSON response from Jenkins
|
135
|
+
#
|
136
|
+
def api_get_request(url_prefix, raw_response = false)
|
137
|
+
url_prefix = "#{@artifactory_path}#{url_prefix}"
|
138
|
+
to_get = URI.escape(url_prefix)
|
139
|
+
request = Net::HTTP::Get.new(to_get)
|
140
|
+
@logger.info "GET #{to_get}"
|
141
|
+
exec_request(request, raw_response)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Sends a PUT request to the Artifactory server with the specified URL
|
145
|
+
def api_put_request(url_prefix, data, raw_response = false)
|
146
|
+
url_prefix = "#{@artifactory_path}#{url_prefix}"
|
147
|
+
to_put = URI.escape(url_prefix)
|
148
|
+
request = Net::HTTP::Put.new(to_put)
|
149
|
+
request.body = data
|
150
|
+
@logger.info "PUT #{to_put}"
|
151
|
+
exec_request(request, raw_response, data)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Sends a POST request to the Artifactory server with the specified URL
|
155
|
+
def api_post_request(url_prefix, raw_response = false, data=nil)
|
156
|
+
url_prefix = "#{@artifactory_path}#{url_prefix}"
|
157
|
+
to_post = URI.escape(url_prefix)
|
158
|
+
request = Net::HTTP::Post.new(to_post)
|
159
|
+
@logger.info "POST #{to_post}"
|
160
|
+
exec_request(request, raw_response, data)
|
161
|
+
end
|
162
|
+
|
163
|
+
#
|
164
|
+
# @param [Net::HTTP::Get Put or Post] request
|
165
|
+
# @param [Boolean] raw_response Return complete Response object instead of
|
166
|
+
# JSON body of response
|
167
|
+
# @param [String] data String to be sent as body of the request
|
168
|
+
|
169
|
+
# @return [String, JSON] Response returned whether loaded JSON or raw
|
170
|
+
def exec_request(request, raw_response=false, data=nil)
|
171
|
+
request.body = data if !data.nil?
|
172
|
+
response = make_http_request(request)
|
173
|
+
if raw_response
|
174
|
+
handle_exception(response, "raw")
|
175
|
+
else
|
176
|
+
handle_exception(response, "body", send_json=true)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
# Private method that handles the exception and raises with proper error
|
183
|
+
# message with the type of exception and returns the required values if no
|
184
|
+
# exceptions are raised.
|
185
|
+
#
|
186
|
+
# @param [Net::HTTP::Response] response Response from Artifactory
|
187
|
+
# @param [String] to_send What should be returned as a response. Allowed
|
188
|
+
# values: "code", "body", and "raw".
|
189
|
+
# @param [Boolean] send_json Boolean value used to determine whether to
|
190
|
+
# load the JSON or send the response as is.
|
191
|
+
#
|
192
|
+
# @return [String, JSON] Response returned whether loaded JSON or raw
|
193
|
+
# string
|
194
|
+
#
|
195
|
+
# @raise [Exceptions::Unauthorized] When invalid credentials are
|
196
|
+
# provided to connect to Artifactory
|
197
|
+
# @raise [Exceptions::NotFound] When the requested page on Artifactory is not
|
198
|
+
# found
|
199
|
+
# @raise [Exceptions::InternalServerError] When Artifactory returns a 500
|
200
|
+
# Internal Server Error
|
201
|
+
# @raise [Exceptions::ApiException] Any other exception returned from
|
202
|
+
# Artifactory that are not categorized in the API Client.
|
203
|
+
#
|
204
|
+
def handle_exception(response, to_send = "code", send_json = false)
|
205
|
+
msg = "ArtifactoryAPI HTTP Code: #{response.code}, Response Body: #{response.body}"
|
206
|
+
@logger.debug msg
|
207
|
+
case response.code.to_i
|
208
|
+
when 200, 201, 302
|
209
|
+
if to_send == "body" && send_json
|
210
|
+
return JSON.parse(response.body)
|
211
|
+
elsif to_send == "body"
|
212
|
+
return response.body
|
213
|
+
elsif to_send == "code"
|
214
|
+
return response.code
|
215
|
+
elsif to_send == "raw"
|
216
|
+
return response
|
217
|
+
end
|
218
|
+
when 400
|
219
|
+
matched = response.body.match(/<p>(.*)<br\s*\/>/)
|
220
|
+
api_message = matched[1] unless matched.nil?
|
221
|
+
@logger.info "API message: #{api_message}"
|
222
|
+
raise Exceptions::ApiException.new(api_message)
|
223
|
+
when 401
|
224
|
+
raise Exceptions::Unauthorized.new
|
225
|
+
when 403
|
226
|
+
raise Exceptions::Forbidden.new
|
227
|
+
when 404
|
228
|
+
raise Exceptions::NotFound.new
|
229
|
+
when 500
|
230
|
+
raise Exceptions::InternalServerError.new
|
231
|
+
when 503
|
232
|
+
raise Exceptions::ServiceUnavailable.new
|
233
|
+
else
|
234
|
+
raise Exceptions::ApiException.new(
|
235
|
+
"Error code #{response.code}"
|
236
|
+
)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module ArtifactoryApi
|
6
|
+
# This module contains classes that define exceptions for various catories.
|
7
|
+
#
|
8
|
+
module Exceptions
|
9
|
+
# This is the base class for Exceptions that is inherited from
|
10
|
+
# RuntimeError.
|
11
|
+
#
|
12
|
+
class ApiException < RuntimeError
|
13
|
+
def initialize( message = "")
|
14
|
+
super(message)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# This exception class handles cases where invalid credentials are provided
|
19
|
+
# to connect to Artifactory.
|
20
|
+
#
|
21
|
+
class Unauthorized < ApiException
|
22
|
+
def initialize( message = "")
|
23
|
+
msg = "Invalid credentials are provided. #{message}"
|
24
|
+
super(msg)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# This exception class handles cases where invalid credentials are provided
|
29
|
+
# to connect to Artifactory.
|
30
|
+
#
|
31
|
+
class Forbidden < ApiException
|
32
|
+
def initialize( message = "")
|
33
|
+
msg = "Forbiddent exception #{message}"
|
34
|
+
super(msg)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# This exception class handles cases where a requested page is not found on
|
39
|
+
# the Artifactory API.
|
40
|
+
#
|
41
|
+
class NotFound < ApiException
|
42
|
+
def initialize( message = "")
|
43
|
+
msg = "Requested component is not found on Artifactory" \
|
44
|
+
if message.empty?
|
45
|
+
super(msg)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# This exception class handles cases where the Artifactory API returns with a
|
50
|
+
# 500 Internel Server Error.
|
51
|
+
#
|
52
|
+
class InternalServerError < ApiException
|
53
|
+
def initialize( message = "")
|
54
|
+
msg = "Internel Server Error. #{message}"
|
55
|
+
super(msg)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# This exception class handles cases where Artifactory is getting restarted
|
60
|
+
# or reloaded where the response code returned is 503
|
61
|
+
#
|
62
|
+
class ServiceUnavailable < ApiException
|
63
|
+
def initialize( message = "")
|
64
|
+
msg = "Artifactory is unavailable #{message}"
|
65
|
+
super(msg)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ArtifactoryApi
|
2
|
+
class Client
|
3
|
+
# Major version of the gem
|
4
|
+
MAJOR = 0
|
5
|
+
# Minor version of the gem
|
6
|
+
MINOR = 1
|
7
|
+
# Tiny version of the gem used for patches
|
8
|
+
TINY = 4
|
9
|
+
# Used for pre-releases
|
10
|
+
PRE = 'pre2'
|
11
|
+
# Version String of Jenkins API Client.
|
12
|
+
VERSION = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
13
|
+
end
|
14
|
+
end
|
data/spec/builds_spec.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe ArtifactoryApi::Client::Builds do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
#Setup mocks
|
7
|
+
logger = Logger.new("test_log.log")
|
8
|
+
@client = double("client")
|
9
|
+
@client.stub(:logger) {logger}
|
10
|
+
@builds = ArtifactoryApi::Client::Builds.new(@client)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should call the all builds endpoint" do
|
14
|
+
#@client.should_receive(:api_get_request) {"/api/builds"}
|
15
|
+
@client.should_receive(:api_get_request).with("/api/build").and_return(nil)
|
16
|
+
builds = ArtifactoryApi::Client::Builds.new(@client)
|
17
|
+
builds.list_all
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the builds map" do
|
21
|
+
the_response = { "builds" => [{"uri" => "/Build1",
|
22
|
+
"lastStarted" => "2013-06-03T13:41:18.147+0000"}],
|
23
|
+
"uri" => "http://artifactory/api/build"}
|
24
|
+
|
25
|
+
@client.should_receive(:api_get_request).with("/api/build").and_return(the_response)
|
26
|
+
|
27
|
+
build_list = @builds.list_all
|
28
|
+
expect(build_list.length).to eq(1)
|
29
|
+
expect(build_list[0][:lastStarted]).to eq("2013-06-03T13:41:18.147+0000")
|
30
|
+
expect(build_list[0][:name]).to eq("Build1")
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should return all runs given a build" do
|
35
|
+
the_response = {"buildsNumbers" => [{"uri" => "/149","started" => "2013-03-14T16:07:43.636+0000"}],
|
36
|
+
"uri" => "https://artifactory-1.ampaxs.net/api/build/Server"}
|
37
|
+
@client.should_receive(:api_get_request).with("/api/build/MyBuild").and_return(the_response)
|
38
|
+
|
39
|
+
runs = @builds.get_runs_for_build "MyBuild"
|
40
|
+
|
41
|
+
expect(runs.length).to eq(1)
|
42
|
+
expect(runs[0][:number]).to eq("149")
|
43
|
+
expect(runs[0][:started]).to eq("2013-03-14T16:07:43.636+0000")
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should sort runs by the run number" do
|
48
|
+
the_response = {"buildsNumbers" => [
|
49
|
+
{"uri" => "/149","started" => "2013-03-14T16:07:43.636+0000"},
|
50
|
+
{"uri" => "/2464","started" => "2013-03-14T16:07:43.636+0000"},
|
51
|
+
{"uri" => "/379","started" => "2013-06-10T19:38:05.857+0000"},
|
52
|
+
{"uri" => "/222","started" => "2013-04-25T19:39:26.464+0000"}],
|
53
|
+
"uri" => "https://artifactory-1.ampaxs.net/api/build/Server"}
|
54
|
+
|
55
|
+
@client.should_receive(:api_get_request).with("/api/build/MyBuild").and_return(the_response)
|
56
|
+
|
57
|
+
runs = @builds.get_runs_for_build "MyBuild"
|
58
|
+
|
59
|
+
expect(runs.length).to eq(4)
|
60
|
+
expect(runs[0][:number]).to eq("149")
|
61
|
+
expect(runs[1][:number]).to eq("222")
|
62
|
+
expect(runs[2][:number]).to eq("379")
|
63
|
+
expect(runs[3][:number]).to eq("2464")
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
it "should return info for a run, given a build and run" do
|
69
|
+
|
70
|
+
the_response = {"buildInfo" => {"version" => "1.0.1", "name" => "MyBuild", "number" => "430"},
|
71
|
+
"uri" => "https://artifactory-1.ampaxs.net/api/build/Server/430"}
|
72
|
+
|
73
|
+
@client.should_receive(:api_get_request).with("/api/build/MyBuild/430").and_return(the_response)
|
74
|
+
|
75
|
+
run_info = @builds.get_run_info "MyBuild","430"
|
76
|
+
|
77
|
+
expect(run_info[:number]).to eq("430")
|
78
|
+
expect(run_info[:name]).to eq("MyBuild")
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require_relative "spec_helper"
|
2
|
+
|
3
|
+
describe ArtifactoryApi::Client do
|
4
|
+
|
5
|
+
describe "initialization" do
|
6
|
+
it "should initialize when server ip, port, and user/password is provided" do
|
7
|
+
expect(
|
8
|
+
lambda do
|
9
|
+
ArtifactoryApi::Client.new(
|
10
|
+
:server_ip => '127.0.0.1',
|
11
|
+
:server_port => 8080,
|
12
|
+
:username => 'username',
|
13
|
+
:password => 'password'
|
14
|
+
)
|
15
|
+
end
|
16
|
+
).not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should initialize when username/password not specified" do
|
20
|
+
expect(
|
21
|
+
lambda do
|
22
|
+
ArtifactoryApi::Client.new(
|
23
|
+
:server_ip => '127.0.0.1',
|
24
|
+
:server_port => 8080
|
25
|
+
)
|
26
|
+
end
|
27
|
+
).not_to raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should initializes with server_url" do
|
31
|
+
expect(
|
32
|
+
lambda do
|
33
|
+
ArtifactoryApi::Client.new(
|
34
|
+
:server_url => 'http://localhost',
|
35
|
+
:username => 'username',
|
36
|
+
:password => 'password'
|
37
|
+
)
|
38
|
+
end
|
39
|
+
).not_to raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should fail to initialize when a username is provided but not a password" do
|
43
|
+
expect(
|
44
|
+
lambda do
|
45
|
+
ArtifactoryApi::Client.new(
|
46
|
+
:server_url => 'http://localhost',
|
47
|
+
:username => 'user_id'
|
48
|
+
)
|
49
|
+
end
|
50
|
+
).to raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should fail to initialize when you don't provide any server data" do
|
54
|
+
expect(
|
55
|
+
lambda do
|
56
|
+
ArtifactoryApi::Client.new(
|
57
|
+
:username => "user", :password => "password")
|
58
|
+
end
|
59
|
+
).to raise_error
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "With valid credentials given" do
|
64
|
+
before do
|
65
|
+
@client = ArtifactoryApi::Client.new(
|
66
|
+
:server_ip => '127.0.0.1',
|
67
|
+
:server_port => 8080,
|
68
|
+
:username => 'username',
|
69
|
+
:password => 'password',
|
70
|
+
:log_location => '/dev/null'
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should return a Build object when you ask for it" do
|
75
|
+
expect(@client.builds.class).to eq(ArtifactoryApi::Client::Builds)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "should return a Artifacts object when you ask for it" do
|
79
|
+
expect(@client.artifacts.class).to eq(ArtifactoryApi::Client::Artifacts)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path('../../lib/artifactory_api', __FILE__)
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.mock_with :rspec
|
6
|
+
config.color_enabled = true
|
7
|
+
config.order = :random
|
8
|
+
config.expect_with :rspec do |expectations|
|
9
|
+
expectations.syntax = :expect
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: artifactory_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rick Carragher
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
version_requirements: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
requirement: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '1.0'
|
25
|
+
prerelease: false
|
26
|
+
type: :development
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10'
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ~>
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '10'
|
39
|
+
prerelease: false
|
40
|
+
type: :development
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubygems-tasks
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.2'
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ~>
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0.2'
|
53
|
+
prerelease: false
|
54
|
+
type: :development
|
55
|
+
description: A client to the artifactory rest api
|
56
|
+
email: rcarragher@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- Gemfile
|
62
|
+
- Gemfile.lock
|
63
|
+
- README.md
|
64
|
+
- Rakefile
|
65
|
+
- lib/artifactory_api.rb
|
66
|
+
- lib/artifactory_api/artifacts.rb
|
67
|
+
- lib/artifactory_api/builds.rb
|
68
|
+
- lib/artifactory_api/client.rb
|
69
|
+
- lib/artifactory_api/exceptions.rb
|
70
|
+
- lib/artifactory_api/version.rb
|
71
|
+
- spec/builds_spec.rb
|
72
|
+
- spec/client_spec.rb
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
homepage: http://rubygems.org/gems/artifactory_api
|
75
|
+
licenses:
|
76
|
+
- Apachev2
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.4.5
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: artfifactory_api consumes the artifactory rest api to do useful stuff
|
98
|
+
test_files:
|
99
|
+
- spec/builds_spec.rb
|
100
|
+
- spec/client_spec.rb
|
101
|
+
- spec/spec_helper.rb
|