Class: Omaship::CLI

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

Constant Summary collapse

PROVISION_STEP_MESSAGES =
{
  "resolve_source" => "Preparing your ship run",
  "prepare_server" => "Preparing your harbor",
  "scaffold_app" => "Scaffolding your ship",
  "deploy_app" => "Deploying your ship",
  "create_tunnel" => "Configuring private access",
  "cutover_dns" => "Wiring up your ship routes",
  "lockdown_firewall" => "Locking down the harbor",
  "healthcheck" => "Running final health checks"
}.freeze
PROVISION_STEP_ETAS =
{
  "resolve_source" => "about 2 min",
  "prepare_server" => "about 2 min",
  "scaffold_app" => "about 90 sec",
  "deploy_app" => "about 90 sec",
  "create_tunnel" => "about 45 sec",
  "cutover_dns" => "about 30 sec",
  "lockdown_firewall" => "about 20 sec",
  "healthcheck" => "less than 15 sec"
}.freeze
DEFAULT_PROVISIONING_ETA =
"about 2 min"

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.exit_on_failure?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/omaship/cli.rb', line 35

def self.exit_on_failure?
  true
end

.help(shell, subcommand = false) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/omaship/cli.rb', line 75

def self.help(shell, subcommand = false)
  if subcommand
    super
  else
    shell.say "Usage:"
    shell.say "  omaship COMMAND [options]"
    shell.say
    shell.say "You must specify a command. The most common commands are:"
    shell.say
    shell.say "  login      Store API token credentials locally"
    shell.say "  whoami     Show authenticated user"
    shell.say "  list       List ships you can access"
    shell.say "  use        Set default ship from `omaship list` (for example: `omaship use acme.omaship.app`)"
    shell.say "  info       Show details for a ship (aliases: ship, status)"
    shell.say "  new        Create and provision a new ship"
    shell.say "  upgrade    Open browser to upgrade your plan"
    shell.say "  complete   Print shell completion script (bash, zsh, fish)"
    shell.say "  logout     Remove local CLI credentials"
    shell.say
    shell.say "Global options:"
    shell.say "  --host=HOST  API host"
    shell.say
    shell.say "All commands can be run with -h (or --help) for more information."
  end
end

.normalize_help_args(given_args) ⇒ Object



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

def self.normalize_help_args(given_args)
  args = given_args.dup

  if root_help_requested?(args)
    []
  else
    help_flag_index = args.index("-h") || args.index("--help")
    if help_flag_index
      [ "help", args.first ]
    else
      args
    end
  end
end

.root_help_requested?(args) ⇒ Boolean

Returns:

  • (Boolean)


67
68
69
# File 'lib/omaship/cli.rb', line 67

def self.root_help_requested?(args)
  args == [ "-h" ] || args == [ "--help" ] || args == [ "help" ]
end

.root_version_requested?(args) ⇒ Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/omaship/cli.rb', line 71

def self.root_version_requested?(args)
  args == [ "-v" ] || args == [ "--version" ]
end

.start(given_args = ARGV, config = {}) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/omaship/cli.rb', line 39

def self.start(given_args = ARGV, config = {})
  if root_version_requested?(given_args)
    $stdout.puts Omaship::VERSION
    return
  end

  normalized_args = normalize_help_args(given_args)
  super(normalized_args, config)
rescue Interrupt
  $stderr.puts "\nAborted."
  exit(130)
end

Instance Method Details

#complete(shell_name) ⇒ Object



287
288
289
290
291
# File 'lib/omaship/cli.rb', line 287

def complete(shell_name)
  normalized_shell = shell_name.to_s.strip.downcase
  script = completion_script_for(shell: normalized_shell)
  say script
end

#infoObject



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/omaship/cli.rb', line 204

def info
  with_api_error_handling(command: :info) do
    token = current_token
    client = build_api_client(token: token)
    resolved_ship = resolve_ship(token: token)
    ship = client.ship(ship_id: resolved_ship.fetch("id")).fetch("ship")
    default_ship_reference = credentials.default_ship.to_s.strip
    latest_voyage = latest_voyage_summary_for(ship:)

    say "Ship: #{ship.fetch("display_name")}"
    say "ID: #{ship.fetch("id")}"
    say "Status: #{ship.fetch("status")}"
    say "Domain: #{ship["root_domain"] || "-"}"
    app_url = ship["app_url"].to_s.strip
    if !app_url.empty?
      say "App: #{app_url}"
    end
    api_url = ship["api_url"].to_s.strip
    if !api_url.empty?
      say "API: #{api_url}"
    end
    say "Default Ship: #{default_ship_reference.empty? ? "-" : default_ship_reference}"

    if latest_voyage
      say "Latest Voyage: #{latest_voyage.fetch(:kind)} (#{latest_voyage.fetch(:status)})"
      if latest_voyage[:id]
        say "Voyage ID: ##{latest_voyage.fetch(:id)}"
      end
    end
  end
end

#listObject



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/omaship/cli.rb', line 157

def list
  with_api_error_handling(command: :list) do
    token = current_token
    ships = build_api_client(token: token).list_ships
    default_ship_reference = current_default_ship_reference(token: token, ships: ships)

    if ships.empty?
      say "No ships available yet."
    else
      say "Ships:"
      ships.each do |ship|
        marker = default_ship_match?(ship: ship, ship_reference: default_ship_reference) ? "*" : " "
        say ship_list_line(ship:, marker:)
      end

      if !default_ship_reference.empty?
        say
        say "* default ship: #{default_ship_reference}"
      end
    end
  end
end

#loginObject



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/omaship/cli.rb', line 103

def 
  token = options[:token] || ENV["OMASHIP_TOKEN"] || ask("API token:", echo: false)
  if token.to_s.strip.empty?
    raise Thor::Error, "Missing API token. Pass --token or set OMASHIP_TOKEN."
  end

  user_payload = build_api_client(token: token).authenticate.fetch("user")
  credentials.write(
    host: resolved_host,
    token: token,
    user: user_payload
  )

  say "Logged in as #{user_payload.fetch("email_address")}"
  say "Credentials saved to #{credentials.path}"
rescue Omaship::ApiClient::UnauthorizedError
  message = "Authentication failed. Check your API token. #{existing_credentials_status_message}"
  raise Thor::Error, message
rescue Omaship::ApiClient::Error => error
  raise Thor::Error, error.message
end

#logoutObject



126
127
128
129
# File 'lib/omaship/cli.rb', line 126

def logout
  credentials.clear
  say "Logged out."
end

#new_ship(name) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/omaship/cli.rb', line 238

def new_ship(name)
  with_api_error_handling(command: :new_ship) do
    token = current_token
    auth = fetch_auth(token: token)
    allowed_starter_kinds = allowed_starter_kinds_from_auth(auth)

    unless can_create_ship_from_auth?(auth)
      raise Thor::Error, "Ship limit reached for your plan. Run `omaship upgrade` to create another ship."
    end

    if allowed_starter_kinds == [ "landing" ]
      create_free_ship(name: name, token: token)
    else
      starter_kind = choose_paid_starter_kind

      if starter_kind == "landing"
        create_paid_landingpage(name: name, token: token)
      else
        create_paid_ship(name: name, token: token, starter_kind: starter_kind, auth: auth)
      end
    end
  end
end

#upgrade(ship_name = nil) ⇒ Object



263
264
265
266
267
268
269
270
271
# File 'lib/omaship/cli.rb', line 263

def upgrade(ship_name = nil)
  url = "#{resolved_host}/settings/license"
  if ship_name
    url = "#{url}?ship=#{ship_name}"
  end

  say "Opening #{url}"
  open_browser(url)
end

#use(ship_reference) ⇒ Object



192
193
194
195
196
197
198
199
200
# File 'lib/omaship/cli.rb', line 192

def use(ship_reference)
  with_api_error_handling(command: :use) do
    token = current_token
    ship = find_ship_by_reference(token: token, ship_reference: ship_reference)
    persist_default_ship(ship)

    say "Default ship set to #{ship.fetch("reference")}."
  end
end

#whoamiObject



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/omaship/cli.rb', line 132

def whoami
  with_api_error_handling(command: :whoami) do
    token = current_token
    client = build_api_client(token: token)
    auth_payload = client.authenticate
    user_payload = auth_payload.fetch("user")
     = auth_payload.fetch("account", {})
    ship_count = .fetch("ship_count", 0).to_i
    plan = normalized_plan_label(plan: user_payload["plan"], admin: user_payload["admin"])
    default_ship_reference = current_default_ship_reference(token: token)

    say "User: #{user_payload.fetch("email_address")}"
    say "Host: #{resolved_host}"
    say "Plan: #{plan}"
    say "Ships: #{ship_count}"

    if default_ship_reference.empty?
      say "Default Ship: -"
    else
      say "Default Ship: #{default_ship_reference}"
    end
  end
end