bosh_cli 1.3232.24.0 → 1.3262.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c71f4dfaeff471cb81968a20e376da09e8609cfa
4
- data.tar.gz: 4163600dbad95ff0513dfc74ce77552b71f35599
3
+ metadata.gz: 59759f7adc2372786190b96dd92b8db80cfeb884
4
+ data.tar.gz: ab19243126537de87c1f21492263431e46988c82
5
5
  SHA512:
6
- metadata.gz: ddc0eebf3cea4efd3b284be7a92c48ce3153b71dd013a419addb8e290419121902ea41a128a4d1d37fd6053e08fdc8fcddc8d7d38d61eaa075a092c195d6ec39
7
- data.tar.gz: 8d6a4f9c8121ffe0937c934dafc0ace23080749ad1dbd799fe9d45008d5534f771bcb9ecdab251ae24eaba0da13c9b454c1d3a0cb66b38753b26605cd0585610
6
+ metadata.gz: 55743026aee4ccdc7bb6ea7b2d1d3136c41c09c7501ca07b490619293ce4caffb4b211a076450a77ae8792d7b6836183d40c4ec3859492f28a56fb3f2c8acb15
7
+ data.tar.gz: c2eac49e1473c6efe3d7d0066b6c5b5ffef83cc35fb6174af430771d4b0b5648a1b1d75af164b66e2a9c53e725068f3f0b49cdbd625f55d563f3633792c7efb3
@@ -13,11 +13,6 @@ module Bosh
13
13
  def authorization_header
14
14
  @token_provider.token
15
15
  end
16
-
17
- def refresh
18
- @token_provider.refresh
19
- true
20
- end
21
16
  end
22
17
 
23
18
  class BasicCredentials
@@ -33,10 +28,6 @@ module Bosh
33
28
  def authorization_header
34
29
  'Basic ' + Base64.encode64("#{@username}:#{@password}").strip
35
30
  end
36
-
37
- def refresh
38
- false
39
- end
40
31
  end
41
32
  end
42
33
  end
@@ -29,7 +29,7 @@ module Bosh
29
29
  end
30
30
 
31
31
  @director_uri = URI.parse(director_uri)
32
- @director_host = @director_uri.host
32
+ @director_ip = Resolv.getaddresses(@director_uri.host).last
33
33
  @scheme = @director_uri.scheme
34
34
  @port = @director_uri.port
35
35
  @credentials = credentials
@@ -127,7 +127,9 @@ module Bosh
127
127
  def list_events(options={})
128
128
  query_string = "/events"
129
129
  delimeter = "?"
130
- [:before_id, :deployment, :instance, :task].each do |param|
130
+ options[:before_time] = URI.encode(options.delete(:before)) if options[:before]
131
+ options[:after_time] = URI.encode(options.delete(:after)) if options[:after]
132
+ [:before_id, :deployment, :instance, :task, :before_time, :after_time].each do |param|
131
133
  if options[param]
132
134
  query_string += "#{delimeter}#{ param.to_s}=#{options[param]}"
133
135
  delimeter = "&"
@@ -268,6 +270,10 @@ module Bosh
268
270
  request_and_track(:delete, add_query_string(url, extras), options)
269
271
  end
270
272
 
273
+ def delete_vm_by_cid(vm_cid)
274
+ request_and_track(:delete, "/vms/#{vm_cid}")
275
+ end
276
+
271
277
  def deploy(manifest_yaml, options = {})
272
278
  options = options.dup
273
279
 
@@ -353,11 +359,15 @@ module Bosh
353
359
  options = options.dup
354
360
 
355
361
  skip_drain = !!options.delete(:skip_drain)
362
+ canaries = options.delete(:canaries)
363
+ max_in_flight = options.delete(:max_in_flight)
356
364
 
357
365
  url = "/deployments/#{deployment_name}/jobs/#{job}"
358
366
  url += "/#{index_or_id}" if index_or_id
359
367
  url += "?state=#{new_state}"
360
368
  url += "&skip_drain=true" if skip_drain
369
+ url += "&max_in_flight=#{max_in_flight}" if max_in_flight
370
+ url += "&canaries=#{canaries}" if canaries
361
371
 
362
372
  options[:payload] = manifest_yaml
363
373
  options[:content_type] = 'text/yaml'
@@ -377,6 +387,12 @@ module Bosh
377
387
  put(url, 'application/json', payload)
378
388
  end
379
389
 
390
+ def change_instance_ignore_state(deployment_name, instance_group_name, id, ignore_state)
391
+ url = "/deployments/#{deployment_name}/instance_groups/#{instance_group_name}/#{id}/ignore"
392
+ payload = JSON.generate('ignore' => ignore_state)
393
+ put(url, 'application/json', payload)
394
+ end
395
+
380
396
  def fetch_logs(deployment_name, job_name, index, log_type,
381
397
  filters = nil, options = {})
382
398
  options = options.dup
@@ -760,7 +776,7 @@ module Bosh
760
776
 
761
777
  response = try_to_perform_http_request(
762
778
  method,
763
- "#{@scheme}://#{@director_host}:#{@port}#{uri}",
779
+ "#{@scheme}://#{@director_ip}:#{@port}#{uri}",
764
780
  payload,
765
781
  headers,
766
782
  num_retries,
@@ -865,32 +881,14 @@ module Bosh
865
881
  end
866
882
 
867
883
  if @credentials
868
- @credentials.refresh unless payload.nil?
869
884
  headers['Authorization'] = @credentials.authorization_header
870
885
  end
871
886
 
872
- response = http_client.request(method, uri, {
887
+ http_client.request(method, uri, {
873
888
  :body => payload,
874
889
  :header => headers,
875
890
  }, &block)
876
891
 
877
- if !response.nil? && response.code == 401
878
- if !payload.nil?
879
- return response
880
- end
881
-
882
- if @credentials.nil? || !@credentials.refresh
883
- raise AuthError
884
- end
885
-
886
- headers['Authorization'] = @credentials.authorization_header
887
- response = http_client.request(method, uri, {
888
- :body => payload,
889
- :header => headers,
890
- }, &block)
891
- end
892
-
893
- response
894
892
  rescue URI::Error,
895
893
  SocketError,
896
894
  Errno::ECONNREFUSED,
@@ -17,22 +17,17 @@ module Bosh
17
17
  access_info.auth_header if access_info
18
18
  end
19
19
 
20
- def refresh
21
- get_access_info(true)
22
- nil
23
- end
24
-
25
20
  def username
26
21
  get_access_info.username
27
22
  end
28
23
 
29
24
  private
30
25
 
31
- def get_access_info(force_refresh = false)
26
+ def get_access_info
32
27
  if @auth_info.client_auth?
33
- client_access_info(force_refresh)
28
+ client_access_info
34
29
  else
35
- password_access_info(force_refresh)
30
+ password_access_info
36
31
  end
37
32
  end
38
33
 
@@ -40,28 +35,26 @@ module Bosh
40
35
  @uaa_client ||= Bosh::Cli::Client::Uaa::Client.new(@target, @auth_info, @config)
41
36
  end
42
37
 
43
- def client_access_info(force_refresh = false)
44
- if !@access_info.nil? && @access_info.was_issued_for?(@auth_info.client_id)
45
- @access_info = refresh_if_needed(@access_info, force_refresh)
38
+ def client_access_info
39
+ if !@client_access_info.nil? && @client_access_info.was_issued_for?(@auth_info.client_id)
40
+ @client_access_info = refresh_if_needed(@client_access_info)
46
41
  else
47
- @access_info = uaa_client.access_info({})
42
+ @client_access_info = uaa_client.access_info({})
48
43
  end
49
44
  end
50
45
 
51
- def password_access_info(force_refresh = false)
52
- if @access_info.nil?
53
- config_access_token = @config.access_token(@target)
54
- return nil unless config_access_token
46
+ def password_access_info
47
+ config_access_token = @config.access_token(@target)
48
+ return nil unless config_access_token
55
49
 
56
- @access_info = PasswordAccessInfo.create(config_access_token, @config.refresh_token(@target), @token_decoder)
57
- return nil unless @access_info
58
- end
50
+ access_info = PasswordAccessInfo.create(config_access_token, @config.refresh_token(@target), @token_decoder)
51
+ return nil unless access_info
59
52
 
60
- @access_info = refresh_if_needed(@access_info, force_refresh)
53
+ refresh_if_needed(access_info)
61
54
  end
62
55
 
63
- def refresh_if_needed(access_info, force_refresh = false)
64
- if access_info.expires_soon? || force_refresh
56
+ def refresh_if_needed(access_info)
57
+ if access_info.expires_soon?
65
58
  uaa_client.refresh(access_info)
66
59
  else
67
60
  access_info
@@ -3,10 +3,11 @@ module Bosh::Cli::Command
3
3
  usage 'events'
4
4
  desc 'Show all deployment events'
5
5
  option '--before-id id', Integer, 'Show all events with id less or equal to given id'
6
- option '--deployment name', String, 'filter all events by the Deployment Name'
7
- option '--task id', String, 'filter all events by the task id'
8
- option '--instance job_name/id', String, 'filter all events by the instance job_name/id'
9
-
6
+ option '--before timestamp', String, 'Show all events by the given timestamp (ex: 2016-05-08 17:26:32)'
7
+ option '--after timestamp', String, 'Show all events after the given timestamp (ex: 2016-05-08 17:26:32)'
8
+ option '--deployment name', String, 'Filter all events by the Deployment Name'
9
+ option '--task id', String, 'Filter all events by the task id'
10
+ option '--instance job_name/id', String, 'Filter all events by the instance job_name/id'
10
11
 
11
12
  def list
12
13
  auth_required
@@ -0,0 +1,31 @@
1
+ require 'cli/name_id_pair'
2
+
3
+ module Bosh::Cli::Command
4
+ class Ignore < Base
5
+
6
+ usage "ignore instance"
7
+ desc "Ignore an instance. 'name_and_id' should be in the form of {name}/{id}"
8
+ def ignore(name_and_id)
9
+ change_ignore_state(name_and_id, true)
10
+ end
11
+
12
+ usage "unignore instance"
13
+ desc "Unignore an instance. 'name_and_id' should be in the form of {name}/{id}"
14
+ def unignore(name_and_id)
15
+ change_ignore_state(name_and_id, false)
16
+ end
17
+
18
+ private
19
+
20
+ def change_ignore_state(name_and_id, desired_state)
21
+ auth_required
22
+ deployment_required
23
+
24
+ instance_pair = Bosh::Cli::NameIdPair.parse(name_and_id)
25
+ manifest = prepare_deployment_manifest(show_state: true)
26
+
27
+ director.change_instance_ignore_state(manifest.name, instance_pair.name, instance_pair.id, desired_state)
28
+ end
29
+
30
+ end
31
+ end
@@ -79,7 +79,7 @@ module Bosh::Cli::Command
79
79
  if has_disk_cid
80
80
  headings += ['Disk CID']
81
81
  end
82
- headings += ['Agent ID', 'Resurrection']
82
+ headings += ['Agent ID', 'Resurrection', 'Ignore']
83
83
  end
84
84
 
85
85
  if options[:dns]
@@ -155,11 +155,9 @@ module Bosh::Cli::Command
155
155
  display_table << :separator if row_count.between?(2, instance_count) && (options[:ps] || last_job != '' && instance['job_name'] != last_job)
156
156
 
157
157
  if options[:details]
158
- if has_disk_cid
159
- row += [instance['vm_cid'], instance['disk_cid'] || 'n/a', instance['agent_id'], instance['resurrection_paused'] ? 'paused' : 'active']
160
- else
161
- row += [instance['vm_cid'], instance['agent_id'], instance['resurrection_paused'] ? 'paused' : 'active']
162
- end
158
+ row << instance['vm_cid']
159
+ row << (instance['disk_cid'] || 'n/a') if has_disk_cid
160
+ row += [instance['agent_id'], instance['resurrection_paused'] ? 'paused' : 'active', instance['ignore'].nil? ? 'n/a' : instance['ignore']]
163
161
  end
164
162
 
165
163
  if options[:dns]
@@ -6,11 +6,16 @@ module Bosh::Cli
6
6
  class JobManagement < Base
7
7
  FORCE = 'Proceed even when there are other manifest changes'
8
8
  SKIP_DRAIN = 'Skip running drain script'
9
+ MAX_IN_FLIGHT = 'Overwrites max_in_flight value in the manifest'
10
+ CANARIES = 'Overwrites canaries value in the manifest'
11
+
9
12
 
10
13
  # bosh start
11
14
  usage 'start'
12
15
  desc 'Start all jobs/job/instance'
13
16
  option '--force', FORCE
17
+ option '--max-in-flight MAX_IN_FLIGHT', MAX_IN_FLIGHT
18
+ option '--canaries CANARIES', CANARIES
14
19
  def start_job(job = '*', index_or_id = nil)
15
20
  change_job_state(:start, job, index_or_id)
16
21
  end
@@ -19,8 +24,10 @@ module Bosh::Cli
19
24
  usage 'stop'
20
25
  desc 'Stop all jobs/job/instance'
21
26
  option '--soft', 'Stop process only'
22
- option '--hard', 'Power off VM'
27
+ option '--hard', 'Delete the VM'
23
28
  option '--force', FORCE
29
+ option '--max-in-flight MAX_IN_FLIGHT', MAX_IN_FLIGHT
30
+ option '--canaries CANARIES', CANARIES
24
31
  option '--skip-drain', SKIP_DRAIN
25
32
  def stop_job(job = '*', index_or_id = nil)
26
33
  if hard?
@@ -34,6 +41,8 @@ module Bosh::Cli
34
41
  usage 'restart'
35
42
  desc 'Restart all jobs/job/instance (soft stop + start)'
36
43
  option '--force', FORCE
44
+ option '--max-in-flight MAX_IN_FLIGHT', MAX_IN_FLIGHT
45
+ option '--canaries CANARIES', CANARIES
37
46
  option '--skip-drain', SKIP_DRAIN
38
47
  def restart_job(job = '*', index_or_id = nil)
39
48
  change_job_state(:restart, job, index_or_id)
@@ -43,6 +52,8 @@ module Bosh::Cli
43
52
  usage 'recreate'
44
53
  desc 'Recreate all jobs/job/instance (hard stop + start)'
45
54
  option '--force', FORCE
55
+ option '--max-in-flight MAX_IN_FLIGHT', MAX_IN_FLIGHT
56
+ option '--canaries CANARIES', CANARIES
46
57
  option '--skip-drain', SKIP_DRAIN
47
58
  def recreate_job(job = '*', index_or_id = nil)
48
59
  change_job_state(:recreate, job, index_or_id)
@@ -53,7 +64,11 @@ module Bosh::Cli
53
64
  def change_job_state(state, job, index_or_id = nil)
54
65
  auth_required
55
66
  manifest = parse_manifest(state)
56
- job_state = JobState.new(self, manifest, skip_drain: skip_drain?)
67
+ options = {skip_drain: skip_drain?}
68
+ options[:canaries] = canaries if canaries
69
+ options[:max_in_flight] = max_in_flight if max_in_flight
70
+
71
+ job_state = JobState.new(self, manifest, options)
57
72
  status, task_id, completion_desc = job_state.change(state, job, index_or_id, force?)
58
73
  task_report(status, task_id, completion_desc)
59
74
  end
@@ -74,6 +89,14 @@ module Bosh::Cli
74
89
  !!options[:skip_drain]
75
90
  end
76
91
 
92
+ def canaries
93
+ options[:canaries]
94
+ end
95
+
96
+ def max_in_flight
97
+ options[:max_in_flight]
98
+ end
99
+
77
100
  def parse_manifest(operation)
78
101
  manifest = prepare_deployment_manifest(show_state: true)
79
102
 
@@ -6,7 +6,7 @@ module Bosh::Cli
6
6
  class Ssh < Base
7
7
 
8
8
  # bosh ssh
9
- usage 'ssh'
9
+ usage 'ssh <job>/<index>'
10
10
  desc 'Execute command or start an interactive session'
11
11
  option '--gateway_host HOST', 'Gateway host'
12
12
  option '--gateway_user USER', 'Gateway user'
@@ -37,11 +37,11 @@ module Bosh::Cli
37
37
  end
38
38
 
39
39
  # bosh scp
40
- usage 'scp'
41
- desc 'upload/download the source file to the given job. ' +
42
- 'Note: for download /path/to/destination is a directory'
43
- option '--download', 'Download file'
44
- option '--upload', 'Upload file'
40
+ usage 'scp <job>/<index> <source> <destination>'
41
+ desc "Transfer files to (--upload) or from (--download) a job.\n" +
42
+ 'Note: for --download, <destination> is treated as a directory'
43
+ option '--download', 'Download <source> file from the job'
44
+ option '--upload', 'Upload <source> file to the job'
45
45
  option '--gateway_host HOST', 'Gateway host'
46
46
  option '--gateway_user USER', 'Gateway user'
47
47
  option '--gateway_identity_file FILE', 'Gateway identity file'
@@ -153,14 +153,30 @@ module Bosh::Cli
153
153
  gateway = nil
154
154
  end
155
155
 
156
- yield sessions, gateway, ssh_session
156
+ begin
157
+ yield sessions, gateway, ssh_session
158
+ rescue Exception => error
159
+ handle_closed_stream_error(error)
160
+ end
157
161
  ensure
158
162
  nl
159
163
  say('Cleaning up ssh artifacts')
160
164
  ssh_session.cleanup
161
165
  indices = sessions.map { |session| session['id'] || session['index'] }
166
+ begin
167
+ gateway.shutdown! if gateway
168
+ rescue Exception => error
169
+ handle_closed_stream_error(error)
170
+ end
162
171
  director.cleanup_ssh(deployment_name, job, "^#{ssh_session.user}$", indices)
163
- gateway.shutdown! if gateway
172
+ end
173
+ end
174
+
175
+ def handle_closed_stream_error(error)
176
+ if error.message.include?('closed stream')
177
+ warn("#{error}")
178
+ else
179
+ raise error
164
180
  end
165
181
  end
166
182
 
@@ -23,6 +23,20 @@ module Bosh::Cli
23
23
  director.change_vm_resurrection(manifest.name, job, index_or_id, resurrection.paused?)
24
24
  end
25
25
  end
26
+
27
+ usage 'delete vm'
28
+ desc 'Deletes a vm'
29
+ def delete(vm_cid)
30
+ auth_required
31
+
32
+ unless confirmed?("Are you sure you want to delete vm '#{vm_cid}'?")
33
+ say('Canceled deleting vm'.make_green)
34
+ return
35
+ end
36
+
37
+ status, task_id = director.delete_vm_by_cid(vm_cid)
38
+ task_report(status, task_id, "Deleted vm '#{vm_cid}'")
39
+ end
26
40
  end
27
41
  end
28
42
  end
@@ -47,7 +47,7 @@ module Bosh::Cli::Command
47
47
  headings += ['VM Type', 'IPs']
48
48
 
49
49
  if options[:details]
50
- headings += ['CID', 'Agent ID', 'Resurrection']
50
+ headings += ['CID', 'Agent ID', 'Resurrection', 'Ignore']
51
51
  end
52
52
  if options[:dns]
53
53
  headings += ['DNS A records']
@@ -83,7 +83,7 @@ module Bosh::Cli::Command
83
83
  row << ips
84
84
 
85
85
  if options[:details]
86
- row += [vm['vm_cid'], vm['agent_id'], vm['resurrection_paused'] ? 'paused' : 'active']
86
+ row += [vm['vm_cid'], vm['agent_id'], vm['resurrection_paused'] ? 'paused' : 'active', vm['ignore'].nil? ? 'n/a' : vm['ignore']]
87
87
  end
88
88
 
89
89
  if options[:dns]
@@ -0,0 +1,22 @@
1
+ module Bosh::Cli
2
+
3
+ class NameIdPair
4
+ def self.parse(str)
5
+ raise ArgumentError, 'str must not be nil' if str.nil?
6
+
7
+ name, _, id = str.rpartition('/')
8
+ if name.empty? || id.empty?
9
+ raise ArgumentError, "\"#{str}\" must be in the form name/id"
10
+ end
11
+
12
+ new(name, id)
13
+ end
14
+
15
+ attr_reader :name, :id
16
+
17
+ def initialize(name, id)
18
+ @name, @id = name, id
19
+ end
20
+ end
21
+
22
+ end
@@ -71,6 +71,8 @@ module Bosh::Cli::TaskTracking
71
71
 
72
72
  if event['type'] == 'deprecation'
73
73
  show_deprecation(event)
74
+ elsif event['type'] == 'warning'
75
+ show_warning(event)
74
76
  elsif event['error']
75
77
  show_error(event)
76
78
  else
@@ -78,6 +80,11 @@ module Bosh::Cli::TaskTracking
78
80
  end
79
81
  end
80
82
 
83
+ def show_warning(event)
84
+ msg = " Warning: #{event['message']}"
85
+ @printer.print(:line_around, msg.make_yellow)
86
+ end
87
+
81
88
  def show_deprecation(event)
82
89
  msg = "Deprecation: #{event['message']}"
83
90
  @printer.print(:line_around, msg.make_red)
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Cli
3
- VERSION = '1.3232.24.0'
3
+ VERSION = '1.3262.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3232.24.0
4
+ version: 1.3262.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - VMware
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-02 00:00:00.000000000 Z
11
+ date: 2016-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bosh_common
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.3232.24.0
19
+ version: 1.3262.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.3232.24.0
26
+ version: 1.3262.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bosh-template
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.3232.24.0
33
+ version: 1.3262.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.3232.24.0
40
+ version: 1.3262.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: cf-uaa-lib
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 1.3232.24.0
131
+ version: 1.3262.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 1.3232.24.0
138
+ version: 1.3262.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: net-ssh
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -364,6 +364,7 @@ files:
364
364
  - lib/cli/commands/errand.rb
365
365
  - lib/cli/commands/events.rb
366
366
  - lib/cli/commands/help.rb
367
+ - lib/cli/commands/ignore.rb
367
368
  - lib/cli/commands/instances.rb
368
369
  - lib/cli/commands/job.rb
369
370
  - lib/cli/commands/job_management.rb
@@ -413,6 +414,7 @@ files:
413
414
  - lib/cli/logs_downloader.rb
414
415
  - lib/cli/manifest.rb
415
416
  - lib/cli/manifest_warnings.rb
417
+ - lib/cli/name_id_pair.rb
416
418
  - lib/cli/name_version_pair.rb
417
419
  - lib/cli/non_interactive_progress_renderer.rb
418
420
  - lib/cli/public_stemcell.rb