ike-artifactory 0.0.1pre2
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/README.md +145 -0
- data/Rakefile +18 -0
- data/bin/cleaner.rb +65 -0
- data/lib/ike_artifactory/client.rb +116 -0
- data/lib/ike_artifactory/docker_cleaner.rb +82 -0
- data/lib/ike_artifactory/exceptions.rb +9 -0
- data/lib/ike_artifactory/version.rb +5 -0
- data/lib/ike_artifactory.rb +6 -0
- metadata +113 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: e54d885ec980d2c49686b6f3395adbf7ab854b433823bd0a4fdf903e9887db8b
|
|
4
|
+
data.tar.gz: e4af791e8b3751311af406bd43d29589de074b7bb2284f81195631782af8dd6e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4fdd3f97640d59e1bd33f1c66d0b16a6fdf94c7c3f76ff7c4b8ae0e8a7190fe7608498f5023f2e89220aa4a955653154e43219949e3cca14ba566ff456297a61
|
|
7
|
+
data.tar.gz: 383af6127fec80f4974c3ba60baafcabe6ceea00a2f514ef588325ff27f85e51b9341ef334b71d86b32d9f6dd0e8909f01ae06521058663a1bb82206a105ab72
|
data/README.md
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# IKE Artifactory
|
|
2
|
+
|
|
3
|
+
This gem provides an object-oriented interface to Artifactory API for managing objects in Artfactory,
|
|
4
|
+
particularly for cleaning up old Docker images.
|
|
5
|
+
|
|
6
|
+
## Classes
|
|
7
|
+
|
|
8
|
+
This gem implements two classes:
|
|
9
|
+
|
|
10
|
+
* `IKE::Artifactory::Client`: Interfaces with the Artifactory API
|
|
11
|
+
* `IKE::Artifactory::DockerCleaner`: Uses `IKE::Artifactory::Client` to implement a single method called `cleanup!` that lets you specify a path in Artifactory that has Docker container images. The `cleanup!` method will delete all images except the following:
|
|
12
|
+
* a list of tags to be excluded (`tags_to_exclude`)
|
|
13
|
+
* any images less than a certain age (`days_old`)
|
|
14
|
+
* any the most recent N images, regardless of age (`most_recent_images`)
|
|
15
|
+
|
|
16
|
+
## Utility scripts
|
|
17
|
+
|
|
18
|
+
Utility scripts that use these classes can be found in the `bin` directory:
|
|
19
|
+
|
|
20
|
+
* `cleaner.rb` - an interface to `IKE::Artifactory::DockerCleaner`; see [README.cleaner.md](README.cleaner.md)
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
Add this line to your application's Gemfile:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
gem 'ike-artifactory-ruby'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
And then execute:
|
|
31
|
+
|
|
32
|
+
$ bundle install
|
|
33
|
+
|
|
34
|
+
Or install it yourself as:
|
|
35
|
+
|
|
36
|
+
$ gem install ike-artifactory-ruby
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
### IKE::Artifactory::Client
|
|
41
|
+
|
|
42
|
+
To create an instance of IKE::Artifactory::Client you will need to provide next parameters:
|
|
43
|
+
* **server**: Artifactory server URL.
|
|
44
|
+
* **repo_key**: Repository in Artifactory server.
|
|
45
|
+
* **user**: Username to be used to access repository.
|
|
46
|
+
* **password**: User's password.
|
|
47
|
+
|
|
48
|
+
#### Example
|
|
49
|
+
```ruby
|
|
50
|
+
require 'ike-artifactory'
|
|
51
|
+
|
|
52
|
+
artifactory_client = IKE::Artifactory::Client.new(
|
|
53
|
+
:server => 'https://artifactory.mydomain.com',
|
|
54
|
+
:repo_key => 'repo-key-example',
|
|
55
|
+
:user => 'Ana',
|
|
56
|
+
:password => 'supersecret'
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
object_info = artifactory_client.get_object_info 'path/to/object'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The output will be a hash with the proprieties of the queried object:
|
|
63
|
+
```ruby
|
|
64
|
+
{"repo"=>"repo-key-example",
|
|
65
|
+
"path"=>"path/to/object",
|
|
66
|
+
"created"=>"2021-05-25T15:27:21.592-07:00",
|
|
67
|
+
"createdBy"=>"some-user",
|
|
68
|
+
"lastModified"=>"2021-05-25T15:27:21.592-07:00",
|
|
69
|
+
"modifiedBy"=>"other-userr",
|
|
70
|
+
"lastUpdated"=>"2021-05-25T15:27:21.592-07:00",
|
|
71
|
+
"children"=>
|
|
72
|
+
[{"uri"=>"/manifest.json", "folder"=>false},
|
|
73
|
+
{"uri"=>
|
|
74
|
+
"/sha256__4f07dd360c1b7e40c438e6437b2044bc31b4f6e5cf36b09a06b0c67e23dfc69d",
|
|
75
|
+
"folder"=>false},
|
|
76
|
+
{"uri"=>
|
|
77
|
+
"/sha256__70fb9965a23f2226fef622992fdf507b8333c61d68259766d4721cc4ba1e5dae",
|
|
78
|
+
"folder"=>false},
|
|
79
|
+
{"uri"=>
|
|
80
|
+
"/sha256__e0f9e11d6f9b3f5af2915fd4839ea0cd268ddccce28a788f54687b6a494770bb",
|
|
81
|
+
"folder"=>false}],
|
|
82
|
+
"uri"=>
|
|
83
|
+
"https://artifactory.mydomain.com:443/artifactory/api/storage/repo-key-example/path/to/object"}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### Methods
|
|
87
|
+
|
|
88
|
+
##### `delete_object(path)`
|
|
89
|
+
Returns `true` if the object pointed by path was successfully deleted, otherwise `false`
|
|
90
|
+
|
|
91
|
+
##### `get_subdirectories(path)`
|
|
92
|
+
Returns a list of subdirectories of the specified `path`.
|
|
93
|
+
|
|
94
|
+
##### `get_object_age(path)`
|
|
95
|
+
Returns the age of the object specified by `path`, or -1 if the age of the object could not be determined (for example, if it does not exist).
|
|
96
|
+
|
|
97
|
+
##### `get_object_info(path)`
|
|
98
|
+
Returns a hash with the proprieties of the queried object.
|
|
99
|
+
|
|
100
|
+
##### `get_subdirectory_ages(path)`
|
|
101
|
+
Returns a hash whose keys are the names of the subdirectories of `path`, and whose values are the `lastModified` age in days of the directory in question.
|
|
102
|
+
|
|
103
|
+
##### `get_images(path)`
|
|
104
|
+
Returns a hash whose keys are the names (tags) of the Docker images found in `path`, and whose values are the age of the Docker image in question. An entry in `path` is considered to be a Docker image if it contains the file identified by the `IKE::Artifactory::Client::IMAGE_MANIFEST` constant, which is `manifest.json`.
|
|
105
|
+
|
|
106
|
+
### IKE::Artifactory::DockerCleaner
|
|
107
|
+
|
|
108
|
+
The constructor arguments of IKE::Artifactory::DockerCleaner are the following:
|
|
109
|
+
* `repo_host`: The URL of the Artifactory host, without the repo key included
|
|
110
|
+
* `repo_key` The repository to be cleaned
|
|
111
|
+
* `folder`: The repository path to be cleaned. `cleanup!` only cleans a single path (directory) and does not recurse
|
|
112
|
+
* `days_old`: The cutoff age for deletion of images. Any images less that `days_old` old will not be cleaned up.
|
|
113
|
+
* `most_recent_images`: The number of most recent container images to keep, regardless of age
|
|
114
|
+
* `tags_to_exclude`: List of Docker container tags to be excluded from deletion, regardless of age
|
|
115
|
+
* `user`: The username to be used to access repository
|
|
116
|
+
* `password`: User's password.
|
|
117
|
+
* `log_level` (optional): Logging verbosity, from the `Logger` Ruby core class. Defaults to ::Logger::INFO.
|
|
118
|
+
* `actually_delete` (optional): Whether to actually delete the images meeting the deletion criteria (truthy) or simply provide output about what would happen (falsy). Defaults to `false`.
|
|
119
|
+
|
|
120
|
+
Returns an array of image tags that would have been deleted (`actually_delete` = `false`) or were deleted (`actually_delete` = `true`):
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
['tag-x', 'tag-y', 'tag-z']
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### Example
|
|
127
|
+
```ruby
|
|
128
|
+
require 'ike-artifactory'
|
|
129
|
+
|
|
130
|
+
images_to_delete = IKE::Artifactory::DockerCleaner.new(
|
|
131
|
+
:server => 'https://artifactory.mydomain.com',
|
|
132
|
+
:repo_key => 'repo-key-example',
|
|
133
|
+
:folder => 'path/to/folder',
|
|
134
|
+
:days_old => 30,
|
|
135
|
+
:most_recent_images => 5,
|
|
136
|
+
:tags_to_exclude => ['tag1', 'tag2', 'tag3'],
|
|
137
|
+
:user => 'Ana',
|
|
138
|
+
:password => 'supersecret'
|
|
139
|
+
).cleanup!
|
|
140
|
+
|
|
141
|
+
puts "Not actually deleting images, but if I did I would have deleted these:"
|
|
142
|
+
images_to_delete.each do |i|
|
|
143
|
+
puts " #{i}"
|
|
144
|
+
end
|
|
145
|
+
```
|
data/Rakefile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'bundler/gem_tasks'
|
|
8
|
+
require 'rake/testtask'
|
|
9
|
+
|
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
|
11
|
+
t.libs << 'lib'
|
|
12
|
+
t.libs << 'test'
|
|
13
|
+
t.pattern = 'test/**/*_test.rb'
|
|
14
|
+
t.verbose = false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
task default: :test
|
data/bin/cleaner.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!env ruby
|
|
2
|
+
|
|
3
|
+
$:.unshift(File.expand_path('../../lib', __FILE__))
|
|
4
|
+
|
|
5
|
+
require 'ike_artifactory'
|
|
6
|
+
|
|
7
|
+
actually_delete = false
|
|
8
|
+
if ARGV[0] == '--actually-delete'
|
|
9
|
+
ARGV.shift
|
|
10
|
+
actually_delete = true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
unless [7,8].include?(ARGV.count)
|
|
14
|
+
STDERR.puts "Usage: $0 [--actually-delete] artifactory_url repo_key username password application_list image_exclude_list days_to_keep [most_recent_images_to_keep]"
|
|
15
|
+
exit 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
artifactory_url = ARGV.shift
|
|
19
|
+
repo_key = ARGV.shift
|
|
20
|
+
user = ARGV.shift
|
|
21
|
+
password = ARGV.shift
|
|
22
|
+
application_list = ARGV.shift
|
|
23
|
+
image_exclude_list = ARGV.shift
|
|
24
|
+
days_to_keep = ARGV.shift.to_i
|
|
25
|
+
most_recent_images_to_keep = ARGV.shift.to_i || 10
|
|
26
|
+
|
|
27
|
+
if days_to_keep <= 7
|
|
28
|
+
STDERR.puts "Invalid number of days_to_keep: #{days_to_keep}"
|
|
29
|
+
exit 2
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
apps = File.readlines(application_list).map { |line| line.chomp }
|
|
33
|
+
|
|
34
|
+
unless apps.count
|
|
35
|
+
STDERR.puts "No applications listed in #{application_list}, quitting"
|
|
36
|
+
exit 2
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
images_to_keep = File.readlines(image_exclude_list).each_with_object({}) do |line, keep|
|
|
40
|
+
parts = line.chomp.split(/:/)
|
|
41
|
+
if parts.length == 2
|
|
42
|
+
keep[parts[0]] ||= []
|
|
43
|
+
keep[parts[0]] << parts[1]
|
|
44
|
+
else
|
|
45
|
+
STDERR.puts "Can't parse #{line} as image to keep, aborting"
|
|
46
|
+
exit 3
|
|
47
|
+
end
|
|
48
|
+
keep
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
apps.each do |app|
|
|
52
|
+
puts "Cleaning #{app}"
|
|
53
|
+
cleaner = IKE::Artifactory::DockerCleaner.new(
|
|
54
|
+
actually_delete: actually_delete,
|
|
55
|
+
repo_host: artifactory_url,
|
|
56
|
+
repo_key: repo_key,
|
|
57
|
+
folder: app,
|
|
58
|
+
days_old: days_to_keep,
|
|
59
|
+
tags_to_exclude: images_to_keep[app],
|
|
60
|
+
user: user,
|
|
61
|
+
password: password,
|
|
62
|
+
most_recent_images: most_recent_images_to_keep
|
|
63
|
+
)
|
|
64
|
+
cleaner.cleanup!
|
|
65
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'rest-client'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'pry-byebug'
|
|
6
|
+
|
|
7
|
+
module IKE
|
|
8
|
+
module Artifactory
|
|
9
|
+
class Client
|
|
10
|
+
|
|
11
|
+
IMAGE_MANIFEST = 'manifest.json'
|
|
12
|
+
|
|
13
|
+
attr_accessor :server
|
|
14
|
+
attr_accessor :repo_key
|
|
15
|
+
attr_accessor :folder_path
|
|
16
|
+
attr_accessor :user
|
|
17
|
+
attr_accessor :password
|
|
18
|
+
|
|
19
|
+
def initialize(**args)
|
|
20
|
+
@server = args[:server]
|
|
21
|
+
@repo_key = args[:repo_key]
|
|
22
|
+
@user = args[:user]
|
|
23
|
+
@password = args[:password]
|
|
24
|
+
|
|
25
|
+
raise IKEArtifactoryClientNotReady.new(msg = 'Required attributes are missing. IKEArtifactoryGem not ready.') unless self.ready?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def delete_object(path)
|
|
29
|
+
fetch(path, method: :delete) do |response, request, result|
|
|
30
|
+
response.code == 204
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def get_subdirectories(path)
|
|
35
|
+
get(path) do |response|
|
|
36
|
+
(response['children'] || []).select do |c|
|
|
37
|
+
c['folder']
|
|
38
|
+
end.map do |f|
|
|
39
|
+
f['uri'][1..]
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def get_object_age(path)
|
|
45
|
+
get(path) do |response|
|
|
46
|
+
( ( Time.now - Time.iso8601(response['lastModified']) ) / (24*60*60) ).to_int
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def get_object_info(path)
|
|
51
|
+
get(path)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def get_subdirectory_ages(path)
|
|
55
|
+
get(path, prefix: "#{server}:443/ui/api/v1/ui/nativeBrowser/#{repo_key}") do |response|
|
|
56
|
+
(response['children'] || []).each_with_object({}) do |child, memo|
|
|
57
|
+
days_old = ( ( Time.now.to_i - (child['lastModified']/1000) ) / (24*60*60) ).to_int
|
|
58
|
+
memo[child['name']] = days_old
|
|
59
|
+
memo
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def get_images(path)
|
|
65
|
+
get_subdirectory_ages(path).select do |(folder, _age)|
|
|
66
|
+
get_object_info([path, folder, IMAGE_MANIFEST].join('/'))
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def ready?
|
|
73
|
+
if ([server, repo_key].include? nil ) || ([user, password].include? nil )
|
|
74
|
+
return false
|
|
75
|
+
end
|
|
76
|
+
true
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def fetch(path, method: :get, prefix: nil)
|
|
80
|
+
retval = nil # Work around Object#stub stomping on return values
|
|
81
|
+
|
|
82
|
+
prefix ||= "#{server}/artifactory/api/storage/#{repo_key}"
|
|
83
|
+
|
|
84
|
+
RestClient::Request.execute(
|
|
85
|
+
:method => method,
|
|
86
|
+
:url => "#{prefix}/#{path}",
|
|
87
|
+
:user => user,
|
|
88
|
+
:password => password
|
|
89
|
+
) do |response, request, result|
|
|
90
|
+
retval =
|
|
91
|
+
if block_given?
|
|
92
|
+
yield response, request, result
|
|
93
|
+
else
|
|
94
|
+
[response, request, result]
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
retval
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def get(path, prefix: nil)
|
|
102
|
+
fetch(path, prefix: prefix) do |response, request, result|
|
|
103
|
+
if response.code == 200
|
|
104
|
+
obj = JSON.parse(response.to_str)
|
|
105
|
+
if block_given?
|
|
106
|
+
yield obj
|
|
107
|
+
else
|
|
108
|
+
obj
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'logger'
|
|
3
|
+
|
|
4
|
+
module IKE
|
|
5
|
+
module Artifactory
|
|
6
|
+
|
|
7
|
+
class DockerCleaner
|
|
8
|
+
attr_accessor :repo_host
|
|
9
|
+
attr_accessor :repo_key
|
|
10
|
+
attr_accessor :folder
|
|
11
|
+
attr_accessor :days_old
|
|
12
|
+
attr_accessor :tags_to_exclude
|
|
13
|
+
|
|
14
|
+
attr_reader :client # is not tested
|
|
15
|
+
attr_reader :most_recent_images # is not tested
|
|
16
|
+
attr_reader :logger # is not tested. Used for testing
|
|
17
|
+
attr_reader :actually_delete
|
|
18
|
+
|
|
19
|
+
def initialize(repo_host:, repo_key:, folder:, days_old:,
|
|
20
|
+
tags_to_exclude:, user:, password:, most_recent_images:,
|
|
21
|
+
log_level: ::Logger::INFO, actually_delete: false)
|
|
22
|
+
|
|
23
|
+
@repo_host = repo_host
|
|
24
|
+
@repo_key = repo_key
|
|
25
|
+
@folder = folder
|
|
26
|
+
@days_old = days_old
|
|
27
|
+
@tags_to_exclude = tags_to_exclude || []
|
|
28
|
+
@most_recent_images = most_recent_images
|
|
29
|
+
|
|
30
|
+
@actually_delete = actually_delete
|
|
31
|
+
|
|
32
|
+
@client = IKE::Artifactory::Client.new(
|
|
33
|
+
:server => repo_host,
|
|
34
|
+
:repo_key => repo_key,
|
|
35
|
+
:user => user,
|
|
36
|
+
:password => password
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
@logger = Logger.new(STDOUT)
|
|
40
|
+
logger.level = log_level
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def cleanup!
|
|
44
|
+
deleted_images = []
|
|
45
|
+
tags = client.get_images(folder).sort_by { |_k,v| v }.to_h
|
|
46
|
+
|
|
47
|
+
too_new_to_delete = tags.keys[0...most_recent_images]
|
|
48
|
+
|
|
49
|
+
logger_prefix = "#{repo_host}/#{repo_key}"
|
|
50
|
+
|
|
51
|
+
tags.each do | tag, tag_days_old |
|
|
52
|
+
|
|
53
|
+
logger.debug "#{logger_prefix}: examining #{tag}"
|
|
54
|
+
|
|
55
|
+
if tags_to_exclude.include?(tag)
|
|
56
|
+
logger.info "#{logger_prefix}: tag #{tag} is explicitly excluded from cleanup"
|
|
57
|
+
next
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if too_new_to_delete.include?(tag)
|
|
61
|
+
logger.info "#{logger_prefix}: tag #{tag} is one of the #{most_recent_images} most recent tags, preserving"
|
|
62
|
+
next
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if tag_days_old < days_old
|
|
66
|
+
logger.info "#{logger_prefix}: tag #{tag} is less than #{days_old} days old, preserving"
|
|
67
|
+
next
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
logger.info "#{logger_prefix}: removing tag #{tag}"
|
|
71
|
+
if actually_delete
|
|
72
|
+
client.delete_object "#{folder}/#{tag}"
|
|
73
|
+
else
|
|
74
|
+
logger.info("#{logger_prefix}: Not actually deleting #{tag} because actually_delete is falsy")
|
|
75
|
+
end
|
|
76
|
+
deleted_images.append(tag)
|
|
77
|
+
end
|
|
78
|
+
deleted_images
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ike-artifactory
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1pre2
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nick Marden
|
|
8
|
+
- Jack Newton
|
|
9
|
+
- Vicente Ramos Garcia
|
|
10
|
+
autorequire:
|
|
11
|
+
bindir: bin
|
|
12
|
+
cert_chain: []
|
|
13
|
+
date: 2021-11-10 00:00:00.000000000 Z
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: rake
|
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
|
18
|
+
requirements:
|
|
19
|
+
- - ">="
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '0'
|
|
29
|
+
- !ruby/object:Gem::Dependency
|
|
30
|
+
name: rest-client
|
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
|
32
|
+
requirements:
|
|
33
|
+
- - ">="
|
|
34
|
+
- !ruby/object:Gem::Version
|
|
35
|
+
version: '0'
|
|
36
|
+
type: :runtime
|
|
37
|
+
prerelease: false
|
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
39
|
+
requirements:
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: '0'
|
|
43
|
+
- !ruby/object:Gem::Dependency
|
|
44
|
+
name: minitest
|
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '0'
|
|
50
|
+
type: :development
|
|
51
|
+
prerelease: false
|
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: '0'
|
|
57
|
+
- !ruby/object:Gem::Dependency
|
|
58
|
+
name: pry-byebug
|
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '0'
|
|
64
|
+
type: :development
|
|
65
|
+
prerelease: false
|
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '0'
|
|
71
|
+
description: Ruby gem for managing objects in Artfactory, particularly for cleaning
|
|
72
|
+
up old Docker images
|
|
73
|
+
email:
|
|
74
|
+
- nmarden@avvo.com
|
|
75
|
+
- jnewton@avvo.com
|
|
76
|
+
- vramosgarcia@avvo.com
|
|
77
|
+
executables: []
|
|
78
|
+
extensions: []
|
|
79
|
+
extra_rdoc_files: []
|
|
80
|
+
files:
|
|
81
|
+
- README.md
|
|
82
|
+
- Rakefile
|
|
83
|
+
- bin/cleaner.rb
|
|
84
|
+
- lib/ike_artifactory.rb
|
|
85
|
+
- lib/ike_artifactory/client.rb
|
|
86
|
+
- lib/ike_artifactory/docker_cleaner.rb
|
|
87
|
+
- lib/ike_artifactory/exceptions.rb
|
|
88
|
+
- lib/ike_artifactory/version.rb
|
|
89
|
+
homepage: https://github.com/internetbrands/ike-artifactory-ruby
|
|
90
|
+
licenses:
|
|
91
|
+
- MIT
|
|
92
|
+
metadata:
|
|
93
|
+
allowed_push_host: https://rubygems.org
|
|
94
|
+
post_install_message:
|
|
95
|
+
rdoc_options: []
|
|
96
|
+
require_paths:
|
|
97
|
+
- lib
|
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
|
+
requirements:
|
|
105
|
+
- - ">"
|
|
106
|
+
- !ruby/object:Gem::Version
|
|
107
|
+
version: 1.3.1
|
|
108
|
+
requirements: []
|
|
109
|
+
rubygems_version: 3.1.6
|
|
110
|
+
signing_key:
|
|
111
|
+
specification_version: 4
|
|
112
|
+
summary: Provides an object-oriented interface to Artifactory API.
|
|
113
|
+
test_files: []
|