nexus_cli_sb 4.0.2

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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +4 -0
  4. data/CHANGELOG.md +14 -0
  5. data/Gemfile +42 -0
  6. data/Guardfile +27 -0
  7. data/LICENSE +15 -0
  8. data/README.md +121 -0
  9. data/Rakefile +1 -0
  10. data/Thorfile +66 -0
  11. data/VERSION +1 -0
  12. data/bin/nexus-cli +10 -0
  13. data/data/pom.xml.erb +13 -0
  14. data/features/nexus_oss.feature +251 -0
  15. data/features/pro/nexus_custom_metadata.feature +116 -0
  16. data/features/pro/nexus_pro.feature +101 -0
  17. data/features/step_definitions/cli_steps.rb +105 -0
  18. data/features/support/env.rb +64 -0
  19. data/lib/nexus_cli/artifact.rb +44 -0
  20. data/lib/nexus_cli/base_remote.rb +16 -0
  21. data/lib/nexus_cli/cli.rb +7 -0
  22. data/lib/nexus_cli/configuration.rb +102 -0
  23. data/lib/nexus_cli/connection.rb +84 -0
  24. data/lib/nexus_cli/errors.rb +259 -0
  25. data/lib/nexus_cli/mixins/artifact_actions.rb +194 -0
  26. data/lib/nexus_cli/mixins/global_settings_actions.rb +64 -0
  27. data/lib/nexus_cli/mixins/logging_actions.rb +45 -0
  28. data/lib/nexus_cli/mixins/pro/custom_metadata_actions.rb +176 -0
  29. data/lib/nexus_cli/mixins/pro/smart_proxy_actions.rb +219 -0
  30. data/lib/nexus_cli/mixins/repository_actions.rb +245 -0
  31. data/lib/nexus_cli/mixins/user_actions.rb +125 -0
  32. data/lib/nexus_cli/n3_metadata.rb +77 -0
  33. data/lib/nexus_cli/remote/oss_remote.rb +11 -0
  34. data/lib/nexus_cli/remote/pro_remote.rb +59 -0
  35. data/lib/nexus_cli/remote_factory.rb +30 -0
  36. data/lib/nexus_cli/tasks.rb +496 -0
  37. data/lib/nexus_cli/version.rb +6 -0
  38. data/lib/nexus_cli.rb +44 -0
  39. data/nexus_cli.gemspec +31 -0
  40. data/spec/fixtures/metadata_search.xml +10 -0
  41. data/spec/fixtures/nexus.config +4 -0
  42. data/spec/spec_helper.rb +22 -0
  43. data/spec/unit/nexus_cli/artifact_spec.rb +82 -0
  44. data/spec/unit/nexus_cli/configuration_spec.rb +137 -0
  45. data/spec/unit/nexus_cli/mixins/pro/custom_metadata_actions_spec.rb +21 -0
  46. data/spec/unit/nexus_cli/oss_remote_spec.rb +78 -0
  47. data/spec/unit/nexus_cli/pro_remote_spec.rb +110 -0
  48. data/spec/unit/nexus_cli/remote_factory_spec.rb +42 -0
  49. metadata +259 -0
@@ -0,0 +1,125 @@
1
+ require 'json'
2
+ require 'jsonpath'
3
+
4
+ module NexusCli
5
+ # @author Kyle Allan <kallan@riotgames.com>
6
+ module UserActions
7
+
8
+
9
+ # Gets information about the current Nexus users.
10
+ #
11
+ # @return [String] a String of XML with data about Nexus users
12
+ def get_users
13
+ response = nexus.get(nexus_url("service/local/users"))
14
+ case response.status
15
+ when 200
16
+ return response.content
17
+ else
18
+ raise UnexpectedStatusCodeException.new(response.status)
19
+ end
20
+ end
21
+
22
+ # Creates a User.
23
+ #
24
+ # @param params [Hash] a Hash of parameters to use during user creation
25
+ #
26
+ # @return [Boolean] true if the user is created, false otherwise
27
+ def create_user(params)
28
+ response = nexus.post(nexus_url("service/local/users"), :body => create_user_json(params), :header => DEFAULT_CONTENT_TYPE_HEADER)
29
+ case response.status
30
+ when 201
31
+ return true
32
+ when 400
33
+ raise CreateUserException.new(response.content)
34
+ else
35
+ raise UnexpectedStatusCodeException.new(reponse.code)
36
+ end
37
+ end
38
+
39
+ # Updates a user by changing parts of that user's data.
40
+ #
41
+ # @param params [Hash] a Hash of parameters to update
42
+ #
43
+ # @return [Boolean] true if the user is updated, false otherwise
44
+ def update_user(params)
45
+ params[:roles] = [] if params[:roles] == [""]
46
+ user_json = get_user(params[:userId])
47
+
48
+ modified_json = JsonPath.for(user_json)
49
+ params.each do |key, value|
50
+ modified_json.gsub!("$..#{key}"){|v| value} unless key == "userId" || value.blank?
51
+ end
52
+
53
+ response = nexus.put(nexus_url("service/local/users/#{params[:userId]}"), :body => JSON.dump(modified_json.to_hash), :header => DEFAULT_CONTENT_TYPE_HEADER)
54
+ case response.status
55
+ when 200
56
+ return true
57
+ when 400
58
+ raise UpdateUserException.new(response.content)
59
+ else
60
+ raise UnexpectedStatusCodeException.new(response.status)
61
+ end
62
+ end
63
+
64
+ # Gets a user
65
+ #
66
+ # @param user [String] the name of the user to get
67
+ #
68
+ # @return [Hash] a parsed Ruby object representing the user's JSON
69
+ def get_user(user)
70
+ response = nexus.get(nexus_url("service/local/users/#{user}"), :header => DEFAULT_ACCEPT_HEADER)
71
+ case response.status
72
+ when 200
73
+ return JSON.parse(response.content)
74
+ when 404
75
+ raise UserNotFoundException.new(user)
76
+ else
77
+ raise UnexpectedStatusCodeException.new(response.status)
78
+ end
79
+ end
80
+
81
+ # Changes the password of a user
82
+ #
83
+ # @param params [Hash] a hash given to update the users password
84
+ #
85
+ # @return [type] [description]
86
+ def change_password(params)
87
+ response = nexus.post(nexus_url("service/local/users_changepw"), :body => create_change_password_json(params), :header => DEFAULT_CONTENT_TYPE_HEADER)
88
+ case response.status
89
+ when 202
90
+ return true
91
+ when 400
92
+ raise InvalidCredentialsException
93
+ else
94
+ raise UnexpectedStatusCodeException.new(response.status)
95
+ end
96
+ end
97
+
98
+ # Deletes the Nexus user with the given id.
99
+ #
100
+ # @param user_id [String] the Nexus user to delete
101
+ #
102
+ # @return [Boolean] true if the user is deleted, false otherwise
103
+ def delete_user(user_id)
104
+ response = nexus.delete(nexus_url("service/local/users/#{user_id}"))
105
+ case response.status
106
+ when 204
107
+ return true
108
+ when 404
109
+ raise UserNotFoundException.new(user_id)
110
+ else
111
+ raise UnexpectedStatusCodeException.new(response.status)
112
+ end
113
+ end
114
+
115
+ private
116
+
117
+ def create_user_json(params)
118
+ JSON.dump(:data => params)
119
+ end
120
+
121
+ def create_change_password_json(params)
122
+ JSON.dump(:data => params)
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,77 @@
1
+ require 'base64'
2
+
3
+ module NexusCli
4
+ module N3Metadata
5
+ class << self
6
+ # Checks if the custom metadata key is valid.
7
+ # Valid characters are alphanumeric with no special characeters.
8
+ def valid_n3_key?(element)
9
+ return !element.nil? && !element.match(/^[a-zA-Z0-9]+$/).nil? ? true : false
10
+ end
11
+
12
+ # Checks if the custom metadata value is valid.
13
+ # Valid characters are anything but quotes.
14
+ def valid_n3_value?(element)
15
+ return !element.nil? && !element.match(/^[^"'\\]*$/).nil? ? true : false
16
+ end
17
+
18
+ # Check if the custom metadata search type is valid.
19
+ def valid_n3_search_type?(element)
20
+ return !element.nil? && ["equal", "notequal", "matches", "bounded"].include?(element)
21
+ end
22
+
23
+ # Creates a custom metadata subject for HTTP requests.
24
+ def create_base64_subject(artifact)
25
+ return Base64.urlsafe_encode64("urn:maven/artifact##{artifact.group_id}:#{artifact.artifact_id}:#{artifact.version}::#{artifact.extension}")
26
+ end
27
+
28
+ # Parses the regular custom metadata xml into a simpler format containing only the custom metadata.
29
+ def convert_result_to_simple_xml(custom_metadata)
30
+ request = []
31
+ document = REXML::Document.new(custom_metadata)
32
+ REXML::XPath.each(document, "//customMetadataResponse/data/customMetadata[namespace=\"urn:nexus/user#\"]") do |row|
33
+ request.push(create_tag(row.elements["key"].text.strip, row.elements["value"].text.strip))
34
+ end
35
+ formatter = REXML::Formatters::Pretty.new(4)
36
+ formatter.compact = true
37
+ document = REXML::Document.new("<artifact-resolution><data>#{request.join}</data></artifact-resolution>")
38
+ out = ""
39
+ formatter.write(document, out)
40
+ out
41
+ end
42
+
43
+ # Parses the regular custom metadata xml into a hash containing only the custom metadata.
44
+ def convert_result_to_hash(custom_metadata)
45
+ request = {}
46
+ document = REXML::Document.new(custom_metadata)
47
+ REXML::XPath.each(document, "//customMetadataResponse/data/customMetadata[namespace=\"urn:nexus/user#\"]") do |row|
48
+ request[row.elements["key"].text.strip] = row.elements["value"].text.strip
49
+ end
50
+ request
51
+ end
52
+
53
+ # Create the request from the specified list of custom metadata key:value pairs
54
+ # @info If the target hash contains empty values for a key that exist in source, the metadata will be deleted
55
+ # @param [Hash] source The source hash of custom metadata key:value pairs
56
+ # @param [Hash] target The target hash to merge with the source hash (optional)
57
+ # @result [Hash] The resulting merge of the source and target hashes
58
+ def create_metadata_hash(source, target={})
59
+ request = []
60
+ source.merge(target).each do |key, value|
61
+ request.push({:namespace => "urn:nexus/user#", :key => key, :value => value, :readOnly => false}) unless value.empty?
62
+ end
63
+ return request
64
+ end
65
+
66
+ def missing_custom_metadata?(custom_metadata)
67
+ return !custom_metadata.match(/<data[ ]*\/>/).nil? ? true : false
68
+ end
69
+
70
+ private
71
+
72
+ def create_tag(tag, value)
73
+ "<#{tag}>#{value}</#{tag}>"
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,11 @@
1
+ module NexusCli
2
+ # @author Kyle Allan <kallan@riotgames.com>
3
+ class OSSRemote < BaseRemote
4
+
5
+ include ArtifactActions
6
+ include GlobalSettingsActions
7
+ include LoggingActions
8
+ include RepositoryActions
9
+ include UserActions
10
+ end
11
+ end
@@ -0,0 +1,59 @@
1
+ module NexusCli
2
+ class ProRemote < BaseRemote
3
+
4
+ include ArtifactActions
5
+ include CustomMetadataActions
6
+ include GlobalSettingsActions
7
+ include LoggingActions
8
+ include RepositoryActions
9
+ include SmartProxyActions
10
+ include UserActions
11
+
12
+ def get_license_info
13
+ response = nexus.get(nexus_url("service/local/licensing"), :header => DEFAULT_ACCEPT_HEADER)
14
+ case response.status
15
+ when 200
16
+ return response.content
17
+ else
18
+ raise UnexpectedStatusCodeException.new(response.status)
19
+ end
20
+ end
21
+
22
+ def install_license(license_file)
23
+ file = File.read(File.expand_path(license_file))
24
+ response = nexus.post(nexus_url("service/local/licensing/upload"), :body => file, :header => {"Content-Type" => "application/octet-stream"})
25
+ case response.status
26
+ when 201
27
+ return true
28
+ when 403
29
+ raise LicenseInstallFailure
30
+ else
31
+ raise UnexpectedStatusCodeException.new(response.status)
32
+ end
33
+ end
34
+
35
+ def install_license_bytes(bytes)
36
+ response = nexus.post(nexus_url("service/local/licensing/upload"), :body => bytes, :header => {"Content-Type" => "application/octet-stream"})
37
+ case response.status
38
+ when 201
39
+ return true
40
+ when 403
41
+ raise LicenseInstallFailure
42
+ else
43
+ raise UnexpectedStatusCodeException.new(response.status)
44
+ end
45
+ end
46
+
47
+ def transfer_artifact(artifact, from_repository, to_repository)
48
+ do_transfer_artifact(artifact, from_repository, to_repository)
49
+
50
+ configuration["repository"] = sanitize_for_id(from_repository)
51
+ from_artifact_metadata = get_custom_metadata_hash(artifact)
52
+
53
+ configuration["repository"] = sanitize_for_id(to_repository)
54
+ to_artifact_metadata = get_custom_metadata_hash(artifact)
55
+
56
+ do_update_custom_metadata(artifact, from_artifact_metadata, to_artifact_metadata)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,30 @@
1
+ require 'httpclient'
2
+ require 'yaml'
3
+
4
+ module NexusCli
5
+ class RemoteFactory
6
+ class << self
7
+ attr_reader :configuration
8
+ attr_reader :connection
9
+
10
+ # Creates a new Nexus Remote that can connect to and communicate with
11
+ # the Nexus server.
12
+ #
13
+ # @param [Hash] overrides
14
+ # @param [Boolean] ssl_verify
15
+ #
16
+ # @return [NexusCli::ProRemote, NexusCli::OSSRemote]
17
+ def create(overrides, ssl_verify=true)
18
+ @configuration = overrides ? Configuration.from_overrides(overrides) : Configuration.from_file
19
+ @connection = Connection.new(configuration, ssl_verify)
20
+ running_nexus_pro? ? ProRemote.new(overrides, ssl_verify) : OSSRemote.new(overrides, ssl_verify)
21
+ end
22
+
23
+ private
24
+
25
+ def running_nexus_pro?
26
+ return connection.status['edition_long'] == "Professional" ? true : false
27
+ end
28
+ end
29
+ end
30
+ end