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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +42 -0
- data/Guardfile +27 -0
- data/LICENSE +15 -0
- data/README.md +121 -0
- data/Rakefile +1 -0
- data/Thorfile +66 -0
- data/VERSION +1 -0
- data/bin/nexus-cli +10 -0
- data/data/pom.xml.erb +13 -0
- data/features/nexus_oss.feature +251 -0
- data/features/pro/nexus_custom_metadata.feature +116 -0
- data/features/pro/nexus_pro.feature +101 -0
- data/features/step_definitions/cli_steps.rb +105 -0
- data/features/support/env.rb +64 -0
- data/lib/nexus_cli/artifact.rb +44 -0
- data/lib/nexus_cli/base_remote.rb +16 -0
- data/lib/nexus_cli/cli.rb +7 -0
- data/lib/nexus_cli/configuration.rb +102 -0
- data/lib/nexus_cli/connection.rb +84 -0
- data/lib/nexus_cli/errors.rb +259 -0
- data/lib/nexus_cli/mixins/artifact_actions.rb +194 -0
- data/lib/nexus_cli/mixins/global_settings_actions.rb +64 -0
- data/lib/nexus_cli/mixins/logging_actions.rb +45 -0
- data/lib/nexus_cli/mixins/pro/custom_metadata_actions.rb +176 -0
- data/lib/nexus_cli/mixins/pro/smart_proxy_actions.rb +219 -0
- data/lib/nexus_cli/mixins/repository_actions.rb +245 -0
- data/lib/nexus_cli/mixins/user_actions.rb +125 -0
- data/lib/nexus_cli/n3_metadata.rb +77 -0
- data/lib/nexus_cli/remote/oss_remote.rb +11 -0
- data/lib/nexus_cli/remote/pro_remote.rb +59 -0
- data/lib/nexus_cli/remote_factory.rb +30 -0
- data/lib/nexus_cli/tasks.rb +496 -0
- data/lib/nexus_cli/version.rb +6 -0
- data/lib/nexus_cli.rb +44 -0
- data/nexus_cli.gemspec +31 -0
- data/spec/fixtures/metadata_search.xml +10 -0
- data/spec/fixtures/nexus.config +4 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/unit/nexus_cli/artifact_spec.rb +82 -0
- data/spec/unit/nexus_cli/configuration_spec.rb +137 -0
- data/spec/unit/nexus_cli/mixins/pro/custom_metadata_actions_spec.rb +21 -0
- data/spec/unit/nexus_cli/oss_remote_spec.rb +78 -0
- data/spec/unit/nexus_cli/pro_remote_spec.rb +110 -0
- data/spec/unit/nexus_cli/remote_factory_spec.rb +42 -0
- 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,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
|