artifactory 1.2.0 → 2.0.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Gemfile +1 -1
  4. data/lib/artifactory.rb +13 -9
  5. data/lib/artifactory/client.rb +16 -3
  6. data/lib/artifactory/errors.rb +1 -2
  7. data/lib/artifactory/resources/artifact.rb +56 -27
  8. data/lib/artifactory/resources/backup.rb +104 -0
  9. data/lib/artifactory/resources/base.rb +47 -0
  10. data/lib/artifactory/resources/layout.rb +1 -50
  11. data/lib/artifactory/resources/ldap_setting.rb +105 -0
  12. data/lib/artifactory/resources/mail_server.rb +61 -0
  13. data/lib/artifactory/resources/repository.rb +11 -14
  14. data/lib/artifactory/resources/url_base.rb +74 -0
  15. data/lib/artifactory/util.rb +41 -0
  16. data/lib/artifactory/version.rb +1 -1
  17. data/spec/integration/resources/backup.rb +22 -0
  18. data/spec/integration/resources/build_spec.rb +1 -3
  19. data/spec/integration/resources/group_spec.rb +2 -2
  20. data/spec/integration/resources/ldap_setting_spec.rb +22 -0
  21. data/spec/integration/resources/mail_server_spec.rb +22 -0
  22. data/spec/integration/resources/repository_spec.rb +1 -1
  23. data/spec/integration/resources/system_spec.rb +1 -1
  24. data/spec/integration/resources/url_base_spec.rb +22 -0
  25. data/spec/integration/resources/user_spec.rb +2 -2
  26. data/spec/spec_helper.rb +0 -1
  27. data/spec/support/api_server/system_endpoints.rb +44 -1
  28. data/spec/unit/artifactory_spec.rb +3 -3
  29. data/spec/unit/client_spec.rb +1 -1
  30. data/spec/unit/resources/artifact_spec.rb +18 -36
  31. data/spec/unit/resources/backup_spec.rb +61 -0
  32. data/spec/unit/resources/base_spec.rb +3 -3
  33. data/spec/unit/resources/build_spec.rb +3 -3
  34. data/spec/unit/resources/group_spec.rb +6 -6
  35. data/spec/unit/resources/layout_spec.rb +4 -4
  36. data/spec/unit/resources/ldap_setting_spec.rb +65 -0
  37. data/spec/unit/resources/mail_server_spec.rb +57 -0
  38. data/spec/unit/resources/plugin_spec.rb +2 -2
  39. data/spec/unit/resources/repository_spec.rb +19 -27
  40. data/spec/unit/resources/system_spec.rb +6 -6
  41. data/spec/unit/resources/url_base_spec.rb +53 -0
  42. data/spec/unit/resources/user_spec.rb +8 -8
  43. metadata +23 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f140751bb7b38da3e211b0c3fbd7332bb60754f3
4
- data.tar.gz: cf32023c6d7ade23e0237828d4a2f25f6c4ed8aa
3
+ metadata.gz: 096468dc3e965e5a8eccdbc3c0e70e56db2f3e13
4
+ data.tar.gz: a301449af639917f992d38e3ced4d7215d32612d
5
5
  SHA512:
6
- metadata.gz: bbc1d3688eee73f034dd8f39c62ad086555aea4345636f2654f428b5d1f89e4b92ee02fbc554187cb42057eaa6d02eb694a82f60afac33cd00987fc033406363
7
- data.tar.gz: 139a0c2ac153c5440dae9d6893b081ad7730139f621ce36c393af81cb89d0a116bd6ff85d9395dd2a43017baa0bf2fbc03c811bc01edf41894298ceab4203d4d
6
+ metadata.gz: f91a4477e6b82e3f2728de0ad4872269e77696e6dbc9195ec4900c27173021a0805ced4da035d8edda721e82ab81f09156616b15208d8d0df860b6fc80aee583
7
+ data.tar.gz: 4a3eaac28598ff0aee2936795f231b7e2549921131967f4448037ac36021ef595a98aba69ea4c2356b0027cdb9c1811dea7fa865815b77d81a7f671b9a7aa106
@@ -3,6 +3,21 @@ Artifactory Client CHANGELOG
3
3
  This file is used to document the changes between releases of the Artifactory
4
4
  Ruby client.
5
5
 
6
+ v2.0.0 (07-15-2014)
7
+ -------------------
8
+ **Breaking Changes**
9
+ - Change the airity of uploading an Artifact
10
+ - Automatically upload checksum files during Artifact upload
11
+
12
+ **Other Changes**
13
+ - Bump to RSpec 3
14
+ - Add support for configuring the Backup resource
15
+ - Add support for configuring the LDAPSetting resource
16
+ - Add support for configuring the MailServer resource
17
+ - Add support for configuring the URLBase resource
18
+ - Set `Transfer-Encoding` to "chunked"
19
+ - Do not swallow returned errors from the server
20
+
6
21
  v1.2.0 (2014-06-02)
7
22
  -------------------
8
23
  - Change the airty of Repository#find to align with other resources
data/Gemfile CHANGED
@@ -3,6 +3,6 @@ gemspec
3
3
 
4
4
  group :test do
5
5
  gem 'sinatra', '~> 1.4'
6
- gem 'rspec', '~> 2.14'
6
+ gem 'rspec', '~> 3.0'
7
7
  gem 'webmock', '~> 1.17'
8
8
  end
@@ -14,15 +14,19 @@ module Artifactory
14
14
  end
15
15
 
16
16
  module Resource
17
- autoload :Artifact, 'artifactory/resources/artifact'
18
- autoload :Base, 'artifactory/resources/base'
19
- autoload :Build, 'artifactory/resources/build'
20
- autoload :Group, 'artifactory/resources/group'
21
- autoload :Layout, 'artifactory/resources/layout'
22
- autoload :Plugin, 'artifactory/resources/plugin'
23
- autoload :Repository, 'artifactory/resources/repository'
24
- autoload :System, 'artifactory/resources/system'
25
- autoload :User, 'artifactory/resources/user'
17
+ autoload :Artifact, 'artifactory/resources/artifact'
18
+ autoload :Backup, 'artifactory/resources/backup'
19
+ autoload :Base, 'artifactory/resources/base'
20
+ autoload :Build, 'artifactory/resources/build'
21
+ autoload :Group, 'artifactory/resources/group'
22
+ autoload :Layout, 'artifactory/resources/layout'
23
+ autoload :LDAPSetting, 'artifactory/resources/ldap_setting'
24
+ autoload :MailServer, 'artifactory/resources/mail_server'
25
+ autoload :Plugin, 'artifactory/resources/plugin'
26
+ autoload :Repository, 'artifactory/resources/repository'
27
+ autoload :System, 'artifactory/resources/system'
28
+ autoload :URLBase, 'artifactory/resources/url_base'
29
+ autoload :User, 'artifactory/resources/user'
26
30
  end
27
31
 
28
32
  class << self
@@ -32,8 +32,12 @@ module Artifactory
32
32
  include Artifactory::Configurable
33
33
 
34
34
  proxy Resource::Artifact
35
+ proxy Resource::Backup
35
36
  proxy Resource::Layout
37
+ proxy Resource::LDAPSetting
38
+ proxy Resource::MailServer
36
39
  proxy Resource::Repository
40
+ proxy Resource::URLBase
37
41
  proxy Resource::User
38
42
  proxy Resource::System
39
43
 
@@ -176,6 +180,7 @@ module Artifactory
176
180
  # Setup PATCH/POST/PUT
177
181
  if [:patch, :post, :put].include?(verb)
178
182
  if data.respond_to?(:read)
183
+ request.add_field('Transfer-Encoding', 'chunked')
179
184
  request.body_stream = data
180
185
  elsif data.is_a?(Hash)
181
186
  request.form_data = data
@@ -337,9 +342,17 @@ module Artifactory
337
342
  # the response object from the request
338
343
  #
339
344
  def error(response)
340
- error = JSON.parse(response.body)['errors'].first
341
- raise Error::HTTPError.new(error)
342
- rescue JSON::ParserError
345
+ if (response.content_type || '').include?('json')
346
+ # Attempt to parse the error as JSON
347
+ begin
348
+ json = JSON.parse(response.body)
349
+
350
+ if json['errors'] && json['errors'].first
351
+ raise Error::HTTPError.new(json['errors'].first)
352
+ end
353
+ rescue JSON::ParserError; end
354
+ end
355
+
343
356
  raise Error::HTTPError.new(
344
357
  'status' => response.code,
345
358
  'message' => response.body,
@@ -6,13 +6,12 @@ module Artifactory
6
6
  # Class for all HTTP errors
7
7
  class HTTPError < ArtifactoryError
8
8
  attr_reader :code
9
- attr_reader :message
10
9
 
11
10
  def initialize(hash = {})
12
11
  @code = hash['status'].to_i
13
12
  @http = hash['message'].to_s
14
13
 
15
- super "The Artifactory server responded with an HTTP Error "\
14
+ super "The Artifactory server responded with an HTTP Error " \
16
15
  "#{@code}: `#{@http}'"
17
16
  end
18
17
  end
@@ -406,25 +406,20 @@ module Artifactory
406
406
  # @see bit.ly/1dhJRMO Artifactory Matrix Properties
407
407
  #
408
408
  # @example Upload an artifact from a File instance
409
- # file = File.new('/local/path/to/file.deb')
410
- # artifact = Artifact.new
411
- # artifact.upload(file, 'libs-release-local', file.deb')
412
- #
413
- # @example Upload an artifact from a path
414
- # artifact.upload('/local/path/to/file.deb', 'libs-release-local', 'file.deb')
409
+ # artifact = Artifact.new(local_path: '/local/path/to/file.deb')
410
+ # artifact.upload('libs-release-local', '/remote/path')
415
411
  #
416
412
  # @example Upload an artifact with matrix properties
417
- # artifact.upload('/local/path/to/file.deb', 'libs-release-local', file.deb', {
413
+ # artifact = Artifact.new(local_path: '/local/path/to/file.deb')
414
+ # artifact.upload('libs-release-local', '/remote/path', {
418
415
  # status: 'DEV',
419
416
  # rating: 5,
420
417
  # branch: 'master'
421
418
  # })
422
419
  #
423
- # @param [String] key
420
+ # @param [String] repo
424
421
  # the key of the repository to which to upload the file
425
- # @param [String, File] path_or_io
426
- # the file or path to the file to upload
427
- # @param [String] path
422
+ # @param [String] remote_path
428
423
  # the path where this resource will live in the remote artifactory
429
424
  # repository, relative to the repository key
430
425
  # @param [Hash] headers
@@ -434,20 +429,54 @@ module Artifactory
434
429
  #
435
430
  # @return [Resource::Artifact]
436
431
  #
437
- def upload(key, path_or_io, path, properties = {}, headers = {})
438
- file = if respond_to?(:read)
439
- path_or_io
440
- else
441
- File.new(File.expand_path(path_or_io))
442
- end
443
-
432
+ def upload(repo, remote_path, properties = {}, headers = {})
433
+ file = File.new(File.expand_path(local_path))
444
434
  matrix = to_matrix_properties(properties)
445
- endpoint = File.join("#{url_safe(key)}#{matrix}", path)
435
+ endpoint = File.join("#{url_safe(repo)}#{matrix}", remote_path)
446
436
 
447
437
  response = client.put(endpoint, file, headers)
438
+
439
+ # Upload checksums if they were given
440
+ upload_checksum(repo, remote_path, :md5, md5) if md5
441
+ upload_checksum(repo, remote_path, :sha1, sha1) if sha1
442
+
448
443
  self.class.from_hash(response)
449
444
  end
450
445
 
446
+ #
447
+ # Upload the checksum for this artifact. **The artifact must already be
448
+ # uploaded or Artifactory will throw an exception!**. This is both a public
449
+ # and private API. It is automatically called in {upload} if the SHA
450
+ # values are set. You may also call it manually.
451
+ #
452
+ # @example Set an artifact's md5
453
+ # artifact = Artifact.new(local_path: '/local/path/to/file.deb')
454
+ # artifact.upload_checksum('libs-release-local', '/remote/path', :md5, 'ABCD1234')
455
+ #
456
+ # @param (see Artifact#upload)
457
+ # @param [Symbol] type
458
+ # the type of checksum to write (+md5+ or +sha1+)
459
+ # @param [String] value
460
+ # the actual checksum
461
+ #
462
+ # @return [true]
463
+ #
464
+ def upload_checksum(repo, remote_path, type, value)
465
+ file = Tempfile.new("checksum.#{type}")
466
+ file.write(value)
467
+ file.rewind
468
+
469
+ endpoint = File.join(url_safe(repo), "#{remote_path}.#{type}")
470
+
471
+ client.put(endpoint, file)
472
+ true
473
+ ensure
474
+ if file
475
+ file.close
476
+ file.unlink
477
+ end
478
+ end
479
+
451
480
  #
452
481
  # Upload an artifact with the given SHA checksum. Consult the artifactory
453
482
  # documentation for the possible responses when the checksums fail to
@@ -456,15 +485,15 @@ module Artifactory
456
485
  # @see Artifact#upload More syntax examples
457
486
  #
458
487
  # @example Upload an artifact with a checksum
459
- # artifact = Artifact.new
460
- # artifact.upload_with_checksum('/local/file', 'libs-release-local', /remote/path', 'ABCD1234')
488
+ # artifact = Artifact.new(local_path: '/local/path/to/file.deb')
489
+ # artifact.upload_with_checksum('libs-release-local', /remote/path', 'ABCD1234')
461
490
  #
462
491
  # @param (see Artifact#upload)
463
492
  # @param [String] checksum
464
493
  # the SHA1 checksum of the artifact to upload
465
494
  #
466
- def upload_with_checksum(key, path_or_io, path, checksum, properties = {})
467
- upload(key, path_or_io, path, properties,
495
+ def upload_with_checksum(repo, remote_path, checksum, properties = {})
496
+ upload(repo, remote_path, properties,
468
497
  'X-Checksum-Deploy' => true,
469
498
  'X-Checksum-Sha1' => checksum,
470
499
  )
@@ -477,13 +506,13 @@ module Artifactory
477
506
  # @see Artifact#upload More syntax examples
478
507
  #
479
508
  # @example Upload an artifact with a checksum
480
- # artifact = Artifact.new('libs-release-local')
481
- # artifact.upload_from_archive('/local/archive', '/remote/path')#
509
+ # artifact = Artifact.new(local_path: '/local/path/to/file.deb')
510
+ # artifact.upload_from_archive('/remote/path')
482
511
  #
483
512
  # @param (see Repository#upload)
484
513
  #
485
- def upload_from_archive(key, path_or_io, path, properties = {})
486
- upload(key, path_or_io, path, properties,
514
+ def upload_from_archive(repo, remote_path, properties = {})
515
+ upload(repo, remote_path, properties,
487
516
  'X-Explode-Archive' => true,
488
517
  )
489
518
  end
@@ -0,0 +1,104 @@
1
+ require 'rexml/document'
2
+
3
+ module Artifactory
4
+ class Resource::Backup < Resource::Base
5
+ class << self
6
+ #
7
+ # Get a list of all backup jobs in the system.
8
+ #
9
+ # @param [Hash] options
10
+ # the list of options
11
+ #
12
+ # @option options [Artifactory::Client] :client
13
+ # the client object to make the request with
14
+ #
15
+ # @return [Array<Resource::Backup>]
16
+ # the list of backup jobs
17
+ #
18
+ def all(options = {})
19
+ config = Resource::System.configuration(options)
20
+ list_from_config('config/backups/backup', config, options)
21
+ end
22
+
23
+ #
24
+ # Find (fetch) a backup job by its key.
25
+ #
26
+ # @example Find a Backup by its key.
27
+ # backup.find('backup-daily') #=> #<Backup key: 'backup-daily' ...>
28
+ #
29
+ # @param [String] key
30
+ # the name of the backup job to find
31
+ # @param [Hash] options
32
+ # the list of options
33
+ #
34
+ # @option options [Artifactory::Client] :client
35
+ # the client object to make the request with
36
+ #
37
+ # @return [Resource::Backup, nil]
38
+ # an instance of the backup job that matches the given key, or +nil+
39
+ # if one does not exist
40
+ #
41
+ def find(key, options = {})
42
+ config = Resource::System.configuration(options)
43
+ find_from_config("config/backups/backup/key[text()='#{key}']", config, options)
44
+ rescue Error::HTTPError => e
45
+ raise unless e.code == 404
46
+ nil
47
+ end
48
+
49
+ private
50
+
51
+ #
52
+ # List all the child text elements in the Artifactory configuration file
53
+ # of a node matching the specified xpath
54
+ #
55
+ # @param [String] xpath
56
+ # xpath expression for the parent element whose children are to be listed
57
+ #
58
+ # @param [REXML] config
59
+ # Artifactory config as an REXML file
60
+ #
61
+ # @param [Hash] options
62
+ # the list of options
63
+ #
64
+ # @return [~Resource::Base]
65
+ #
66
+ def list_from_config(xpath, config, options = {})
67
+ REXML::XPath.match(config, xpath).map do |r|
68
+ hash = Util.xml_to_hash(r, 'excludedRepositories', false)
69
+ from_hash(hash, options)
70
+ end
71
+ end
72
+
73
+ #
74
+ # Find all the sibling text elements in the Artifactory configuration file
75
+ # of a node matching the specified xpath
76
+ #
77
+ # @param [String] xpath
78
+ # xpath expression for the element whose siblings are to be found
79
+ #
80
+ # @param [REXML] config
81
+ # Artifactory configuration file as an REXML doc
82
+ #
83
+ # @param [Hash] options
84
+ # the list of options
85
+ #
86
+ def find_from_config(xpath, config, options = {})
87
+ name_node = REXML::XPath.match(config, xpath)
88
+ return nil if name_node.empty?
89
+ properties = Util.xml_to_hash(name_node[0].parent, 'excludedRepositories', false)
90
+ from_hash(properties, options)
91
+ end
92
+ end
93
+
94
+ attribute :key, ->{ raise 'name missing!' }
95
+ attribute :enabled, true
96
+ attribute :dir
97
+ attribute :cron_exp
98
+ attribute :retention_period_hours
99
+ attribute :create_archive
100
+ attribute :excluded_repositories
101
+ attribute :send_mail_on_error
102
+ attribute :exclude_builds
103
+ end
104
+ end
@@ -91,6 +91,53 @@ module Artifactory
91
91
  from_hash(client.get(url), client: client)
92
92
  end
93
93
 
94
+ #
95
+ # List all the child text elements in the Artifactory configuration file
96
+ # of a node matching the specified xpath
97
+ #
98
+ # @param [String] xpath
99
+ # xpath expression for the parent element whose children are to be listed
100
+ #
101
+ # @param [REXML] config
102
+ # Artifactory config as an REXML file
103
+ #
104
+ # @param [Hash] options
105
+ # the list of options
106
+ #
107
+ def list_from_config(xpath, config, options = {})
108
+ REXML::XPath.match(config, xpath).map do |r|
109
+ hash = {}
110
+
111
+ r.each_element_with_text do |l|
112
+ hash[l.name] = l.get_text
113
+ end
114
+ from_hash(hash, options)
115
+ end
116
+ end
117
+
118
+ #
119
+ # Find the text elements matching a giving xpath
120
+ #
121
+ # @param [String] xpath
122
+ # xpath expression
123
+ #
124
+ # @param [REXML] config
125
+ # Artifactory configuration file as an REXML doc
126
+ #
127
+ # @param [Hash] options
128
+ # the list of options
129
+ #
130
+ def find_from_config(xpath, config, options = {})
131
+ name_node = REXML::XPath.match(config, xpath)
132
+ return nil if name_node.empty?
133
+ properties = {}
134
+ name_node[0].parent.each_element_with_text do |e|
135
+ properties[e.name] = Util.to_type(e.text)
136
+ end
137
+
138
+ from_hash(properties, options)
139
+ end
140
+
94
141
  #
95
142
  # Construct a new object from the hash.
96
143
  #
@@ -45,60 +45,11 @@ module Artifactory
45
45
  raise unless e.code == 404
46
46
  nil
47
47
  end
48
-
49
- private
50
- #
51
- # List all the child text elements in the Artifactory configuration file
52
- # of a node matching the specified xpath
53
- #
54
- # @param [String] xpath
55
- # xpath expression for the parent element whose children are to be listed
56
- #
57
- # @param [REXML] config
58
- # Artifactory config as an REXML file
59
- #
60
- # @param [Hash] options
61
- # the list of options
62
- #
63
- def list_from_config(xpath, config, options = {})
64
- REXML::XPath.match(config, xpath).map do |r|
65
- hash = {}
66
-
67
- r.each_element_with_text do |l|
68
- hash[l.name] = l.get_text
69
- end
70
- from_hash(hash, options)
71
- end
72
- end
73
-
74
- #
75
- # Find all the sibling text elements in the Artifactory configuration file
76
- # of a node matching the specified xpath
77
- #
78
- # @param [String] xpath
79
- # xpath expression for the element whose siblings are to be found
80
- #
81
- # @param [REXML] config
82
- # Artifactory configuration file as an REXML doc
83
- #
84
- # @param [Hash] options
85
- # the list of options
86
- #
87
- def find_from_config(xpath, config, options = {})
88
- name_node = REXML::XPath.match(config, xpath)
89
- return nil if name_node.empty?
90
- properties = {}
91
- name_node[0].parent.each_element_with_text do |e|
92
- properties[e.name] = e.text
93
- end
94
-
95
- from_hash(properties, options)
96
- end
97
48
  end
98
49
 
99
50
  attribute :name, ->{ raise 'Name missing!' }
100
51
  attribute :artifact_path_pattern
101
- attribute :distinctive_descriptor_path_pattern, 'true'
52
+ attribute :distinctive_descriptor_path_pattern, true
102
53
  attribute :descriptor_path_pattern
103
54
  attribute :folder_integration_revision_reg_exp
104
55
  attribute :file_integration_revision_reg_exp