Class: Hu::Cli::Scale

Inherits:
Optix::Cli
  • Object
show all
Defined in:
lib/hu/scale.rb

Overview

Heroku Scale

Constant Summary collapse

DYNO_TYPES =
[
  {
    id: 'eco',
    sleeps: true,
    pro: false,
    ram: 512,
    cpu: 1,
    dedicated: false,
    usd: 0,
    letter: 'f',
    color: "\e[0;32;1m",
  },
  {
    id: 'basic',
    sleeps: false,
    pro: false,
    ram: 512,
    cpu: 1,
    dedicated: false,
    usd: 7,
    letter: 'H',
    color: "\e[0;32m",
  },
  {
    id: 'standard-1x',
    sleeps: false,
    pro: true,
    ram: 512,
    cpu: 1,
    dedicated: false,
    usd: 25,
    letter: '1',
    color: "\e[0;33m",
  },
  {
    id: 'standard-2x',
    sleeps: false,
    pro: true,
    ram: 1024,
    cpu: 4,
    dedicated: false,
    usd: 50,
    letter: '2',
    color: "\e[0;33;1m",
  },
  {
    id: 'performance-m',
    sleeps: false,
    pro: true,
    ram: 2560,
    cpu: 11,
    dedicated: true,
    usd: 250,
    letter: 'M',
    color: "\e[0;31;1m",
  },
  {
    id: 'performance-l',
    sleeps: false,
    pro: true,
    ram: 14_336,
    cpu: 46,
    dedicated: true,
    usd: 500,
    letter: 'L',
    color: "\e[0;35;1m",
  }
].freeze

Instance Method Summary collapse

Instance Method Details

#hObject



195
196
197
# File 'lib/hu/scale.rb', line 195

def h
  @h ||= PlatformAPI.connect_oauth(Hu::API_TOKEN)
end

#heroku_state(force_refresh = false) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
# File 'lib/hu/scale.rb', line 174

def heroku_state(force_refresh = false)
  return @heroku_state unless force_refresh || @heroku_state.nil?
  data = {}
  app_names = h.app.list.map { |e| e['name'] }.reject { |e| ignored_app?(e) }
  threads = []
  app_names.each_with_index do |app_name, _i|
    threads << Thread.new do
      h.formation.list(app_name).each do |dyno|
        dyno_size = dyno['size'].downcase
        data[app_name] ||= {}
        data[app_name][dyno_size] ||= []
        data[app_name][dyno_size] << { type: dyno['type'], quantity: dyno['quantity'] }
      end
    end
  end
  threads.each_with_index do |t, _i|
    t.join
  end
  @heroku_state = data
end

#ignored_app?(app_name) ⇒ Boolean

Returns:

  • (Boolean)


167
168
169
170
171
172
# File 'lib/hu/scale.rb', line 167

def ignored_app?(app_name)
  ENV.fetch('HU_IGNORE_APPS', '').split(' ').each do |p|
    return true if File.fnmatch(p, app_name)
  end
  false
end


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
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/hu/scale.rb', line 115

def print_state(state)
  cols = ['$/mo', 'fH12ML', 'formation']
  rows = []

  total_cost = 0
  max_app_name_len = state.keys.reduce(0) { |a, e| [a, e.length].max }
  state.sort.each do |app_name, dyno_types|
    next if ignored_app?(app_name)
    row = { 'app' => app_name, 'fH12ML' => '......', 'formation' => "\e[0mheroku ps:scale -a #{app_name.ljust(max_app_name_len).color(:green).bright}" }
    cost = 0
    dyno_types.each do |dyno_type, dynos|
      dynos.each do |dyno|
        row = Marshal.load(Marshal.dump(row))
        dyno_type_str = dyno[:type]
        quant_colon_type = "#{dyno[:quantity]}:#{dyno_type}"
        if dyno[:quantity] == 0
          dyno_type_str = dyno_type_str.color(:black).bright
          quant_colon_type = quant_colon_type.color(:black).bright
        else
          dyno_type_str = dyno_type_str.color(:yellow)
          quant_colon_type = quant_colon_type.color(:yellow)
          idx = DYNO_TYPES.find { |e| e[:id] == dyno_type }[:index]
          row['fH12ML'][idx] = 'fH12ML'[idx]
        end
        row['formation'] += " #{dyno_type_str}" + '='.color(:black).bright + quant_colon_type.to_s
        cost += (DYNO_TYPES.find { |e| e[:id] == dyno_type }&.fetch(:usd, 0) || 0) * dyno[:quantity]
      end
    end
    new_row = ''.dup
    row['fH12ML'].each_char do |l|
      new_row << (DYNO_TYPES.find {|dt| dt[:letter] == l}[:color] + l + "\e[0;30;1m" rescue '.')
    end
    row['fH12ML'] = "\e[0;30;1m"+new_row
    total_cost += cost
    row['$/mo'] = format '%4d', cost
    rows << row
  end

  puts
  puts ' Current Dyno Formation '.inverse
  puts

  tpl = "%-5s %6s %s\n"
  printf tpl.bright, *cols
  rows.each do |row|
    printf tpl, *cols.map { |col| row[col] }
  end
  puts
  puts "Total: $#{total_cost} USD/mo"
  puts
end


103
104
105
106
107
108
109
110
111
112
113
# File 'lib/hu/scale.rb', line 103

def print_types
  cols = %w(id ram cpu dedicated sleeps usd)
  tpl  = "%-16s %5s %4s %11s %7s %5s\n"
  puts
  puts ' Available Dyno Types '.inverse
  puts
  printf tpl.bright, *cols
  DYNO_TYPES.each do |dyno_type|
    printf tpl, *cols.map { |col| dyno_type[col.to_sym] }
  end
end

#scale(_cmd, _opts, _args) ⇒ Object



97
98
99
100
101
# File 'lib/hu/scale.rb', line 97

def scale(_cmd, _opts, _args)
  print_types
  puts
  print_state heroku_state
end