Module: Kontena::Cli::Common

Included in:
Helper, Kontena::Callbacks::AuthenticateAfterDeploy, Kontena::Callbacks::BeforeDeployConfigurationWizard, Kontena::Callbacks::ClearCurrentMasterAfterTerminate, Kontena::Callbacks::ConfigureAuthProviderAfterDeploy, Kontena::Callbacks::CreateInitialGridAfterDeploy, Kontena::Callbacks::DisplayLogoBeforeMasterDeploy, Kontena::Callbacks::InstallSslCertificateAfterDeploy, Kontena::Callbacks::InviteSelfAfterDeploy, Kontena::Callbacks::ListAndSelectGrid, Kontena::Callbacks::SetServerProviderAfterDeploy, Kontena::Callbacks::SuggestInvitingYourself, Apps::BuildCommand, Apps::ConfigCommand, Apps::DeployCommand, Apps::InitCommand, Apps::ListCommand, Apps::LogsCommand, Apps::MonitorCommand, Apps::RemoveCommand, Apps::RestartCommand, Apps::ScaleCommand, Apps::ShowCommand, Apps::StartCommand, Apps::StopCommand, Kontena::Cli::Certificate::AuthorizeCommand, Kontena::Cli::Certificate::GetCommand, Kontena::Cli::Certificate::RegisterCommand, Kontena::Cli::Cloud::LoginCommand, Kontena::Cli::Cloud::LogoutCommand, Kontena::Cli::Cloud::Master::AddCommand, Kontena::Cli::Cloud::Master::ListCommand, Kontena::Cli::Cloud::Master::RemoveCommand, Kontena::Cli::Cloud::Master::ShowCommand, Kontena::Cli::Cloud::Master::UpdateCommand, Kontena::Cli::Cloud::MasterCommand, Kontena::Cli::Containers::ExecCommand, Kontena::Cli::Containers::InspectCommand, Kontena::Cli::Containers::ListCommand, Kontena::Cli::Containers::LogsCommand, Etcd::GetCommand, Etcd::HealthCommand, Etcd::ListCommand, Etcd::MkdirCommand, Etcd::RemoveCommand, Etcd::SetCommand, ExternalRegistries::AddCommand, ExternalRegistries::ListCommand, ExternalRegistries::RemoveCommand, Grids::AuditLogCommand, Grids::CloudConfigCommand, Grids::CreateCommand, Grids::CurrentCommand, Grids::EnvCommand, Grids::EventsCommand, Grids::HealthCommand, Grids::ListCommand, Grids::LogsCommand, Grids::RemoveCommand, Grids::ShowCommand, Grids::TrustedSubnets::AddCommand, Grids::TrustedSubnets::ListCommand, Grids::TrustedSubnets::RemoveCommand, Grids::UpdateCommand, Grids::UseCommand, Grids::Users::AddCommand, Grids::Users::ListCommand, Grids::Users::RemoveCommand, LogoutCommand, Master::AuditLogCommand, Master::Config::ExportCommand, Master::Config::GetCommand, Master::Config::ImportCommand, Master::Config::SetCommand, Master::Config::UnsetCommand, Master::CreateCommand, Master::CurrentCommand, Master::InitCloudCommand, Master::ListCommand, Master::LoginCommand, Master::LogoutCommand, Master::RemoveCommand, Master::SshCommand, Master::Token::CreateCommand, Master::Token::CurrentCommand, Master::Token::ListCommand, Master::Token::RemoveCommand, Master::Token::ShowCommand, Master::UseCommand, Master::User::InviteCommand, Master::User::ListCommand, Master::User::RemoveCommand, Master::User::Role::AddCommand, Master::User::Role::RemoveCommand, Nodes::HealthCommand, Nodes::Labels::AddCommand, Nodes::Labels::ListCommand, Nodes::Labels::RemoveCommand, Nodes::ListCommand, Nodes::RemoveCommand, Nodes::ShowCommand, Nodes::SshCommand, Nodes::UpdateCommand, Plugins::InstallCommand, Plugins::UninstallCommand, Registry::CreateCommand, Registry::RemoveCommand, Services::ContainersCommand, Services::CreateCommand, Services::DeployCommand, Services::Envs::AddCommand, Services::Envs::ListCommand, Services::Envs::RemoveCommand, Services::EventsCommand, Services::ExecCommand, Services::LinkCommand, Services::ListCommand, Services::LogsCommand, Services::MonitorCommand, Services::RemoveCommand, Services::RestartCommand, Services::ScaleCommand, Services::Secrets::LinkCommand, Services::Secrets::UnlinkCommand, Services::ServicesHelper, Services::ShowCommand, Services::StartCommand, Services::StatsCommand, Services::StopCommand, Services::UnlinkCommand, Services::UpdateCommand, Stacks::BuildCommand, Stacks::DeployCommand, Stacks::EventsCommand, Stacks::InstallCommand, Stacks::ListCommand, Stacks::LogsCommand, Stacks::MonitorCommand, Stacks::Registry::PullCommand, Stacks::Registry::PushCommand, Stacks::Registry::RemoveCommand, Stacks::Registry::SearchCommand, Stacks::Registry::ShowCommand, Stacks::RemoveCommand, Stacks::ShowCommand, Stacks::UpgradeCommand, Stacks::ValidateCommand, Stacks::YAML::Opto::Resolvers::ServiceLink, Stacks::YAML::Opto::Resolvers::Vault, Stacks::YAML::Opto::Resolvers::VaultCertPrompt, Stacks::YAML::Opto::Setters::Vault, Stacks::YAML::Prompt, Stacks::YAML::Reader, Vault::ExportCommand, Vault::ImportCommand, Vault::ListCommand, Vault::ReadCommand, Vault::RemoveCommand, Vault::UpdateCommand, Vault::WriteCommand, VersionCommand, Volumes::CreateCommand, Volumes::ListCommand, Volumes::RemoveCommand, Volumes::ShowCommand, Vpn::ConfigCommand, Vpn::CreateCommand, Vpn::RemoveCommand, WhoamiCommand, MainCommand, StacksCache::RegistryClientFactory
Defined in:
lib/kontena/cli/common.rb

Instance Method Summary collapse

Instance Method Details

#access_token=(token) ⇒ Object



283
284
285
286
# File 'lib/kontena/cli/common.rb', line 283

def access_token=(token)
  require_current_master.token.access_token = token
  config.write
end

#add_master(server_name, master_info) ⇒ Object



288
289
290
# File 'lib/kontena/cli/common.rb', line 288

def add_master(server_name, master_info)
  config.add_server(master_info.merge('name' => server_name))
end

#any_key_to_continue(timeout = nil) ⇒ Object



326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/kontena/cli/common.rb', line 326

def any_key_to_continue(timeout = nil)
  return nil if running_silent?
  return nil unless $stdout.tty?
  return any_key_to_continue_with_timeout(timeout) if timeout
  msg = "Press any key to continue or ctrl-c to cancel.. "
  print pastel.bright_cyan("#{msg}")
  char = $stdin.getch
  print "\r#{' ' * msg.length}\r"
  if char == "\u0003"
    error "Canceled"
  end
end

#any_key_to_continue_with_timeout(timeout = 9) ⇒ Object



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/kontena/cli/common.rb', line 296

def any_key_to_continue_with_timeout(timeout=9)
  return nil if running_silent?
  return nil unless $stdout.tty?
  start_time = Time.now.to_i
  end_time   = start_time + timeout
  Thread.main['any_key.timed_out']   = false
  msg = "Press any key to continue or ctrl-c to cancel.. (Automatically continuing in ? seconds)"

  reader_thread = Thread.new do
    Thread.main['any_key.char'] = $stdin.getch
  end

  countdown_thread = Thread.new do
    time_left = timeout
    while time_left > 0 && Thread.main['any_key.char'].nil?
      print "\r#{pastel.bright_white("#{msg.sub("?", time_left.to_s)}")} "
      time_left = end_time - Time.now.to_i
      sleep 0.1
    end
    print "\r#{' ' * msg.length}  \r"
    reader_thread.kill if reader_thread.alive?
  end

  countdown_thread.join

  if Thread.main['any_key.char'] == "\u0003"
    error "Canceled"
  end
end

#api_url ⇒ Object



209
210
211
# File 'lib/kontena/cli/common.rb', line 209

def api_url
  config.require_current_master.url
end

#api_url=(api_url) ⇒ Object



278
279
280
281
# File 'lib/kontena/cli/common.rb', line 278

def api_url=(api_url)
  config.current_master.url = api_url
  config.write
end

#api_url_version ⇒ Object



174
175
176
# File 'lib/kontena/cli/common.rb', line 174

def api_url_version
  client.server_version
end

#ask(question = "") ⇒ Object



247
248
249
# File 'lib/kontena/cli/common.rb', line 247

def ask(question = "")
  prompt.ask(question)
end

#clear_current_grid ⇒ Object



221
222
223
224
# File 'lib/kontena/cli/common.rb', line 221

def clear_current_grid
  current_master.delete_field(:grid) if require_current_master.respond_to?(:grid)
  config.write
end

#client(token = nil, api_url = nil) ⇒ Object



186
187
188
189
190
191
192
193
194
195
# File 'lib/kontena/cli/common.rb', line 186

def client(token = nil, api_url = nil)
  if token.kind_of?(String)
    token = Kontena::Cli::Config::Token.new(access_token: token)
  end

  @client ||= Kontena::Client.new(
    api_url || require_current_master.url,
    token || require_current_master.token
  )
end

#cloud_auth? ⇒ Boolean

Returns:

  • (Boolean)


167
168
169
170
171
172
# File 'lib/kontena/cli/common.rb', line 167

def cloud_auth?
  return false unless 
  return false unless .token
  return false unless .token.access_token
  true
end

#cloud_client ⇒ Object



178
179
180
# File 'lib/kontena/cli/common.rb', line 178

def cloud_client
  @cloud_client ||= Kontena::Client.new(.url, .token, prefix: '/')
end

#config ⇒ Object



117
118
119
# File 'lib/kontena/cli/common.rb', line 117

def config
  Kontena::Cli::Config.instance
end

#confirm(message = 'Destructive command. You can skip this prompt by running this command with --force option. Are you sure?') ⇒ Object



270
271
272
273
274
275
276
# File 'lib/kontena/cli/common.rb', line 270

def confirm(message = 'Destructive command. You can skip this prompt by running this command with --force option. Are you sure?')
  if self.respond_to?(:force?) && self.force?
    return
  end
  exit_with_error 'Command requires --force' unless $stdout.tty? && $stdin.tty?
  prompt.yes?(message) || error('Aborted command.')
end

#confirm_command(name, message = nil) ⇒ Object



259
260
261
262
263
264
265
266
267
268
# File 'lib/kontena/cli/common.rb', line 259

def confirm_command(name, message = nil)
  if self.respond_to?(:force?) && self.force?
    return
  end
  exit_with_error 'Command requires --force' unless $stdout.tty? && $stdin.tty?
  puts message if message
  puts "Destructive command. To proceed, type \"#{name}\" or re-run this command with --force option."

  ask("Enter '#{name}' to confirm: ") == name || error("Confirmation did not match #{name}. Aborted command.")
end

#current_account ⇒ Object



159
160
161
# File 'lib/kontena/cli/common.rb', line 159

def 
  config.
end

#current_grid ⇒ Object



226
227
228
# File 'lib/kontena/cli/common.rb', line 226

def current_grid
  (self.respond_to?(:grid) ? self.grid : nil) || config.current_grid
end

#current_grid=(grid) ⇒ Object



213
214
215
# File 'lib/kontena/cli/common.rb', line 213

def current_grid=(grid)
  config.current_grid=(grid)
end

#current_master ⇒ Object



234
235
236
# File 'lib/kontena/cli/common.rb', line 234

def current_master
  config.current_master
end

#current_master=(master_alias) ⇒ Object



238
239
240
# File 'lib/kontena/cli/common.rb', line 238

def current_master=(master_alias)
  config.current_master = master_alias
end

#current_master_index ⇒ Object



230
231
232
# File 'lib/kontena/cli/common.rb', line 230

def current_master_index
  config.find_server_index(require_current_master.name)
end

#display_account_login_info ⇒ Object



339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/kontena/cli/common.rb', line 339

def 
  if 
    if .token && .token.access_token
      begin
        puts [
          pastel.green("Authenticated to Kontena Cloud at"),
          pastel.yellow(.url),
          pastel.green("as"),
          pastel.yellow(.username)
        ].join(' ')
      rescue
      end
    else
      puts pastel.cyan("Not authenticated to Kontena Cloud")
    end
  end
end

#display_login_info(only: nil) ⇒ Object



377
378
379
380
# File 'lib/kontena/cli/common.rb', line 377

def (only: nil)
    unless only == :account
   unless only == :master
end

#display_logo ⇒ Object



382
383
384
# File 'lib/kontena/cli/common.rb', line 382

def 
  puts File.read(File.expand_path('../../../../LOGO', __FILE__))
end

#display_master_login_info ⇒ Object



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/kontena/cli/common.rb', line 357

def 
  server = config.current_master
  if server
    if server.token && server.token.access_token
      puts [
        pastel.green('Authenticated to Kontena Master'),
        pastel.yellow(server.name),
        pastel.green('at'),
        pastel.yellow(server.url),
        pastel.green('as'),
        pastel.yellow(server.token.username || server.username)
      ].join(' ')
    else
      puts pastel.cyan("Not authenticated to current master #{server.name}")
    end
  else
    puts pastel.cyan("Current master not selected")
  end
end

#error(message = "Error") ⇒ Object



242
243
244
245
# File 'lib/kontena/cli/common.rb', line 242

def error(message = "Error")
  prompt.error(message)
  exit(1)
end

#exit_with_error(msg, code = 1) ⇒ Object



111
112
113
114
115
# File 'lib/kontena/cli/common.rb', line 111

def exit_with_error(msg, code = 1)
  error = pastel.red('error')
  $stderr.puts " [#{error}] #{msg}"
  exit code
end

#kontena_account ⇒ Object



163
164
165
# File 'lib/kontena/cli/common.rb', line 163

def 
  @kontena_account ||= config.(ENV['KONTENA_ACCOUNT'] || 'kontena')
end

#logger ⇒ Object



13
14
15
16
17
18
19
# File 'lib/kontena/cli/common.rb', line 13

def logger
  return @logger if @logger
  @logger = Logger.new(ENV["DEBUG"] ? $stderr : $stdout)
  @logger.level = ENV["DEBUG"].nil? ? Logger::INFO : Logger::DEBUG
  @logger.progname = 'COMMON'
  @logger
end

#pastel ⇒ Object



21
22
23
# File 'lib/kontena/cli/common.rb', line 21

def pastel
  @pastel ||= Pastel.new(enabled: $stdout.tty?)
end

Print that doesn't print if self.silent?



57
58
59
60
61
62
63
# File 'lib/kontena/cli/common.rb', line 57

def print(*msgs)
  if running_silent?
    logger.debug(msgs.join)
  else
    super(*msgs)
  end
end

#prompt ⇒ Object



255
256
257
# File 'lib/kontena/cli/common.rb', line 255

def prompt
  ::Kontena.prompt
end

#puts(*msgs) ⇒ Object

Puts that doesn't puts if self.silent?



66
67
68
69
70
71
72
73
74
75
# File 'lib/kontena/cli/common.rb', line 66

def puts(*msgs)
  if running_silent?
    msgs.compact.each { |msg| logger.debug(msg) }
  elsif Thread.main['spinners'] && !Thread.main['spinners'].empty?
    Thread.main['spinner_msgs'] ||= []
    msgs.each { |msg| Thread.main['spinner_msgs'] << msg }
  else
    super(*msgs)
  end
end

#require_api_url ⇒ Object



121
122
123
# File 'lib/kontena/cli/common.rb', line 121

def require_api_url
  config.require_current_master.url
end

#require_current_account ⇒ Object



155
156
157
# File 'lib/kontena/cli/common.rb', line 155

def 
  config.
end

#require_current_grid ⇒ Object



217
218
219
# File 'lib/kontena/cli/common.rb', line 217

def require_current_grid
  config.require_current_grid
end

#require_current_master ⇒ Object



151
152
153
# File 'lib/kontena/cli/common.rb', line 151

def require_current_master
  config.require_current_master
end

#require_token ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/kontena/cli/common.rb', line 125

def require_token
  retried ||= false
  config.require_current_master_token
rescue Kontena::Cli::Config::TokenExpiredError
  if retried
    raise ArgumentError, "Current master access token has expired and refresh failed."
  else
    logger.debug "Access token expired, trying to refresh"
    retried = true
    client.refresh_token && retry
  end
end

#reset_client ⇒ Object



197
198
199
# File 'lib/kontena/cli/common.rb', line 197

def reset_client
  @client = nil
end

#reset_cloud_client ⇒ Object



182
183
184
# File 'lib/kontena/cli/common.rb', line 182

def reset_cloud_client
  @cloud_client = nil
end

#running_silent? ⇒ Boolean

Returns:

  • (Boolean)


38
39
40
# File 'lib/kontena/cli/common.rb', line 38

def running_silent?
  self.respond_to?(:silent?) && self.silent?
end

#running_verbose? ⇒ Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/kontena/cli/common.rb', line 42

def running_verbose?
  self.respond_to?(:verbose?) && self.verbose?
end

#settings ⇒ Object



205
206
207
# File 'lib/kontena/cli/common.rb', line 205

def settings
  config
end

#settings_filename ⇒ Object



201
202
203
# File 'lib/kontena/cli/common.rb', line 201

def settings_filename
  config.config_filename
end

#spinner(msg, &block) ⇒ Object



292
293
294
# File 'lib/kontena/cli/common.rb', line 292

def spinner(msg, &block)
  Kontena::Cli::Spinner.spin(msg, &block)
end

#sprint(*msgs) ⇒ Object

Print that prints even when self.silent?



52
53
54
# File 'lib/kontena/cli/common.rb', line 52

def sprint(*msgs)
  ::Kernel.print(*msgs)
end

#sputs(*msgs) ⇒ Object

Puts that puts even when self.silent?



47
48
49
# File 'lib/kontena/cli/common.rb', line 47

def sputs(*msgs)
  ::Kernel.puts(*msgs)
end

#stdin_input(message = nil, mode = :ask) ⇒ Object

Read from STDIN. If stdin is a console, use prompt to ask.

Parameters:

  • message (String) (defaults to: nil)
  • mode (Symbol) (defaults to: :ask) —

    (prompt method: :ask, :multiline, etc)



28
29
30
31
32
33
34
35
36
# File 'lib/kontena/cli/common.rb', line 28

def stdin_input(message = nil, mode = :ask)
  if $stdin.tty?
    Array(prompt.send(mode, message)).join.chomp
  elsif !$stdin.eof?
    $stdin.read.chomp
  else
    exit_with_error 'Missing input'
  end
end

#use_refresh_token(server) ⇒ Object

Invalidate refresh_token

Parameters:



140
141
142
143
144
145
146
147
148
149
# File 'lib/kontena/cli/common.rb', line 140

def use_refresh_token(server)
  return unless server.token
  return unless server.token.refresh_token
  return if server.token.expired?
  client = Kontena::Client.new(server.url, server.token)
  logger.debug "Trying to invalidate refresh token on #{server.name}"
  client.refresh_token
rescue => ex
  logger.debug "Refreshing failed: #{ex.class.name} : #{ex.message}"
end

#vfakespinner(msg, success: true) ⇒ Object

Like vspinner but without actually running any block



98
99
100
101
102
103
104
# File 'lib/kontena/cli/common.rb', line 98

def vfakespinner(msg, success: true)
  if !running_verbose?
    logger.debug msg
    return
  end
  puts " [#{ success ? 'done'.colorize(:green) : 'fail'.colorize(:red)}] #{msg}"
end

#vputs(msg = nil) ⇒ Object

Only output message if in verbose mode



78
79
80
81
82
83
84
# File 'lib/kontena/cli/common.rb', line 78

def vputs(msg = nil)
  if running_verbose?
    puts msg
  elsif ENV["DEBUG"] && msg
    logger.debug msg
  end
end

#vspinner(msg, &block) ⇒ Object

Only show spinner when in verbose mode



87
88
89
90
91
92
93
94
95
# File 'lib/kontena/cli/common.rb', line 87

def vspinner(msg, &block)
  return vfakespinner(msg) unless block_given?

  if running_verbose?
    spinner(msg, &block)
  else
    yield
  end
end

#warning(msg) ⇒ Object



106
107
108
109
# File 'lib/kontena/cli/common.rb', line 106

def warning(msg)
  warning = pastel.yellow('warn')
  $stderr.puts " [#{warning}] #{msg}"
end

#yes?(question = "") ⇒ Boolean

Returns:

  • (Boolean)


251
252
253
# File 'lib/kontena/cli/common.rb', line 251

def yes?(question = "")
  prompt.yes?(question)
end