nexus_api 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,31 @@
1
1
  module NexusAPI
2
2
  class API
3
3
  # GET /service/rest/beta/security/roles
4
+ def list_roles
5
+ @connection.get_response(endpoint: 'security/roles', api_version: 'beta')
6
+ end
7
+
4
8
  # POST /service/rest/beta/security/roles
9
+ def create_role(id:, name:, description: nil, privileges: [], roles: [])
10
+ parameters = {
11
+ 'id' => id,
12
+ 'name' => name,
13
+ 'description' => description,
14
+ 'privileges' => privileges,
15
+ 'roles' => roles
16
+ }
17
+ @connection.post(endpoint: 'security/roles', parameters: parameters, api_version: 'beta')
18
+ end
19
+
5
20
  # GET /service/rest/beta/security/roles/{id}
21
+ def list_role(id:)
22
+ @connection.get_response(endpoint: "security/roles/#{id}?source=default", api_version: 'beta')
23
+ end
24
+
6
25
  # PUT /service/rest/beta/security/roles/{id}
7
26
  # DELETE /service/rest/beta/security/roles/{id}
27
+ def delete_role(id:)
28
+ @connection.delete(endpoint: "security/roles/#{id}", api_version: 'beta')
29
+ end
8
30
  end
9
31
  end
@@ -13,6 +13,23 @@ module NexusAPI
13
13
  @connection.get_response(endpoint: endpoint, paginate: paginate)
14
14
  end
15
15
 
16
+ def search_all_assets(name:, format: nil, repository: nil, sha1: nil, version: nil)
17
+ results = Array.new.tap do |results|
18
+ loop do
19
+ results.concat(
20
+ search_asset(
21
+ name: name,
22
+ format: format,
23
+ repository: repository,
24
+ sha1: sha1,
25
+ version: version,
26
+ paginate: true
27
+ ))
28
+ break unless paginate?
29
+ end
30
+ end
31
+ end
32
+
16
33
  # GET /service/rest/v1/search/assets/download
17
34
  end
18
35
  end
@@ -5,11 +5,20 @@ module NexusAPI
5
5
  @connection.get_response(endpoint: 'tags', paginate: paginate)
6
6
  end
7
7
 
8
+ def list_all_tags
9
+ tags = Array.new.tap do |tags|
10
+ loop do
11
+ tags.concat(list_tags(paginate: true))
12
+ break unless paginate?
13
+ end
14
+ end
15
+ end
16
+
8
17
  # POST /service/rest/v1/tags
9
18
  def create_tag(name:)
10
- parameters = JSON.dump({
19
+ parameters = {
11
20
  'name' => name,
12
- })
21
+ }
13
22
  @connection.post(endpoint: 'tags', parameters: parameters)
14
23
  end
15
24
 
@@ -1,9 +1,30 @@
1
1
  module NexusAPI
2
2
  class API
3
3
  # GET /service/rest/beta/security/users
4
+ def list_users
5
+ @connection.get_response(endpoint: 'security/users', api_version: 'beta')
6
+ end
7
+
4
8
  # POST /service/rest/beta/security/users
9
+ def create_user(user_id:, first_name:, last_name:, email:, password:, roles:)
10
+ parameters = {
11
+ 'userId' => user_id,
12
+ 'firstName' => first_name,
13
+ 'lastName' => last_name,
14
+ 'emailAddress' => email,
15
+ 'password' => password,
16
+ 'status' => 'active',
17
+ 'roles' => roles,
18
+ }
19
+ @connection.post(endpoint: 'security/users', parameters: parameters, api_version: 'beta')
20
+ end
21
+
5
22
  # PUT /service/rest/beta/security/users/{userId}
6
23
  # DELETE /service/rest/beta/security/users/{userId}
24
+ def delete_user(user_id:)
25
+ @connection.delete(endpoint: "security/users/#{user_id}", api_version: 'beta')
26
+ end
27
+
7
28
  # PUT /service/rest/beta/security/users/{userId}/change-password
8
29
  # DELETE /service/rest/beta/security/users/{userId}/user-token
9
30
  end
@@ -51,16 +51,31 @@ module NexusAPI
51
51
  print_paginating_set(action: :list_components, params: {repository: options[:repository]}, filter: 'name', proc: proc)
52
52
  end
53
53
 
54
+ desc 'privileges', 'Prints out a list of all privileges'
55
+ def privileges
56
+ print_set(action: :list_privileges, filter: 'name')
57
+ end
58
+
54
59
  desc 'repositories', 'Prints out a list of all repositories'
55
60
  def repositories
56
61
  print_set(action: :list_repositories, filter: 'name')
57
62
  end
58
63
 
64
+ desc 'roles', 'Prints out a list of all roles'
65
+ def roles
66
+ print_set(action: :list_roles, filter: 'name')
67
+ end
68
+
59
69
  desc 'status', 'Prints out if the Nexus server can respond to read and write requests'
60
70
  def status
61
71
  setup
62
72
  puts "Nexus can respond to read requests: #{@api.status}"
63
73
  puts "Nexus can respond to write requests: #{@api.status_writable}"
64
74
  end
75
+
76
+ desc 'users', 'Prints out a list of all users'
77
+ def users
78
+ print_set(action: :list_users, filter: 'emailAddress')
79
+ end
65
80
  end
66
81
  end
@@ -15,8 +15,8 @@ module NexusAPI
15
15
  return false unless docker_valid?
16
16
  image_name = image_name(@pull_host, image_name, tag)
17
17
  begin
18
- image = @docker.pull_image(@username, @password, image_name)
19
- rescue Docker::Error::NotFoundError => error
18
+ @docker.pull_image(@username, @password, image_name)
19
+ rescue Docker::Error::NotFoundError
20
20
  puts "ERROR: Failed to pull Docker image #{image_name}.\nDoes it exist in Nexus?"
21
21
  return false
22
22
  end
@@ -88,7 +88,11 @@ module NexusAPI
88
88
 
89
89
  def handle(error)
90
90
  puts "ERROR: Request failed"
91
- puts error.description if error.is_a?(RestClient::Response)
91
+ if error.is_a?(RestClient::Response)
92
+ puts error.description
93
+ else
94
+ puts error.to_s
95
+ end
92
96
  end
93
97
 
94
98
  def catch_connection_error
@@ -98,8 +102,12 @@ module NexusAPI
98
102
  return handle(error)
99
103
  rescue RestClient::Unauthorized => error
100
104
  return handle(error)
105
+ rescue RestClient::Exceptions::ReadTimeout => error
106
+ return handle(error)
101
107
  rescue RestClient::ExceptionWithResponse => error
102
108
  return handle(error.response)
109
+ rescue StandardError => error
110
+ return handle(error)
103
111
  end
104
112
  end
105
113
 
@@ -108,6 +116,7 @@ module NexusAPI
108
116
  end
109
117
 
110
118
  def send_request(connection_method, endpoint, parameters: '', headers: {}, api_version: 'v1')
119
+ parameters = parameters.to_json if headers['Content-Type'] == 'application/json'
111
120
  url = "https://#{@hostname}/service/rest/#{api_version}/#{endpoint}"
112
121
  catch_connection_error do
113
122
  RestClient::Request.execute(
@@ -124,7 +133,7 @@ module NexusAPI
124
133
  # paginate answers is the user requesting pagination, paginate? answers does a continuation token exist
125
134
  # if an empty continuation token is included in the request we'll get an ArrayIndexOutOfBoundsException
126
135
  endpoint += "#{url_marker}continuationToken=#{@continuation_token}" if paginate && paginate?
127
- response = send_request(
136
+ send_request(
128
137
  :get,
129
138
  endpoint,
130
139
  headers: headers,
@@ -1,4 +1,4 @@
1
1
  module NexusAPI
2
- VERSION = '1.4.0'
2
+ VERSION = '2.0.0'
3
3
  end
4
4
 
@@ -1,92 +1,432 @@
1
- require 'json'
2
-
3
1
  module NexusAPI
4
2
  class ParameterBuilder
5
- # Write Policies
6
- ALLOW = 'ALLOW'
7
- ALLOW_ONCE = 'ALLOW_ONCE'
8
- DENY = 'DENY'
9
-
10
- # Version Policy
11
- RELEASE = 'RELEASE'
12
- SNAPSHOT = 'SNAPSHOT'
13
- MIXED = 'MIXED'
14
-
15
- # Layout or Deploy Policy
16
- STRICT = 'STRICT'
17
- PERMISSIVE = 'PERMISSIVE'
3
+ def self.docker_group(name, members, options)
4
+ default_options = {
5
+ 'online' => true,
6
+ 'storage' => {
7
+ 'blobStoreName' => 'default',
8
+ 'strictContentTypeValidation' => true
9
+ },
10
+ 'docker' => {
11
+ 'v1Enabled' => false,
12
+ 'forceBasicAuth' => true
13
+ },
14
+ 'group' => {}
15
+ }
16
+ apply_changes(default: default_options, override: options, name: name, members: members)
17
+ end
18
18
 
19
- def self.docker_hosted(name, port, write_policy: ALLOW_ONCE)
20
- {
21
- 'name' => name,
19
+ def self.docker_hosted(name, options)
20
+ default_options = {
22
21
  'online' => true,
23
22
  'storage' => {
24
23
  'blobStoreName' => 'default',
25
24
  'strictContentTypeValidation' => true,
26
- 'writePolicy' => write_policy
25
+ 'writePolicy' => 'allow_once'
26
+ },
27
+ 'cleanup' => {
28
+ 'policyNames' => []
29
+ },
30
+ 'docker' => {
31
+ 'v1Enabled' => false,
32
+ 'forceBasicAuth' => true
33
+ }
34
+ }
35
+ apply_changes(default: default_options, override: options, name: name)
36
+ end
37
+
38
+ def self.docker_proxy(name, remote_url, options)
39
+ default_options = {
40
+ 'online' => true,
41
+ 'storage' => {
42
+ 'blobStoreName' => 'default',
43
+ 'strictContentTypeValidation' => true
44
+ },
45
+ 'proxy' => {
46
+ 'contentMaxAge' => 1440,
47
+ 'metadataMaxAge' => 1440
48
+ },
49
+ 'negativeCache' => {
50
+ 'enabled' => true,
51
+ 'timeToLive' => 1440
52
+ },
53
+ 'httpClient' => {
54
+ 'blocked' => false,
55
+ 'autoBlock' => true
27
56
  },
28
57
  'docker' => {
29
58
  'v1Enabled' => false,
30
- 'forceBasicAuth' => true,
31
- 'httpPort' => port
59
+ 'forceBasicAuth' => true
60
+ },
61
+ 'dockerProxy' => {
62
+ 'indexType' => 'REGISTRY'
32
63
  }
33
- }.to_json
64
+ }
65
+ apply_changes(default: default_options, override: options, name: name, url: remote_url)
34
66
  end
35
67
 
36
- def self.maven_hosted(name, write_policy: ALLOW_ONCE, version_policy: RELEASE, layout_policy: STRICT)
37
- {
38
- 'name' => name,
68
+ def self.maven_group(name, members, options)
69
+ default_options = {
70
+ 'online' => true,
71
+ 'storage' => {
72
+ 'blobStoreName' => 'default',
73
+ 'strictContentTypeValidation' => true
74
+ },
75
+ 'group' => {}
76
+ }
77
+ apply_changes(default: default_options, override: options, name: name, members: members)
78
+ end
79
+
80
+ def self.maven_hosted(name, options)
81
+ default_options = {
39
82
  'online' => true,
40
83
  'storage' => {
41
84
  'blobStoreName' => 'default',
42
85
  'strictContentTypeValidation' => true,
43
- 'writePolicy' => write_policy
86
+ 'writePolicy' => 'allow_once'
87
+ },
88
+ 'cleanup' => {
89
+ 'policyNames' => []
90
+ },
91
+ 'maven' => {
92
+ 'versionPolicy' => 'RELEASE',
93
+ 'layoutPolicy' => 'STRICT'
94
+ }
95
+ }
96
+ apply_changes(default: default_options, override: options, name: name)
97
+ end
98
+
99
+ def self.maven_proxy(name, remote_url, options)
100
+ default_options = {
101
+ 'online' => true,
102
+ 'storage' => {
103
+ 'blobStoreName' => 'default',
104
+ 'strictContentTypeValidation' => true
105
+ },
106
+ 'cleanup' => {
107
+ 'policyNames' => []
108
+ },
109
+ 'proxy' => {
110
+ 'contentMaxAge' => 1440,
111
+ 'metadataMaxAge' => 1440
112
+ },
113
+ 'negativeCache' => {
114
+ 'enabled' => true,
115
+ 'timeToLive' => 1440
116
+ },
117
+ 'httpClient' => {
118
+ 'blocked' => false,
119
+ 'autoBlock' => true,
44
120
  },
45
121
  'maven' => {
46
- 'versionPolicy' => version_policy,
47
- 'layoutPolicy' => layout_policy
122
+ 'versionPolicy' => 'RELEASE',
123
+ 'layoutPolicy' => 'STRICT'
124
+ }
125
+ }
126
+ apply_changes(default: default_options, override: options, name: name, url: remote_url)
127
+ end
128
+
129
+ def self.npm_group(name, members, options)
130
+ default_options = {
131
+ 'online' => true,
132
+ 'storage' => {
133
+ 'blobStoreName' => 'default',
134
+ 'strictContentTypeValidation' => true
135
+ },
136
+ 'group' => {}
137
+ }
138
+ apply_changes(default: default_options, override: options, name: name, members: members)
139
+ end
140
+
141
+ def self.npm_hosted(name, options)
142
+ default_options = {
143
+ 'online' => true,
144
+ 'storage' => {
145
+ 'blobStoreName' => 'default',
146
+ 'strictContentTypeValidation' => true,
147
+ 'writePolicy' => 'allow_once'
148
+ },
149
+ 'cleanup' => {
150
+ 'policyNames' => []
151
+ }
152
+ }
153
+ apply_changes(default: default_options, override: options, name: name)
154
+ end
155
+
156
+ def self.npm_proxy(name, remote_url, options)
157
+ default_options = {
158
+ 'online' => true,
159
+ 'storage' => {
160
+ 'blobStoreName' => 'default',
161
+ 'strictContentTypeValidation' => true
162
+ },
163
+ 'cleanup' => {
164
+ 'policyNames' => []
165
+ },
166
+ 'proxy' => {
167
+ 'contentMaxAge' => 1440,
168
+ 'metadataMaxAge' => 1440
169
+ },
170
+ 'negativeCache' => {
171
+ 'enabled' => true,
172
+ 'timeToLive' => 1440
173
+ },
174
+ 'httpClient' => {
175
+ 'blocked' => false,
176
+ 'autoBlock' => true,
177
+ },
178
+ }
179
+ apply_changes(default: default_options, override: options, name: name, url: remote_url)
180
+ end
181
+
182
+ def self.pypi_group(name, members, options)
183
+ default_options = {
184
+ 'online' => true,
185
+ 'storage' => {
186
+ 'blobStoreName' => 'default',
187
+ 'strictContentTypeValidation' => true
188
+ },
189
+ 'group' => {}
190
+ }
191
+ apply_changes(default: default_options, override: options, name: name, members: members)
192
+ end
193
+
194
+ def self.pypi_hosted(name, options)
195
+ default_options = {
196
+ 'online' => true,
197
+ 'storage' => {
198
+ 'blobStoreName' => 'default',
199
+ 'strictContentTypeValidation' => true,
200
+ 'writePolicy' => 'allow_once'
201
+ },
202
+ 'cleanup' => {
203
+ 'policyNames' => []
48
204
  }
49
- }.to_json
205
+ }
206
+ apply_changes(default: default_options, override: options, name: name)
207
+ end
208
+
209
+ def self.pypi_proxy(name, remote_url, options)
210
+ default_options = {
211
+ 'online' => true,
212
+ 'storage' => {
213
+ 'blobStoreName' => 'default',
214
+ 'strictContentTypeValidation' => true
215
+ },
216
+ 'cleanup' => {
217
+ 'policyNames' => []
218
+ },
219
+ 'proxy' => {
220
+ 'contentMaxAge' => 1440,
221
+ 'metadataMaxAge' => 1440
222
+ },
223
+ 'negativeCache' => {
224
+ 'enabled' => true,
225
+ 'timeToLive' => 1440
226
+ },
227
+ 'httpClient' => {
228
+ 'blocked' => false,
229
+ 'autoBlock' => true,
230
+ },
231
+ }
232
+ apply_changes(default: default_options, override: options, name: name, url: remote_url)
233
+ end
234
+
235
+ def self.raw_group(name, members, options)
236
+ default_options = {
237
+ 'online' => true,
238
+ 'storage' => {
239
+ 'blobStoreName' => 'default',
240
+ 'strictContentTypeValidation' => true
241
+ },
242
+ 'group' => {}
243
+ }
244
+ apply_changes(default: default_options, override: options, name: name, members: members)
50
245
  end
51
246
 
52
- def self.npm_hosted(name, write_policy: ALLOW_ONCE)
53
- {
54
- 'name' => name,
247
+ def self.raw_hosted(name, options)
248
+ default_options = {
55
249
  'online' => true,
56
250
  'storage' => {
57
251
  'blobStoreName' => 'default',
58
252
  'strictContentTypeValidation' => true,
59
- 'writePolicy' => write_policy
253
+ 'writePolicy' => 'allow_once'
254
+ },
255
+ 'cleanup' => {
256
+ 'policyNames' => []
60
257
  }
61
- }.to_json
258
+ }
259
+ apply_changes(default: default_options, override: options, name: name)
260
+ end
261
+
262
+ def self.raw_proxy(name, remote_url, options)
263
+ default_options = {
264
+ 'online' => true,
265
+ 'storage' => {
266
+ 'blobStoreName' => 'default',
267
+ 'strictContentTypeValidation' => true
268
+ },
269
+ 'cleanup' => {
270
+ 'policyNames' => []
271
+ },
272
+ 'proxy' => {
273
+ 'contentMaxAge' => 1440,
274
+ 'metadataMaxAge' => 1440
275
+ },
276
+ 'negativeCache' => {
277
+ 'enabled' => true,
278
+ 'timeToLive' => 1440
279
+ },
280
+ 'httpClient' => {
281
+ 'blocked' => false,
282
+ 'autoBlock' => true,
283
+ }
284
+ }
285
+ apply_changes(default: default_options, override: options, name: name, url: remote_url)
286
+ end
287
+
288
+ def self.rubygems_group(name, members, options)
289
+ default_options = {
290
+ 'online' => true,
291
+ 'storage' => {
292
+ 'blobStoreName' => 'default',
293
+ 'strictContentTypeValidation' => true
294
+ },
295
+ 'group' => {}
296
+ }
297
+ apply_changes(default: default_options, override: options, name: name, members: members)
62
298
  end
63
299
 
64
- def self.pypi_hosted(name, write_policy: ALLOW_ONCE)
65
- {
66
- 'name' => name,
300
+ def self.rubygems_hosted(name, options)
301
+ default_options = {
67
302
  'online' => true,
68
303
  'storage' => {
69
304
  'blobStoreName' => 'default',
70
305
  'strictContentTypeValidation' => true,
71
- 'writePolicy' => write_policy
306
+ 'writePolicy' => 'allow_once'
307
+ },
308
+ 'cleanup' => {
309
+ 'policyNames' => []
72
310
  }
73
- }.to_json
311
+ }
312
+ apply_changes(default: default_options, override: options, name: name)
74
313
  end
75
314
 
76
- def self.yum_hosted(name, depth, write_policy: ALLOW_ONCE, deploy_policy: STRICT)
77
- {
78
- 'name' => name,
315
+ def self.rubygems_proxy(name, remote_url, options)
316
+ default_options = {
317
+ 'online' => true,
318
+ 'storage' => {
319
+ 'blobStoreName' => 'default',
320
+ 'strictContentTypeValidation' => true
321
+ },
322
+ 'cleanup' => {
323
+ 'policyNames' => []
324
+ },
325
+ 'proxy' => {
326
+ 'contentMaxAge' => 1440,
327
+ 'metadataMaxAge' => 1440
328
+ },
329
+ 'negativeCache' => {
330
+ 'enabled' => true,
331
+ 'timeToLive' => 1440
332
+ },
333
+ 'httpClient' => {
334
+ 'blocked' => false,
335
+ 'autoBlock' => true,
336
+ },
337
+ }
338
+ apply_changes(default: default_options, override: options, name: name, url: remote_url)
339
+ end
340
+
341
+ def self.yum_group(name, members, options)
342
+ default_options = {
343
+ 'online' => true,
344
+ 'storage' => {
345
+ 'blobStoreName' => 'default',
346
+ 'strictContentTypeValidation' => true
347
+ },
348
+ 'group' => {}
349
+ }
350
+ apply_changes(default: default_options, override: options, name: name, members: members)
351
+ end
352
+
353
+ def self.yum_hosted(name, options)
354
+ default_options = {
79
355
  'online' => true,
80
356
  'storage' => {
81
357
  'blobStoreName' => 'default',
82
358
  'strictContentTypeValidation' => true,
83
- 'writePolicy' => write_policy
359
+ 'writePolicy' => 'allow_once'
360
+ },
361
+ 'cleanup' => {
362
+ 'policyNames' => []
84
363
  },
85
364
  'yum' => {
86
- 'repodataDepth' => depth,
87
- 'deployPolicy' => deploy_policy
365
+ 'repodataDepth' => 3,
366
+ 'deployPolicy' => 'STRICT'
88
367
  }
89
- }.to_json
368
+ }
369
+ apply_changes(default: default_options, override: options, name: name)
370
+ end
371
+
372
+ def self.yum_proxy(name, remote_url, options)
373
+ default_options = {
374
+ 'online' => true,
375
+ 'storage' => {
376
+ 'blobStoreName' => 'default',
377
+ 'strictContentTypeValidation' => true
378
+ },
379
+ 'cleanup' => {
380
+ 'policyNames' => []
381
+ },
382
+ 'proxy' => {
383
+ 'contentMaxAge' => 1440,
384
+ 'metadataMaxAge' => 1440
385
+ },
386
+ 'negativeCache' => {
387
+ 'enabled' => true,
388
+ 'timeToLive' => 1440
389
+ },
390
+ 'httpClient' => {
391
+ 'blocked' => false,
392
+ 'autoBlock' => true,
393
+ },
394
+ }
395
+ apply_changes(default: default_options, override: options, name: name, url: remote_url)
396
+ end
397
+
398
+
399
+ private
400
+
401
+ def self.deep_merge(default_hash, hash)
402
+ full_hash = {}
403
+
404
+ default_hash.each do |key, value|
405
+ if hash[key].nil?
406
+ full_hash[key] = value
407
+ else
408
+ if value.is_a?(Hash)
409
+ full_hash[key] = deep_merge(value, hash[key])
410
+ else
411
+ full_hash[key] = hash[key]
412
+ end
413
+ hash.delete(key)
414
+ end
415
+ end
416
+
417
+ hash.each do |key, value|
418
+ full_hash[key] = value
419
+ end
420
+
421
+ return full_hash
422
+ end
423
+
424
+ def self.apply_changes(default:, override:, name:, url: nil, members: nil)
425
+ options = deep_merge(default, override)
426
+ options['name'] = name
427
+ options['proxy']['remoteUrl'] = url unless url.nil?
428
+ options['group']['memberNames'] = members unless members.nil?
429
+ return options
90
430
  end
91
431
  end
92
432
  end