Class: Artifactory::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/artifactory/client.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(endpoint:, username: nil, password: nil, api_key: nil, ssl_verify: true) ⇒ Client

Initialize an Artifactory client instance

Parameters:

  • endpoint (String)

    Artifactory REST API endpoint

  • username (String) (defaults to: nil)

    Username for HTTP basic authentication

  • password (String) (defaults to: nil)

    Password for HTTP basic authentication

  • api_key (String) (defaults to: nil)

    API key

  • ssl_verify (Boolean) (defaults to: true)

    Enable/Disable SSL verification



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/artifactory/client.rb', line 19

def initialize(endpoint:, username: nil, password: nil, api_key: nil, ssl_verify: true)
  basic_auth = {}
  uri = URI.parse(endpoint)
  http = Net::HTTP.new(uri.host, uri.port)

  if (username and api_key) or (username.nil? and api_key.nil?)
    raise RuntimeError, "Either HTTP basic or API key are allowed as authentication methods"
  end

  headers = {
    'Content-type' => 'application/json',
    'Accept' => 'application/json',
  }

  if username
    basic_auth = {'username' => username, 'password' => password}
  else
    headers['X-JFrog-Art-Api'] = api_key
  end

  if uri.scheme == 'https'
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless ssl_verify
  end

  @uri = uri
  @http = http
  @basic_auth = basic_auth
  @headers = headers
end

Instance Attribute Details

#basic_authObject (readonly)

Returns the value of attribute basic_auth.



9
10
11
# File 'lib/artifactory/client.rb', line 9

def basic_auth
  @basic_auth
end

#headersObject (readonly)

Returns the value of attribute headers.



9
10
11
# File 'lib/artifactory/client.rb', line 9

def headers
  @headers
end

#httpObject (readonly)

Returns the value of attribute http.



9
10
11
# File 'lib/artifactory/client.rb', line 9

def http
  @http
end

#uriObject (readonly)

Returns the value of attribute uri.



9
10
11
# File 'lib/artifactory/client.rb', line 9

def uri
  @uri
end

Instance Method Details

#docker_images(repo_key:) ⇒ Hash, Array<String>

Lists all Docker repositories hosted in under an Artifactory Docker repository

Parameters:

  • repo_key (String)

    Repository key

  • recurse (Boolean)

    Recursively retrieve image tags

Returns:

  • (Hash, Array<String>)

    List of docker images



83
84
85
# File 'lib/artifactory/client.rb', line 83

def docker_images(repo_key:)
  api_get("/docker/#{repo_key}/v2/_catalog")['repositories']
end

#docker_manifest(repo_key:, image_name:, image_tag:) ⇒ Hash

Retrieve a docker image tag manifest

Parameters:

  • repo_key (String)

    Repository key

  • image_name (String)

    Docker image name

  • image_tag (String)

    Docker image tag

Returns:

  • (Hash)

    Docker manifest describing the tag



104
105
106
# File 'lib/artifactory/client.rb', line 104

def docker_manifest(repo_key:, image_name:, image_tag:)
  api_get("/docker/#{repo_key}/v2/#{image_name}/manifests/#{image_tag}")
end

#docker_tags(repo_key:, image_name:) ⇒ Array<String>

Retrieve all tags for a docker image

Parameters:

  • repo_key (String)

    Repository key

  • image_name (String)

    Docker image name

Returns:

  • (Array<String>)

    List of tags



93
94
95
# File 'lib/artifactory/client.rb', line 93

def docker_tags(repo_key:, image_name:)
  api_get("/docker/#{repo_key}/v2/#{image_name}/tags/list")['tags']
end

#file_delete(repo_key:, path:) ⇒ Object

Deletes a file or a folder from the specified destination

Parameters:

  • repo_key (String)

    Repository key

  • path (String)

    Path of the file to delete



186
187
188
# File 'lib/artifactory/client.rb', line 186

def file_delete(repo_key:, path:)
  api_delete(File.join(repo_key, path))
end

#file_info(repo_key:, path:) ⇒ Hash

Get file information like last modification time, creation time etc.

Parameters:

  • repo_key (String)

    Repository key

  • path (String)

    Path of the file to look up

Returns:

  • (Hash)

    File information



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/artifactory/client.rb', line 140

def file_info(repo_key:, path:)
  ret = {}

  api_get(File.join("/storage", repo_key, path).chomp('/')).each do |k, v|
    case k
      when "created", "lastModified", "lastUpdated"
        ret[k] = Time.parse(v)

      else
        ret[k] = v
    end
  end

  ret
end

#file_list(repo_key:, folder_path: '/', deep: false, depth: 0, list_folders: false, md_timestamps: false, include_root_path: false) ⇒ Hash

Get a flat (the default) or deep listing of the files and folders (not included by default) within a folder

Parameters:

  • repo_key (String)

    Repository key

  • image_name (String)

    Docker image name

  • image_tag (String)

    Docker image tag

Returns:

  • (Hash)

    Docker manifest describing the tag



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/artifactory/client.rb', line 115

def file_list(repo_key:, folder_path: '/', deep: false, depth: 0, list_folders: false, md_timestamps: false, include_root_path: false)
  path = ["/storage", repo_key, folder_path].join('/').chomp('/')
  params = ['list']
  params << "deep=#{deep ? 1 : 0}"
  params << "depth=#{depth}" if depth > 0
  params << "listFolders=#{list_folders ? 1 : 0}"
  params << "mdTimestamps=#{md_timestamps ? 1 : 0}"
  params << "includeRootPath=#{include_root_path ? 1 : 0}"

  files = {}
  api_get([path, params.join('&')].join('?'))['files'].each do |file|
    name = file['uri']
    files[name] = file.tap { |h| h.delete('uri') }
    files[name]['lastModified'] = Time.parse(files[name]['lastModified'])
  end

  files
end

#file_stat(repo_key:, path:) ⇒ Hash

Get file statistics like the number of times an item was downloaded, last download date and last downloader.

Parameters:

  • repo_key (String)

    Repository key

  • path (String)

    Path of the file to look up

Returns:

  • (Hash)

    File statistics



162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/artifactory/client.rb', line 162

def file_stat(repo_key:, path:)
  ret = {}

  p = File.join("/storage", repo_key, path).chomp('/')
  params = ['stats']

  api_get([p, params.join('&')].join('?')).tap { |h| h.delete('uri') }.each do |k, v|
    case k
      when "lastDownloaded", "remoteLastDownloaded"
        ret[k] = Time.at(v/1000) if v > 0

      else
        ret[k] = v
    end
  end

  ret
end

#get_repo(key:) ⇒ Hash

Retrieves the current configuration of a repository. Supported by local, remote and virtual repositories.

Parameters:

  • key (String)

    Repository key

Returns:

  • (Hash)

    Repository information



55
56
57
# File 'lib/artifactory/client.rb', line 55

def get_repo(key:)
  api_get("/repositories/#{key}").tap { |h| h.delete('key') }
end

#repos(type: nil, recurse: false) ⇒ Hash

Returns a list of minimal repository details (unless recurse is enabled) for all repositories of the specified type.

Parameters:

  • type (nil, local, remote, virtual) (defaults to: nil)

    Optionally filter by repository type

  • recurse (Boolean) (defaults to: false)

    Recursively retrieve repos configuration

Returns:

  • (Hash)

    List of repositories



65
66
67
68
69
70
71
72
73
74
75
# File 'lib/artifactory/client.rb', line 65

def repos(type: nil, recurse: false)
  ret = {}
  params = []
  params << "type=#{type}" if type

  api_get(["/repositories", params.join('&')].join('?')).each do |repo|
    ret[repo['key']] = recurse ? self.get_repo(key: repo['key']) : repo.tap { |h| h.delete('key') }
  end

  ret
end

#search_creation(repo_key:, from_date: nil, to_date: Time.now) ⇒ Hash

Get all artifacts created in date range

Parameters:

  • repo_key (String, Array<String>)

    Repository key(s)

  • from_date (Time) (defaults to: nil)

    Return artifacts that have not been used since the given date

  • to_date (Time) (defaults to: Time.now)

    Return artifacts that have been created before the given date

Returns:

  • (Hash)

    Artifacts matching search criteria



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/artifactory/client.rb', line 285

def search_creation(repo_key:, from_date: nil, to_date: Time.now)
  ret = []

  path = File.join("/search", "creation")
  params = []
  params << "from=#{(from_date.to_f.round(3) * 1000).to_i}" if from_date
  params << "to=#{(to_date.to_f.round(3) * 1000).to_i}"
  params << "repos=#{repo_key.is_a?(Array) ? repo_key.join(',') : repo_key}"

  api_get([path, params.join('&')].join('?'))['results'].each do |result|
    full_path = result['uri'].scan(/\/storage\/(.+?)(\/.*)/).flatten

    file = {
      "repo_key" => full_path[0],
      "path" => full_path[1]
    }

    result.each do |k, v|
      case k
        when "created"
          file[k] = Time.parse(v)

        else
          file[k] = v
      end
    end

    ret << file
  end

  ret
end

#search_dates(repo_key:, from_date: nil, to_date: Time.now, date_fields:) ⇒ Hash

Get all artifacts with specified dates within the given range

Parameters:

  • repo_key (String, Array<String>)

    Repository key(s)

  • from_date (Time) (defaults to: nil)

    Return artifacts that have not been used since the given date

  • to_date (Time) (defaults to: Time.now)

    Return artifacts that have been created before the given date

  • date_fields (created, lastModified, lastDownloaded)

    Date fields that specify which fields the from_date and to_date values should be applied to

Returns:

  • (Hash)

    Artifacts matching search criteria



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/artifactory/client.rb', line 238

def search_dates(repo_key:, from_date: nil, to_date: Time.now, date_fields:)
  ret = []

  valid_date_fields = ["created", "lastModified", "lastDownloaded"]

  date_fields.each do |date_field|
    raise ValueError, "Not a valid date field '#{date_field}'" unless valid_date_fields.include?(date_field)
  end

  path = File.join("/search", "dates")
  params = []
  params << "from=#{(from_date.to_f.round(3) * 1000).to_i}" if from_date
  params << "to=#{(to_date.to_f.round(3) * 1000).to_i}"
  params << "repos=#{repo_key.is_a?(Array) ? repo_key.join(',') : repo_key}"
  params << "dateFields=#{date_fields.join(',')}"

  api_get([path, params.join('&')].join('?'))['results'].each do |result|
    full_path = result['uri'].scan(/\/storage\/(.+?)(\/.*)/).flatten

    file = {
      "repo_key" => full_path[0],
      "path" => full_path[1]
    }

    result.each do |k, v|
      case k
        when *valid_date_fields
          file[k] = Time.parse(v)

        else
          file[k] = v
      end
    end

    ret << file
  end

  ret
end

#search_pattern(repo_key:, pattern:) ⇒ Hash

Get all artifacts matching the given path pattern

Parameters:

  • repo_key (String)

    Repository key

  • pattern (String)

    File pattern

Returns:

  • (Hash)

    Artifacts matching search pattern



324
325
326
327
328
329
# File 'lib/artifactory/client.rb', line 324

def search_pattern(repo_key:, pattern:)
  path = File.join("/search", "pattern")
  params = ["pattern=#{repo_key}:#{pattern}"]

  api_get([path, params].join('?'))['files']
end

#search_usage(repo_key:, not_used_since:, created_before: nil) ⇒ Hash

Retrieve all artifacts not downloaded since the specified Java epoch in milliseconds

Parameters:

  • repo_key (String, Array<String>)

    Repository key(s)

  • not_used_since (Time)

    Return artifacts that have not been used since the given date

  • created_before (Time) (defaults to: nil)

    Return artifacts that have been created before the given date

Returns:

  • (Hash)

    Artifacts matching search criteria



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/artifactory/client.rb', line 197

def search_usage(repo_key:, not_used_since:, created_before: nil)
  ret = []

  path = File.join("/search", "usage")
  params = []
  params << "notUsedSince=#{(not_used_since.to_f.round(3) * 1000).to_i}"
  params << "createdBefore=#{(created_before.to_f.round(3) * 1000).to_i}" if created_before
  params << "repos=#{repo_key.is_a?(Array) ? repo_key.join(',') : repo_key}"

  api_get([path, params.join('&')].join('?'))['results'].each do |result|
    full_path = result['uri'].scan(/\/storage\/(.+?)(\/.*)/).flatten

    file = {
      "repo_key" => full_path[0],
      "path" => full_path[1]
    }

    result.each do |k, v|
      case k
        when "lastDownloaded", "remoteLastDownloaded"
          file[k] = Time.parse(v)

        else
          file[k] = v
      end
    end

    ret << file
  end

  ret
end