brasa 0.2.0 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e032ecc30bbe651d19e8a91b2f72763a0b210aa110fa1dfb635ae4cd5c1b516
4
- data.tar.gz: df821859fe77ebc80d247d272f3be6dc604c9cfbb0f39de24b65f46a5a19ea11
3
+ metadata.gz: 5a49c4bccb1e9a9074615b14ea63f96a85163c5a8af134cbbf7fe8fa5c662b3a
4
+ data.tar.gz: bdc9b16edbdf065340d199a1a4d254a2e49c51b641000bd701d09a35bd94af91
5
5
  SHA512:
6
- metadata.gz: 4057bbc29ef417a5c7690e5d5bca6355e3eb6da62a09296b0082954c5946e65e8ddaf5d715e26ad9d9a2e46826912b1b9c80d59246afbf61f95e0a9e296b28eb
7
- data.tar.gz: 2385cd7bbee60f2041ddfeff043d3ee4cfdd1d7fe4987ff1e7da90a5a7db94844b9a0870a3fd3d9cefb4042be08375e937afeb6335ba3047dbaf268f5bd0dbe9
6
+ metadata.gz: 447bed84e8814068dc16e6eaae55fc82474acd5435e28da5e732376431c79c485e8f677d8f095598d399f5e56827328db86145e65e5bd43426c0172ff1743074
7
+ data.tar.gz: be3aa908f2e07f3d84c9b52e26355a50e2bd469a3d3a01d9009a5552affeba50b7de0655ad55546bbe40614e310e09a54aa7402f17615e771a995b3be7b6d1fd
data/lib/brasa/cli.rb CHANGED
@@ -4,6 +4,8 @@ require "brasa/commands/init"
4
4
  require "brasa/commands/up"
5
5
  require "brasa/commands/deploy"
6
6
  require "brasa/commands/logs"
7
+ require "brasa/commands/logs_search"
8
+ require "brasa/commands/logs_export"
7
9
  require "brasa/commands/env"
8
10
  require "brasa/commands/database"
9
11
  require "brasa/commands/scale"
@@ -45,6 +47,25 @@ module Brasa
45
47
  Commands::Logs.new.execute(options)
46
48
  end
47
49
 
50
+ desc "logs:search", "Buscar nos logs da aplicação"
51
+ option :query, type: :string, required: true, desc: "Termo de busca"
52
+ option :level, type: :string, desc: "Filtrar por nível (error, warn, info)"
53
+ option :source, type: :string, desc: "Filtrar por source"
54
+ option :since, type: :string, desc: "Período (ex: 1h, 24h, 7d)"
55
+ option :limit, type: :string, default: "100", desc: "Limite de resultados"
56
+ define_method("logs:search") do
57
+ Commands::LogsSearch.new.execute(options)
58
+ end
59
+
60
+ desc "logs:export", "Exportar logs da aplicação"
61
+ option :format, type: :string, default: "json", desc: "Formato de exportação (json, csv)"
62
+ option :since, type: :string, desc: "Data/hora inicial"
63
+ option :until, type: :string, desc: "Data/hora final"
64
+ option :level, type: :string, desc: "Filtrar por nível (error, warn, info)"
65
+ define_method("logs:export") do
66
+ Commands::LogsExport.new.execute(options)
67
+ end
68
+
48
69
  desc "env SUBCOMMAND", "Gerenciar variáveis de ambiente"
49
70
  subcommand "env", Commands::Env
50
71
 
@@ -0,0 +1,28 @@
1
+ require "brasa/commands/base"
2
+
3
+ module Brasa
4
+ module Commands
5
+ class LogsExport < Base
6
+ def execute(options = {})
7
+ require_auth!
8
+ slug = app_slug
9
+
10
+ format = options.fetch("format", "json")
11
+ params = { export_format: format }
12
+ params[:since] = options["since"] if options["since"]
13
+ params[:until] = options["until"] if options["until"]
14
+ params[:level] = options["level"] if options["level"]
15
+
16
+ result = api.get("/api/v1/apps/#{slug}/logs/export", params: params)
17
+
18
+ if result.is_a?(Array)
19
+ puts JSON.pretty_generate(result)
20
+ else
21
+ puts result
22
+ end
23
+ rescue Api::Client::ApiError => e
24
+ error("Erro: #{e.message}")
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ require "brasa/commands/base"
2
+
3
+ module Brasa
4
+ module Commands
5
+ class LogsSearch < Base
6
+ def execute(options = {})
7
+ require_auth!
8
+ slug = app_slug
9
+ query = options["query"]
10
+
11
+ unless query
12
+ info("Uso: brasa logs:search <query> [--level error] [--since 1h]")
13
+ return
14
+ end
15
+
16
+ params = { q: query, limit: options.fetch("limit", "100") }
17
+ params[:level] = options["level"] if options["level"]
18
+ params[:source] = options["source"] if options["source"]
19
+ params[:since] = options["since"] if options["since"]
20
+
21
+ results = api.get("/api/v1/apps/#{slug}/logs/search", params: params)
22
+
23
+ if results.nil? || results.empty?
24
+ info("Nenhum resultado encontrado.")
25
+ return
26
+ end
27
+
28
+ results.each do |entry|
29
+ puts "#{pastel.dim(entry["timestamp"])} #{pastel.cyan(entry["source"])} [#{colorize_level(entry["level"])}] #{entry["message"]}"
30
+ end
31
+ rescue Api::Client::ApiError => e
32
+ error("Erro: #{e.message}")
33
+ end
34
+
35
+ private
36
+
37
+ def colorize_level(level)
38
+ case level
39
+ when "error" then pastel.red(level)
40
+ when "warn" then pastel.yellow(level)
41
+ when "info" then pastel.green(level)
42
+ else pastel.dim(level)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -6,19 +6,25 @@ module Brasa
6
6
  class Redis < Thor
7
7
  namespace :redis
8
8
 
9
+ MEMORY_TO_PLAN = {
10
+ 256 => "starter",
11
+ 512 => "pro",
12
+ 1024 => "business"
13
+ }.freeze
14
+
9
15
  desc "status", "Ver status do Redis"
10
16
  def status
11
17
  helper = RedisHelper.new
12
18
  helper.require_auth!
13
19
  slug = helper.app_slug
14
20
 
15
- redis = helper.api.get("/api/v1/apps/#{slug}/redis")
21
+ addon = helper.api.get("/api/v1/apps/#{slug}/addons/cache")
16
22
 
17
23
  puts helper.pastel.bold("Redis de #{slug}")
18
- puts " Status: #{redis["status"]}"
19
- puts " Versão: Redis #{redis["version"]}"
20
- puts " Memória: #{redis["memory_mb"]}MB"
21
- puts " URL: #{redis["redis_url"]}"
24
+ puts " Status: #{addon["status"]}"
25
+ puts " Plano: #{addon["plan"]}"
26
+ puts " Memória: #{addon.dig("config", "memory_mb")}MB"
27
+ puts " Custo: R$ #{addon["monthly_cost_brl"]}/mês"
22
28
  rescue Api::Client::ApiError => e
23
29
  RedisHelper.new.error("Erro: #{e.message}")
24
30
  end
@@ -30,8 +36,14 @@ module Brasa
30
36
  helper.require_auth!
31
37
  slug = helper.app_slug
32
38
 
33
- helper.info("Habilitando Redis com #{options[:memory]}MB...")
34
- result = helper.api.post("/api/v1/apps/#{slug}/redis", { memory_mb: options[:memory] })
39
+ plan = MEMORY_TO_PLAN[options[:memory]]
40
+ unless plan
41
+ helper.error("Memória inválida. Use: 256, 512 ou 1024")
42
+ return
43
+ end
44
+
45
+ helper.info("Habilitando Redis com #{options[:memory]}MB (plano #{plan})...")
46
+ result = helper.api.post("/api/v1/apps/#{slug}/addons", { addon: { slug: "cache", plan: plan } })
35
47
  helper.success("Redis habilitado! Status: #{result["status"]}")
36
48
  rescue Api::Client::ApiError => e
37
49
  RedisHelper.new.error("Erro: #{e.message}")
@@ -50,7 +62,7 @@ module Brasa
50
62
  end
51
63
 
52
64
  helper.info("Removendo Redis...")
53
- helper.api.delete("/api/v1/apps/#{slug}/redis")
65
+ helper.api.delete("/api/v1/apps/#{slug}/addons/cache")
54
66
  helper.success("Redis removido com sucesso!")
55
67
  rescue Api::Client::ApiError => e
56
68
  RedisHelper.new.error("Erro: #{e.message}")
@@ -3,8 +3,8 @@ require "brasa/commands/base"
3
3
  module Brasa
4
4
  module Commands
5
5
  class Up < Base
6
- POLL_INTERVAL = 3
7
- MAX_POLLS = 60
6
+ POLL_INTERVAL = 5
7
+ MAX_POLLS = 120
8
8
 
9
9
  def execute(options = {})
10
10
  require_auth!
@@ -15,14 +15,17 @@ module Brasa
15
15
  app = create_app(config)
16
16
  info("App #{app["slug"]} criado. Provisionando infraestrutura...")
17
17
 
18
- wait_for_provisioning(app["slug"])
18
+ unless wait_for_provisioning(app["slug"])
19
+ return
20
+ end
19
21
  success("Infraestrutura provisionada!")
20
22
 
21
23
  info("Iniciando primeiro deploy...")
22
24
  deploy = trigger_deploy(app["slug"])
23
- wait_for_deploy(app["slug"], deploy["id"])
24
25
 
25
- success("Deploy concluído! App disponível em https://#{app["slug"]}.usebrasa.com.br")
26
+ if wait_for_deploy(app["slug"], deploy["id"])
27
+ success("Deploy concluído! App disponível em https://#{app["slug"]}.usebrasa.com.br")
28
+ end
26
29
  rescue Api::Client::ValidationError => e
27
30
  error("Erro ao criar app: #{e.message}")
28
31
  rescue Api::Client::ApiError => e
@@ -48,29 +51,31 @@ module Brasa
48
51
  def wait_for_provisioning(slug)
49
52
  MAX_POLLS.times do
50
53
  app = api.get("/api/v1/apps/#{slug}")
51
- return if app["status"] == "active"
54
+ return true if app["status"] == "active"
52
55
  if app["status"] == "error"
53
56
  error("Erro no provisionamento.")
54
- return
57
+ return false
55
58
  end
56
59
  print "."
57
60
  sleep(POLL_INTERVAL)
58
61
  end
59
62
  error("Timeout aguardando provisionamento.")
63
+ false
60
64
  end
61
65
 
62
66
  def wait_for_deploy(slug, deploy_id)
63
67
  MAX_POLLS.times do
64
68
  deploy = api.get("/api/v1/apps/#{slug}/deploys/#{deploy_id}")
65
- return if deploy["status"] == "live"
69
+ return true if deploy["status"] == "live"
66
70
  if deploy["status"] == "failed"
67
71
  error("Deploy falhou.")
68
- return
72
+ return false
69
73
  end
70
74
  print "."
71
75
  sleep(POLL_INTERVAL)
72
76
  end
73
77
  error("Timeout aguardando deploy.")
78
+ false
74
79
  end
75
80
  end
76
81
  end
data/lib/brasa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Brasa
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brasa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brasa
@@ -145,6 +145,8 @@ files:
145
145
  - lib/brasa/commands/init.rb
146
146
  - lib/brasa/commands/login.rb
147
147
  - lib/brasa/commands/logs.rb
148
+ - lib/brasa/commands/logs_export.rb
149
+ - lib/brasa/commands/logs_search.rb
148
150
  - lib/brasa/commands/redis.rb
149
151
  - lib/brasa/commands/scale.rb
150
152
  - lib/brasa/commands/status.rb