nexus_cli 0.7.3 → 0.8.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/VERSION +1 -1
- data/bin/nexus-cli +0 -4
- data/features/nexus_oss.feature +26 -0
- data/lib/nexus_cli.rb +4 -0
- data/lib/nexus_cli/errors.rb +15 -1
- data/lib/nexus_cli/n3_metadata.rb +39 -56
- data/lib/nexus_cli/nexus_oss_remote.rb +262 -181
- data/lib/nexus_cli/nexus_pro_remote.rb +207 -190
- data/lib/nexus_cli/nexus_remote_factory.rb +30 -12
- data/lib/nexus_cli/tasks.rb +17 -18
- data/nexus_cli.gemspec +1 -1
- data/pro/nexus_custom_metadata.feature +97 -0
- data/pro/nexus_pro.feature +0 -99
- data/spec/oss_remote_spec.rb +6 -2
- data/spec/pro_remote_spec.rb +66 -6
- metadata +6 -5
@@ -1,113 +1,110 @@
|
|
1
|
-
require '
|
1
|
+
require 'httpclient'
|
2
2
|
require 'nokogiri'
|
3
|
-
require 'tempfile'
|
4
3
|
require 'yaml'
|
5
4
|
|
6
5
|
module NexusCli
|
7
6
|
class ProRemote < OSSRemote
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def get_artifact_custom_info_n3(artifact)
|
7
|
+
# Gets the custom metadata for an artifact
|
8
|
+
# @param [String] artifact The GAVE string of the artifact
|
9
|
+
# @result [String] The resulting custom metadata xml from the get operation
|
10
|
+
def get_artifact_custom_info_raw(artifact)
|
14
11
|
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
encoded_string = N3Metadata::create_base64_subject(group_id, artifact_id, version, extension)
|
13
|
+
response = nexus.get(nexus_url("service/local/index/custom_metadata/#{configuration['repository']}/#{encoded_string}"))
|
14
|
+
case response.status
|
15
|
+
when 200
|
16
|
+
if N3Metadata::missing_custom_metadata?(response.content)
|
17
|
+
raise N3NotFoundException
|
20
18
|
else
|
21
|
-
return
|
19
|
+
return response.content
|
22
20
|
end
|
23
|
-
|
21
|
+
when 404
|
24
22
|
raise ArtifactNotFoundException
|
23
|
+
else
|
24
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
begin
|
34
|
-
n3_temp.write(N3Metadata::parse_n3_hash(n3_user_urns))
|
35
|
-
n3_temp.close
|
36
|
-
update_artifact_custom_info_n3(artifact, n3_temp.path)
|
37
|
-
ensure
|
38
|
-
n3_temp.close
|
39
|
-
n3_temp.unlink
|
40
|
-
end
|
28
|
+
# Gets the custom metadata for an artifact in a simplified XML format
|
29
|
+
# @param [String] artifact The GAVE string of the artifact
|
30
|
+
# @result [String] The resulting custom metadata xml from the get operation
|
31
|
+
def get_artifact_custom_info(artifact)
|
32
|
+
N3Metadata::convert_result_to_simple_xml(get_artifact_custom_info_raw(artifact))
|
41
33
|
end
|
42
34
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
35
|
+
# Updates custom metadata for an artifact
|
36
|
+
# @param [String] artifact The GAVE string of the artifact
|
37
|
+
# @param [Array] *params The array of key:value strings
|
38
|
+
# @result [Integer] The resulting exit code of the operation
|
39
|
+
def update_artifact_custom_info(artifact, *params)
|
40
|
+
target_n3 = parse_custom_metadata_update_params(*params)
|
49
41
|
|
50
42
|
# Get all the urn:nexus/user# keys and consolidate.
|
51
43
|
# Read in nexus n3 file. If this is a newly-added artifact, there will be no n3 file so escape the exception.
|
52
44
|
begin
|
53
|
-
nexus_n3 =
|
54
|
-
rescue
|
55
|
-
nexus_n3 =
|
45
|
+
nexus_n3 = N3Metadata::convert_result_to_hash(get_artifact_custom_info_raw(artifact))
|
46
|
+
rescue N3NotFoundException
|
47
|
+
nexus_n3 = {}
|
56
48
|
end
|
57
49
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
n3_temp = Tempfile.new("nexus_n3")
|
67
|
-
begin
|
68
|
-
n3_temp.write(N3Metadata::parse_n3_hash(n3_user_urns))
|
69
|
-
n3_temp.close
|
70
|
-
nexus[post_string].put({:file => File.new(n3_temp.path)})
|
71
|
-
ensure
|
72
|
-
n3_temp.close
|
73
|
-
n3_temp.unlink
|
50
|
+
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
51
|
+
encoded_string = N3Metadata::create_base64_subject(group_id, artifact_id, version, extension)
|
52
|
+
response = nexus.post(nexus_url("service/local/index/custom_metadata/#{configuration['repository']}/#{encoded_string}"), :body => create_custom_metadata_update_json(nexus_n3, target_n3), :header => DEFAULT_CONTENT_TYPE_HEADER)
|
53
|
+
case response.code
|
54
|
+
when 201
|
55
|
+
return true
|
56
|
+
else
|
57
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
74
58
|
end
|
75
59
|
end
|
76
60
|
|
61
|
+
# Clears all custom metadata from an artifact
|
62
|
+
# @param [String] The GAVE string of the artifact
|
63
|
+
# @result [Integer] The resulting exit code of the operation
|
77
64
|
def clear_artifact_custom_info(artifact)
|
78
|
-
|
65
|
+
get_artifact_custom_info(artifact) # Check that artifact has custom metadata
|
79
66
|
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
ensure
|
88
|
-
n3_temp.close
|
89
|
-
n3_temp.unlink
|
67
|
+
encoded_string = N3Metadata::create_base64_subject(group_id, artifact_id, version, extension)
|
68
|
+
response = nexus.post(nexus_url("service/local/index/custom_metadata/#{configuration['repository']}/#{encoded_string}"), :body => create_custom_metadata_clear_json, :header => DEFAULT_CONTENT_TYPE_HEADER)
|
69
|
+
case response.status
|
70
|
+
when 201
|
71
|
+
return true
|
72
|
+
else
|
73
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
90
74
|
end
|
91
75
|
end
|
92
76
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
77
|
+
# Searches for artifacts using custom metadata
|
78
|
+
# @param [Array] *params The array of key:type:value strings
|
79
|
+
# @result [String] The resulting xml from the search
|
80
|
+
def search_artifacts_custom(*params)
|
81
|
+
nodesets = Array.new
|
82
|
+
parse_custom_metadata_search_params(*params).each do |param|
|
83
|
+
response = nexus.get(nexus_url("service/local/search/m2/freeform"), :query => {:p => param[0], :t => param[1], :v => param[2]})
|
84
|
+
case response.status
|
85
|
+
when 200
|
86
|
+
nodesets.push(Nokogiri::XML(response.body).xpath("/search-results/data"))
|
87
|
+
when 400
|
88
|
+
raise BadSearchRequestException
|
89
|
+
when 404
|
102
90
|
raise ArtifactNotFoundException
|
91
|
+
else
|
92
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
103
93
|
end
|
104
94
|
end
|
105
|
-
|
95
|
+
# Perform array intersection across all NodeSets for the final common set.
|
96
|
+
result = nodesets.inject(nodesets.first) {|memo, nodeset| get_common_artifact_set(memo, nodeset)}
|
106
97
|
return result.nil? ? "" : result.to_xml(:indent => 4)
|
107
98
|
end
|
108
99
|
|
109
100
|
def get_pub_sub(repository_id)
|
110
|
-
nexus
|
101
|
+
response = nexus.get(nexus_url("service/local/smartproxy/pub-sub/#{repository_id}"))
|
102
|
+
case response.status
|
103
|
+
when 200
|
104
|
+
return response.content
|
105
|
+
else
|
106
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
107
|
+
end
|
111
108
|
end
|
112
109
|
|
113
110
|
def enable_artifact_publish(repository_id)
|
@@ -123,17 +120,15 @@ module NexusCli
|
|
123
120
|
end
|
124
121
|
|
125
122
|
def artifact_publish(repository_id, params)
|
126
|
-
nexus
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
123
|
+
response = nexus.put(nexus_url("service/local/smartproxy/pub-sub/#{repository_id}"), :body => create_pub_sub_json(params), :header => DEFAULT_CONTENT_TYPE_HEADER)
|
124
|
+
case response.status
|
125
|
+
when 200
|
126
|
+
return true
|
127
|
+
else
|
128
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
133
129
|
end
|
134
130
|
end
|
135
131
|
|
136
|
-
|
137
132
|
def enable_artifact_subscribe(repository_id)
|
138
133
|
raise NotProxyRepositoryException.new(repository_id) unless Nokogiri::XML(get_repository_info(repository_id)).xpath("/repository/data/repoType").first.content == "proxy"
|
139
134
|
|
@@ -151,13 +146,12 @@ module NexusCli
|
|
151
146
|
end
|
152
147
|
|
153
148
|
def artifact_subscribe(repository_id, params)
|
154
|
-
nexus
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
149
|
+
response = nexus.put(nexus_url("service/local/smartproxy/pub-sub/#{repository_id}"), :body => create_pub_sub_json(params), :header => DEFAULT_CONTENT_TYPE_HEADER)
|
150
|
+
case response.status
|
151
|
+
when 200
|
152
|
+
return true
|
153
|
+
else
|
154
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
161
155
|
end
|
162
156
|
end
|
163
157
|
|
@@ -174,154 +168,177 @@ module NexusCli
|
|
174
168
|
end
|
175
169
|
|
176
170
|
def smart_proxy(params)
|
177
|
-
nexus
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
end
|
171
|
+
response = nexus.put(nexus_url("service/local/smartproxy/settings"), :body => create_smart_proxy_settings_json(params), :header => DEFAULT_CONTENT_TYPE_HEADER)
|
172
|
+
case response.status
|
173
|
+
when 200
|
174
|
+
return true
|
175
|
+
else
|
176
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
184
177
|
end
|
185
178
|
end
|
186
179
|
|
187
180
|
def get_smart_proxy_settings
|
188
|
-
nexus
|
181
|
+
response = nexus.get(nexus_url("service/local/smartproxy/settings"), :header => DEFAULT_ACCEPT_HEADER)
|
182
|
+
case response.status
|
183
|
+
when 200
|
184
|
+
return response.content
|
185
|
+
else
|
186
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
187
|
+
end
|
189
188
|
end
|
190
189
|
|
191
190
|
def get_smart_proxy_key
|
192
|
-
nexus
|
191
|
+
response = nexus.get(nexus_url("service/local/smartproxy/settings"), :header => DEFAULT_ACCEPT_HEADER)
|
192
|
+
case response.status
|
193
|
+
when 200
|
194
|
+
return response.content
|
195
|
+
else
|
196
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
197
|
+
end
|
193
198
|
end
|
194
199
|
|
195
200
|
def add_trusted_key(certificate, description, path=true)
|
196
201
|
params = {:description => description}
|
197
202
|
params[:certificate] = path ? File.read(File.expand_path(certificate)) : certificate
|
198
|
-
nexus
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
end
|
203
|
+
response = nexus.post(nexus_url("service/local/smartproxy/trusted-keys"), :body => create_add_trusted_key_json(params), :header => DEFAULT_CONTENT_TYPE_HEADER)
|
204
|
+
case response.status
|
205
|
+
when 201
|
206
|
+
return true
|
207
|
+
else
|
208
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
205
209
|
end
|
206
210
|
end
|
207
211
|
|
208
212
|
def delete_trusted_key(key_id)
|
209
|
-
nexus
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
end
|
213
|
+
response = nexus.delete(nexus_url("service/local/smartproxy/trusted-keys/#{key_id}"))
|
214
|
+
case response.status
|
215
|
+
when 204
|
216
|
+
return true
|
217
|
+
else
|
218
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
216
219
|
end
|
217
220
|
end
|
218
221
|
|
219
222
|
def get_trusted_keys
|
220
|
-
nexus
|
223
|
+
response = nexus.get(nexus_url("service/local/smartproxy/trusted-keys"), :header => DEFAULT_ACCEPT_HEADER)
|
224
|
+
case response.status
|
225
|
+
when 200
|
226
|
+
return response.content
|
227
|
+
else
|
228
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
229
|
+
end
|
221
230
|
end
|
222
231
|
|
223
232
|
def get_license_info
|
224
|
-
nexus
|
233
|
+
response = nexus.get(nexus_url("service/local/licensing"), :header => DEFAULT_ACCEPT_HEADER)
|
234
|
+
case response.status
|
235
|
+
when 200
|
236
|
+
return response.content
|
237
|
+
else
|
238
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
239
|
+
end
|
225
240
|
end
|
226
241
|
|
227
242
|
def install_license(license_file)
|
228
243
|
file = File.read(File.expand_path(license_file))
|
229
|
-
nexus
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
end
|
244
|
+
response = nexus.post(nexus_url("service/local/licensing/upload"), :body => file, :header => {"Content-Type" => "application/octet-stream"})
|
245
|
+
case response.status
|
246
|
+
when 201
|
247
|
+
return true
|
248
|
+
when 403
|
249
|
+
raise LicenseInstallFailure
|
250
|
+
else
|
251
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
238
252
|
end
|
239
253
|
end
|
240
254
|
|
241
255
|
def install_license_bytes(bytes)
|
242
|
-
nexus
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
end
|
256
|
+
response = nexus.post(nexus_url("service/local/licensing/upload"), :body => bytes, :header => {"Content-Type" => "application/octet-stream"})
|
257
|
+
case response.status
|
258
|
+
when 201
|
259
|
+
return true
|
260
|
+
when 403
|
261
|
+
raise LicenseInstallFailure
|
262
|
+
else
|
263
|
+
raise UnexpectedStatusCodeException.new(response.status)
|
251
264
|
end
|
252
265
|
end
|
253
266
|
|
254
267
|
private
|
255
268
|
|
256
|
-
|
257
|
-
|
258
|
-
|
269
|
+
def create_add_trusted_key_json(params)
|
270
|
+
JSON.dump(:data => params)
|
271
|
+
end
|
259
272
|
|
260
|
-
|
261
|
-
|
262
|
-
|
273
|
+
def create_smart_proxy_settings_json(params)
|
274
|
+
JSON.dump(:data => params)
|
275
|
+
end
|
263
276
|
|
264
|
-
|
265
|
-
|
266
|
-
|
277
|
+
def create_pub_sub_json(params)
|
278
|
+
JSON.dump(:data => params)
|
279
|
+
end
|
267
280
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
281
|
+
# Converts an array of parameters used to update custom metadata
|
282
|
+
# @param [Array] *params The array of key:value strings
|
283
|
+
# @return [Hash] The resulting hash of parsed key:value items
|
284
|
+
# @example
|
285
|
+
# parse_custom_metadata_update_params(["cookie:oatmeal raisin"]) #=> {"cookie"=>"oatmeal raisin"}
|
286
|
+
def parse_custom_metadata_update_params(*params)
|
287
|
+
params.inject({}) do |parsed_params, param|
|
288
|
+
# param = key:value
|
289
|
+
metadata_key, metadata_value = param.split(":", 2)
|
290
|
+
if N3Metadata::valid_n3_key?(metadata_key) && N3Metadata::valid_n3_value?(metadata_value)
|
291
|
+
parsed_params[metadata_key] = metadata_value
|
292
|
+
else
|
280
293
|
raise N3ParameterMalformedException
|
281
294
|
end
|
295
|
+
parsed_params
|
282
296
|
end
|
297
|
+
end
|
283
298
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
return parsed_params
|
297
|
-
rescue
|
299
|
+
# Converts an array of parameters used to search by custom metadata
|
300
|
+
# @param [Array] *params The array of key:type:value strings
|
301
|
+
# @result [Array] The resulting array of parsed key:type:value items
|
302
|
+
# @example
|
303
|
+
# parse_custom_metadata_search_params(["cookie:matches:oatmeal raisin"]) #=> #=> [["cookie","matches","oatmeal raisin"]]
|
304
|
+
def parse_custom_metadata_search_params(*params)
|
305
|
+
params.inject([]) do |parsed_params, param|
|
306
|
+
# param = key:type:value
|
307
|
+
metadata_key, search_type, metadata_value = param.split(":", 3)
|
308
|
+
if N3Metadata::valid_n3_key?(metadata_key) && N3Metadata::valid_n3_value?(metadata_value) && N3Metadata::valid_n3_search_type?(search_type)
|
309
|
+
parsed_params.push([metadata_key, search_type, metadata_value])
|
310
|
+
else
|
298
311
|
raise SearchParameterMalformedException
|
299
312
|
end
|
313
|
+
parsed_params
|
300
314
|
end
|
315
|
+
end
|
301
316
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
return intersection.count > 0 ? Nokogiri::XML("<data>#{intersection.join}</data>").root : Nokogiri::XML("").root
|
306
|
-
end
|
317
|
+
def create_custom_metadata_update_json(source, target)
|
318
|
+
JSON.dump(:data => N3Metadata::create_metadata_hash(source, target))
|
319
|
+
end
|
307
320
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
321
|
+
def create_custom_metadata_clear_json
|
322
|
+
JSON.dump(:data => {})
|
323
|
+
end
|
324
|
+
|
325
|
+
# Gets the intersection of two artifact arrays, returning the common set
|
326
|
+
# @param [Array] set1, set2 The two Nokogiri::NodeSet objects to intersect
|
327
|
+
# @result [Nokogiri::NodeSet] The resulting object generated from the array intersect
|
328
|
+
def get_common_artifact_set(set1, set2)
|
329
|
+
intersection = get_artifact_array(set1) & get_artifact_array(set2)
|
330
|
+
return intersection.count > 0 ? Nokogiri::XML("<data>#{intersection.join}</data>").root : Nokogiri::XML("").root
|
331
|
+
end
|
332
|
+
|
333
|
+
# Collect <artifact> elements into an array
|
334
|
+
# @info This will allow use of array intersection to find common artifacts in searches
|
335
|
+
# @param [Nokogiri::NodeSet] set The object to be divided by <artifact> elements
|
336
|
+
# @result [Array] The result array of artifact elements
|
337
|
+
def get_artifact_array(set)
|
338
|
+
set.search("//artifact").inject([]) do |artifacts, artifact|
|
339
|
+
artifacts.push(artifact.to_s)
|
340
|
+
artifacts
|
325
341
|
end
|
342
|
+
end
|
326
343
|
end
|
327
344
|
end
|