ike-artifactory 0.0.1pre2
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|