Class: Kontena::Cli::Stacks::ListCommand

Inherits:
Kontena::Command show all
Includes:
Common, GridOptions, Common, TableGenerator::Helper
Defined in:
lib/kontena/cli/stacks/list_command.rb

Constant Summary collapse

HEALTH_ICONS =
{
  unhealthy: Kontena.pastel.red('').freeze,
  partial:   Kontena.pastel.yellow('').freeze,
  healthy:   Kontena.pastel.green('').freeze,
  default:   Kontena.pastel.dim('').freeze
}

Instance Attribute Summary

Attributes inherited from Kontena::Command

#arguments, #exit_code, #result

Instance Method Summary collapse

Methods included from Common

#abort_on_validation_errors, #current_dir, #display_notifications, #hint_on_validation_notifications, #loader, #loader_class, #reader, #set_env_variables, #stack, #stack_name, #stacks_client

Methods included from Kontena::Cli::Services::ServicesHelper

#create_service, #delete_service, #deploy_service, #get_service, #health_status, #health_status_icon, #int_to_filesize, #parse_build_args, #parse_container_name, #parse_deploy_opts, #parse_health_check, #parse_image, #parse_links, #parse_log_opts, #parse_memory, #parse_ports, #parse_relative_time, #parse_secrets, #parse_service_id, #render_service_deploy_instances, #restart_service, #scale_service, #show_service, #show_service_containers, #show_service_instances, #start_service, #stop_service, #update_service, #wait_for_deploy_to_finish

Methods included from Common

#access_token=, #add_master, #any_key_to_continue, #any_key_to_continue_with_timeout, #api_url, #api_url=, #caret, #clear_current_grid, #client, #cloud_auth?, #cloud_client, #config, #confirm, #confirm_command, #current_grid, #current_master_index, #debug?, #display_account_login_info, #display_login_info, display_logo, #display_master_login_info, #error, exit_with_error, #kontena_account, #logger, #pastel, #print, #prompt, #puts, #require_api_url, #require_token, #reset_client, #reset_cloud_client, #running_quiet?, #running_silent?, #running_verbose?, #spin_if, #spinner, #sprint, #sputs, #stdin_input, #use_refresh_token, #vfakespinner, #vputs, #vspinner, #warning

Methods included from TableGenerator::Helper

#generate_table, included, #print_table, #table_generator

Methods included from GridOptions

included

Methods inherited from Kontena::Command

banner, callback_matcher, #help_requested?, inherited, #instance, load_subcommand, requires_current_account_token, requires_current_account_token?, requires_current_grid, requires_current_grid?, requires_current_master, requires_current_master?, requires_current_master_token, requires_current_master_token?, #run, #run_callbacks, #verify_current_account_token, #verify_current_grid, #verify_current_master, #verify_current_master_token

Instance Method Details

#build_depths(stacks) ⇒ Object



26
27
28
29
30
31
32
33
34
# File 'lib/kontena/cli/stacks/list_command.rb', line 26

def build_depths(stacks)
  stacks.sort_by { |s| s['name'] }.each do |stack|
    stack['depth'] += 1
    stacks_by_names(stacks, stack['children'].map { |n| n['name'] }).each do |child_stack|
      child_stack['depth'] += stack['depth']
    end
  end
  stacks
end

#executeObject



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/kontena/cli/stacks/list_command.rb', line 53

def execute
  stacks = build_depths(get_stacks)

  print_table(stacks) do |row|
    next if quiet?
    row['name'] = health_icon(stack_health(row)) + " " + tree_icon(row) + " " + row['name']
    row['stack'] = "#{row['stack']}:#{row['version']}"
    row['services_count'] = row['services'].size
    row['ports'] = stack_ports(row).join(',')
    row['state'] = pastel.send(state_color(row['state']), row['state'])
    row['labels'] = stack_labels(row)
  end
end

#fieldsObject

Defines a set of columns for the command.



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/kontena/cli/stacks/list_command.rb', line 41

def fields
  return ['name'] if quiet?
  {
    name: 'name',
    stack: 'stack',
    services: 'services_count',
    state: 'state',
    'exposed ports' => 'ports',
    labels: 'labels'
  }
end

#get_stacksObject



36
37
38
# File 'lib/kontena/cli/stacks/list_command.rb', line 36

def get_stacks
  client.get("grids/#{current_grid}/stacks")['stacks'].tap { |stacks| stacks.map { |stack| stack['depth'] = 0 } }
end

#health_icon(health) ⇒ Object



77
78
79
# File 'lib/kontena/cli/stacks/list_command.rb', line 77

def health_icon(health)
  HEALTH_ICONS.fetch(health) { HEALTH_ICONS[:default] }
end

#stack_health(stack) ⇒ Symbol

Parameters:

  • stack (Hash)

Returns:

  • (Symbol)


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
# File 'lib/kontena/cli/stacks/list_command.rb', line 124

def stack_health(stack)
  services_count = stack['services'].size
  return :unknown if services_count == 0

  fully_healthy_count = 0
  partial_healthy_count = 0
  unhealthy_count = 0
  unknown_count = 0
  stack['services'].each { |s|
    total = s.dig('health_status', 'total').to_i
    healthy = s.dig('health_status', 'healthy').to_i
    if total > 0 && healthy == total
      fully_healthy_count += 1
    elsif healthy < total && healthy > 0
      partial_healthy_count += 1
    elsif healthy == 0 && total > 0
      unhealthy_count += 1
    else
      unknown_count += 1
    end
  }
  return :partial if partial_healthy_count > 0
  return :partial if unhealthy_count > 0 && fully_healthy_count > 0
  return :unhealthy if unhealthy_count == services_count
  return :healthy if fully_healthy_count == services_count
  return :healthy if fully_healthy_count > 0 && unknown_count > 0

  :unknown
end

#stack_labels(stack) ⇒ <String>

Converts an array of stack labels into a comma-separated string or ‘-’ when labels field is not defined.

Parameters:

  • stack (Hash)

Returns:



102
103
104
105
106
# File 'lib/kontena/cli/stacks/list_command.rb', line 102

def stack_labels(stack)
  labels = (stack['labels'] || ['-']).join(',')
  # trim labels to fit viewport when exceed 43 chars
  labels.length > 43 && $stdout.isatty ? "#{labels[0..40]}..." : labels
end

#stack_ports(stack) ⇒ Array<String>

Parameters:

  • stack (Hash)

Returns:



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/kontena/cli/stacks/list_command.rb', line 110

def stack_ports(stack)
  ports = []
  stack['services'].each{|s|
    service_ports = s['ports'].map{|p|
      p['ip'] = '*' if p['ip'] == '0.0.0.0'
      "#{p['ip']}:#{p['node_port']}->#{p['container_port']}/#{p['protocol']}"
    }
    ports = ports + service_ports unless service_ports.empty?
  }
  ports
end

#stacks_by_names(stacks, name_list) ⇒ Object



22
23
24
# File 'lib/kontena/cli/stacks/list_command.rb', line 22

def stacks_by_names(stacks, name_list)
  name_list.map { |name| stacks.find { |stack| stack['name'] == name } }.compact
end

#state_color(state) ⇒ Object



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

def state_color(state)
  case state
  when 'running' then :green
  when 'deploying', 'initialized' then :blue
  when 'stopped' then :red
  when 'partially_running' then :yellow
  else :clear
  end
end

#tree_icon(row) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/kontena/cli/stacks/list_command.rb', line 81

def tree_icon(row)
  return '' unless $stdout.tty?
  parent = row['parent']
  children = row['children'] || []
  if parent.nil? && children.empty?
    # solo
    char = ''
  elsif parent.nil? && !children.empty?
    char = ''
  elsif !parent.nil?
    char = '┗━'
  end
  left_pad = ' ' * (2 * (row['depth'] - 1))
  left_pad + char
end