Class: Artifactory::Cleaner::CLI

Inherits:
Thor
  • Object
show all
Defined in:
lib/artifactory/cleaner/cli.rb

Overview

Command Line Interface class, powers the artifactory-cleaner terminal command


A single Artifactory::Cleaner::CLI instance is created by the bin/artifactory_cleaner command for parsing options and executing the command specified by the user. The Artifactory::Cleaner::CLI uses Thor to provide git command/subcommand style ARGV parsing

See Also:

Defined Under Namespace

Classes: RepoTableCol

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ CLI

Constructor for a new CLI interface



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/artifactory/cleaner/cli.rb', line 54

def initialize(*args)
  super
  @config = {}
  begin
    load_conf_file options[:conf_file] if options[:conf_file]
  rescue => ex
    STDERR.puts "Unable to load config from #{options[:conf_file]}: #{ex}"
    exit Sysexits::EX_DATAERR
  end
  @artifactory_config = {
     endpoint: options[:endpoint] || @config['endpoint'],
     api_key: options[:api_key] || @config['api-key'],
  }
  @repo_table_cols = Artifactory::Cleaner::CLI.repo_table_cols
  #invoke :create_controller
  create_controller
end

Class Method Details

.default_repo_table_colsObject



48
49
50
# File 'lib/artifactory/cleaner/cli.rb', line 48

def self.default_repo_table_cols
  [:key, :package_type, :rclass, :url, :description]
end

.repo_table_colsObject



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/artifactory/cleaner/cli.rb', line 26

def self.repo_table_cols
  [
    RepoTableCol.new(:key, 'ID', nil),
    RepoTableCol.new(:package_type, 'Type', nil),
    RepoTableCol.new(:rclass, 'Class', :local),
    RepoTableCol.new(:url, 'URL', :remote),
    RepoTableCol.new(:description, 'Description', nil),
    RepoTableCol.new(:notes, 'Notes', nil),
    RepoTableCol.new(:blacked_out?, 'Blacked Out', nil),
    RepoTableCol.new(:yum_root_depth, 'YUM Root Depth', nil),
    RepoTableCol.new(:checksum_policy_type, 'Checksum Policy', nil),
    RepoTableCol.new(:includes_pattern, 'Includes Pattern', nil),
    RepoTableCol.new(:excludes_pattern, 'Excludes Pattern', nil),
    RepoTableCol.new(:handle_releases, 'Releases', nil),
    RepoTableCol.new(:handle_snapshots, 'Snapshots', nil),
    RepoTableCol.new(:property_sets, 'Property Sets', nil),
    RepoTableCol.new(:repo_layout_ref, 'Layout', nil),
    RepoTableCol.new(:repositories, 'Included Repos', nil),
    RepoTableCol.new(:inspect, 'Inspection'),
  ]
end

Instance Method Details

#archiveObject

Download artifacts meeting specific criteria

WARNING: This method will cause the ‘last_downloaded` property of all the matching artifacts to be updated; therefore, using this method with a `last_used_before` switch may not be idempotent as it will cause the set of artifacts matching the search to change

Consider using ‘clean –archive` instead



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/artifactory/cleaner/cli.rb', line 175

def archive
  dates = parse_date_options
  filter = load_artifact_filter
  archive_to = parse_archive_option
  if archive_to.nil?
    STDERR.puts "Missing required `--archive-to` option specifying a a valid, existing directory under which to store archived artifacts"
    exit Sysexits::EX_USAGE
  end

  report = {
      archived: {
          artifact_count: 0,
          bytes: 0
      },
      skipped: {
          artifact_count: 0,
          bytes: 0
      }
  }

  @controller.with_discovered_artifacts(from: dates[:from], to: dates[:to], repos: options[:repos], threads: options[:threads]) do |artifact|
    if artifact_meets_criteria(artifact, dates, filter)
      if options.dry_run?
        STDERR.puts "Would archive #{artifact} to #{archive_to}"
      else
        @controller.archive_artifact artifact, archive_to
      end

      report[:archived][:artifact_count] += 1
      report[:archived][:bytes] += artifact.size
    else
      STDERR.puts "[DEBUG] Skipped #{artifact.inspect} because it did not meet the criteria" if options.verbose?
      report[:skipped][:artifact_count] += 1
      report[:skipped][:bytes] += artifact.size
    end
  end
  report.each do |key,values|
    puts "#{key} #{values[:artifact_count]} artifacts totaling #{Util.filesize values[:bytes]}"
  end
end

#cleanObject

Delete artifacts meeting specific criteria

Clean up an Artifactory instance by deleting old, unused artifacts which meet given criteria

This is a CLI interface to Artifactory::Cleaner’s primary function: deleting artifacts which have not been used in a long time (or which meet other criteria, determined by the powerful regex-based filters)



234
235
236
237
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
277
278
279
280
281
282
283
284
285
286
# File 'lib/artifactory/cleaner/cli.rb', line 234

def clean
  dates = parse_date_options
  filter = load_artifact_filter
  archive_to = parse_archive_option

  # Ready to locate and delete artifacts
  report = {
      deleted: {
          artifact_count: 0,
          bytes: 0
      },
      archived: {
          artifact_count: 0,
          bytes: 0
      },
      skipped: {
          artifact_count: 0,
          bytes: 0
      }
  }

  STDERR.puts "[DEBUG] controller.bucketize_artifacts from #{dates[:from]} to #{dates[:to]} repos #{options[:repos]}" if options.verbose?
  @controller.with_discovered_artifacts(from: dates[:from], to: dates[:to], repos: options[:repos], threads: options[:threads]) do |artifact|
    if artifact_meets_criteria(artifact, dates, filter)
      if archive_to
        if options.dry_run?
          STDERR.puts "Would archive #{artifact} to #{archive_to}"
        else
          @controller.archive_artifact artifact, archive_to
        end

        report[:archived][:artifact_count] += 1
        report[:archived][:bytes] += artifact.size
      end

      if options.dry_run?
        STDERR.puts "Would delete #{artifact}"
      else
        @controller.delete_artifact artifact
      end

      report[:deleted][:artifact_count] += 1
      report[:deleted][:bytes] += artifact.size
    else
      STDERR.puts "[DEBUG] Skipped #{artifact.inspect} because it did not meet the criteria" if options.verbose?
      report[:skipped][:artifact_count] += 1
      report[:skipped][:bytes] += artifact.size
    end
  end
  report.each do |key,values|
    puts "#{key} #{values[:artifact_count]} artifacts totaling #{Util.filesize values[:bytes]}"
  end
end

#list_reposObject

List all available repos



89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/artifactory/cleaner/cli.rb', line 89

def list_repos()
  repo_info_table = []
  repos = @controller.discover_repos
  repo_kinds = []
  repo_kinds << :local if options.local?
  repo_kinds << :remote if options.remote?
  repo_kinds << :virtual if options.virtual?
  include_cols = get_repo_cols(repo_kinds)
  repos[:local].each {|k, r| repo_info_table << repo_cols(r, include_cols)} if options.local?
  repos[:remote].each {|k, r| repo_info_table << repo_cols(r, include_cols)} if options.remote?
  repos[:virtual].each {|k, r| repo_info_table << repo_cols(r, include_cols)} if options.virtual?
  print_repo_list repo_info_table, include_cols
end

#usage_reportObject

Analyze usage and report where space is used



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/artifactory/cleaner/cli.rb', line 112

def usage_report
  begin
    from = Time.parse(options[:from])
    to = Time.parse(options[:to])
  rescue => ex
    STDERR.puts "Unable to parse time format. Please use: YYYY-MM-DD HH:II:SS"
    STDERR.puts ex
    exit Sysexits::EX_USAGE
  end

  begin
    STDERR.puts "[DEBUG] controller.bucketize_artifacts from #{from} to #{to} repos #{options[:repos]}" if options.verbose?
    buckets = @controller.bucketize_artifacts(
        from: from,
        to: to,
        repos: options[:repos],
        threads: options[:threads],
    )

    @controller.bucketized_artifact_report(buckets).each { |l| STDERR.puts l }
    if options.details?
      puts "# Detailed Bucket Report:"
      puts "buckets:"
      buckets.each do |bucket|
        puts "#--  #{bucket.length} artifacts between #{bucket.min} and #{bucket.max} days old repo_info_table #{bucket.filesize} bytes --"
        puts "  - min: #{bucket.min} # days old"
        puts "    max: #{bucket.max} # days old"
        if bucket.empty?
          puts "    artifacts: []"
        else
          puts "    artifacts:"
          bucket.each { |pkg| puts "    - #{@controller.yaml_format(pkg,6)}" }
        end
      end
    end
  rescue => err
    STDERR.puts "An exception occured while generating the usage report: #{err}"
    STDERR.puts err.full_message
    STDERR.puts "Caused by: #{err.cause.full_message}" if err.cause
    Pry::rescued(err) if defined?(Pry::rescue)
    exit Sysexits::EX_UNAVAILABLE
  end
end

#versionObject

Show version information



75
76
77
78
# File 'lib/artifactory/cleaner/cli.rb', line 75

def version
  STDERR.puts "Artifactory::Cleaner version #{Artifactory::Cleaner::VERSION}"
  STDERR.puts "Copyright (C) 2020 Pinnacle 21, inc. All Rights Reserved"
end