jatai 1.2.1 → 1.3.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 +4 -4
- data/lib/jatai/cli.rb +8 -0
- data/lib/jatai/commands/run.rb +79 -0
- data/lib/jatai/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7b9131e1a51d23a7120a320f01c24d31b332e636467c048bbfddea25bd49b643
|
|
4
|
+
data.tar.gz: 5306e6ed76d3076ebe707d08f399d9071d63814fe92cd930239a2143113ba87a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed82a595b2b854268d89902e495963b548b6b6a0057d9e846aa01345157fe5c02ea76935901aede74a668be8a8c6ed1c9a7f509702fd27e8f45b37cbf2f382c4
|
|
7
|
+
data.tar.gz: 17fb609ef8532e4da8d49c8bd1cb8ada50fc3052772db9b4b625de6f6516fb830ab8de27264c9166c30eff5080b2adb0d07c827bda32c7184682a0488746e235
|
data/lib/jatai/cli.rb
CHANGED
|
@@ -13,6 +13,7 @@ require "jatai/commands/status"
|
|
|
13
13
|
require "jatai/commands/destroy"
|
|
14
14
|
require "jatai/commands/domains"
|
|
15
15
|
require "jatai/commands/redis"
|
|
16
|
+
require "jatai/commands/run"
|
|
16
17
|
|
|
17
18
|
module Jatai
|
|
18
19
|
class CLI < Thor
|
|
@@ -41,6 +42,13 @@ module Jatai
|
|
|
41
42
|
Commands::Deploy.new.execute(options)
|
|
42
43
|
end
|
|
43
44
|
|
|
45
|
+
# "run" é palavra reservada do Thor — mapeada p/ run_command.
|
|
46
|
+
desc "run COMANDO", "Executar comando one-off no app (pod efêmero do release atual)"
|
|
47
|
+
map "run" => :run_command
|
|
48
|
+
def run_command(*command_parts)
|
|
49
|
+
Commands::Run.new.execute(command_parts)
|
|
50
|
+
end
|
|
51
|
+
|
|
44
52
|
desc "logs", "Ver logs da aplicação em tempo real"
|
|
45
53
|
option :tail, type: :numeric, default: 100, desc: "Número de linhas"
|
|
46
54
|
def logs
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require "jatai/commands/base"
|
|
2
|
+
|
|
3
|
+
module Jatai
|
|
4
|
+
module Commands
|
|
5
|
+
# jatai run "<comando>" — executa um comando one-off num pod efêmero com a
|
|
6
|
+
# imagem do release atual, streama a saída e retorna o exit code real.
|
|
7
|
+
class Run < Base
|
|
8
|
+
RUN_TIMEOUT = 960 # activeDeadlineSeconds (900) + folga
|
|
9
|
+
|
|
10
|
+
def execute(command_parts)
|
|
11
|
+
require_auth!
|
|
12
|
+
command = Array(command_parts).join(" ").strip
|
|
13
|
+
return error("Informe o comando: jatai run \"bin/rails runner '...'\"") if command.empty?
|
|
14
|
+
|
|
15
|
+
slug = app_slug
|
|
16
|
+
run = api.post("/api/v1/apps/#{slug}/runs", body: { command: command })
|
|
17
|
+
info("Run ##{run["id"]} criado — subindo pod efêmero com o release atual...")
|
|
18
|
+
|
|
19
|
+
status = follow(run["id"])
|
|
20
|
+
finish(slug, run["id"], status)
|
|
21
|
+
rescue Api::Client::ValidationError => e
|
|
22
|
+
error("Erro: #{e.message}")
|
|
23
|
+
exit(1)
|
|
24
|
+
rescue Api::Client::ApiError => e
|
|
25
|
+
error("Erro: #{e.message}")
|
|
26
|
+
exit(1)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def follow(run_id)
|
|
32
|
+
ws = connect_websocket
|
|
33
|
+
ws.on_log { |msg| puts msg["line"] if msg.is_a?(Hash) && msg["line"] }
|
|
34
|
+
ws.wait_for("AppRunChannel",
|
|
35
|
+
params: { run_id: run_id },
|
|
36
|
+
until_status: %w[succeeded failed error],
|
|
37
|
+
timeout: RUN_TIMEOUT)
|
|
38
|
+
rescue Jatai::Websocket::CableClient::ConnectionError
|
|
39
|
+
info("[WebSocket indisponível — aguardando resultado via API...]")
|
|
40
|
+
poll_until_done(run_id)
|
|
41
|
+
ensure
|
|
42
|
+
ws&.disconnect
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def poll_until_done(run_id)
|
|
46
|
+
(RUN_TIMEOUT / 5).times do
|
|
47
|
+
run = api.get("/api/v1/apps/#{app_slug}/runs/#{run_id}")
|
|
48
|
+
return run["status"] if %w[succeeded failed error].include?(run["status"])
|
|
49
|
+
sleep(5)
|
|
50
|
+
end
|
|
51
|
+
"error"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# O socket entrega o status; o exit code vem da API (fonte de verdade).
|
|
55
|
+
def finish(slug, run_id, status)
|
|
56
|
+
run = api.get("/api/v1/apps/#{slug}/runs/#{run_id}")
|
|
57
|
+
exit_code = run["exit_code"]
|
|
58
|
+
|
|
59
|
+
case status
|
|
60
|
+
when "succeeded"
|
|
61
|
+
success("Concluído (exit 0)")
|
|
62
|
+
exit(0)
|
|
63
|
+
when "failed"
|
|
64
|
+
hint = exit_code == 137 ? " — processo morto (SIGKILL), possivelmente falta de memória (OOM)" : ""
|
|
65
|
+
error("Comando terminou com exit #{exit_code}#{hint}")
|
|
66
|
+
exit(exit_code.to_i.clamp(1, 255))
|
|
67
|
+
else
|
|
68
|
+
error("Run falhou na infraestrutura. Tente novamente ou verifique com: jatai status")
|
|
69
|
+
exit(1)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def connect_websocket
|
|
74
|
+
require "jatai/websocket/cable_client"
|
|
75
|
+
Jatai::Websocket::CableClient.new.tap(&:connect!)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/lib/jatai/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jatai
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jataí Cloud
|
|
@@ -176,6 +176,7 @@ files:
|
|
|
176
176
|
- lib/jatai/commands/logs_export.rb
|
|
177
177
|
- lib/jatai/commands/logs_search.rb
|
|
178
178
|
- lib/jatai/commands/redis.rb
|
|
179
|
+
- lib/jatai/commands/run.rb
|
|
179
180
|
- lib/jatai/commands/scale.rb
|
|
180
181
|
- lib/jatai/commands/status.rb
|
|
181
182
|
- lib/jatai/commands/up.rb
|