kamal-backup 0.3.0.beta12 → 0.3.0.beta14

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: 42ee96d9a7a664d18460f7143c466ebe6d6d75a70031c0c75a070fae2e3fa64b
4
- data.tar.gz: 02bc406f76d5010cd9c382c5b6ea4d17bb8dce0dab50d2742d86bec9e7bb93cc
3
+ metadata.gz: 78dad6331e7a06890125c303e9631e8701d6a1aeffe953134905456910a9e445
4
+ data.tar.gz: af988f114c9449b3f5d6fe8fecb6b09ecddddf20887aadf7d98700b8f2023c5d
5
5
  SHA512:
6
- metadata.gz: 45d35e27cb88d61a8996ed5b2158fc59e3f9ef51b615e88919efd83d6174b044d60984d8be5ac15d937229c5b2a9ded61f90053afb5a6569ddb2f8c824b88bad
7
- data.tar.gz: 5d0c18b5faf002497831421773ede6b4d50805fdb8d70490c6746b0229f06cf44b59a1c2683913439f4de186aeb2388c69acd97f965d52e266b8921ed4fb2a86
6
+ metadata.gz: 7af73531536f8179425f95ebd4b5a9d3522e4fe0e2a109564795a4da318e73b9b85e26427bb4d7ee7b388cea94deb9f1670b9ca18c7b5a4592d8906182b9c794
7
+ data.tar.gz: 4b32db0463641ca0f51dc35f23cb5b6d00bc36ac09518921efec1636d0517bc39624d1ef36fc1f86ad53efb554dd880c583dd5e9e5f4ff6c9efe39a3b5888d75
@@ -5,10 +5,11 @@ require_relative "errors"
5
5
 
6
6
  module KamalBackup
7
7
  class CommandSpec
8
- attr_reader :argv, :env
8
+ attr_reader :argv, :env, :host
9
9
 
10
- def initialize(argv:, env: {})
10
+ def initialize(argv:, env: {}, host: nil)
11
11
  @argv = Array(argv).compact.map(&:to_s)
12
+ @host = host.to_s unless host.to_s.empty?
12
13
  @env = env.each_with_object({}) do |(key, value), result|
13
14
  next if value.nil? || value.to_s.empty?
14
15
 
@@ -85,7 +86,7 @@ module KamalBackup
85
86
  started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
86
87
  display = spec.display(redactor)
87
88
 
88
- write_message("INFO", "Running #{colorize(display, :yellow, :bold)} #{local_target}", id)
89
+ write_message("INFO", "Running #{colorize(display, :yellow, :bold)} #{target_for(spec)}", id)
89
90
  write_message("DEBUG", "Command: #{colorize(display, :blue)}", id)
90
91
 
91
92
  { id: id, started_at: started_at, redactor: redactor }
@@ -177,6 +178,14 @@ module KamalBackup
177
178
  end
178
179
  end
179
180
 
181
+ def target_for(spec)
182
+ if spec.host
183
+ "on #{colorize(spec.host, :blue)}"
184
+ else
185
+ local_target
186
+ end
187
+ end
188
+
180
189
  def log_level?(level)
181
190
  LEVELS.fetch(level) >= @verbosity
182
191
  end
@@ -53,7 +53,11 @@ module KamalBackup
53
53
  end
54
54
 
55
55
  def execute_on_accessory(accessory_name:, command:, stream: false)
56
- capture_kamal(kamal_exec_argv(accessory_name, command), stream: stream)
56
+ if stream && (target = live_accessory_target(accessory_name))
57
+ execute_on_accessory_live(accessory_name: accessory_name, command: command, target: target)
58
+ else
59
+ capture_kamal(kamal_exec_argv(accessory_name, command), stream: stream)
60
+ end
57
61
  end
58
62
 
59
63
  def remote_version(accessory_name:)
@@ -176,12 +180,13 @@ module KamalBackup
176
180
  ]
177
181
  end
178
182
 
179
- def kamal_exec_argv(accessory_name, command)
183
+ def kamal_exec_argv(accessory_name, command, interactive: false)
180
184
  [
181
185
  *kamal_command,
182
186
  "accessory",
183
187
  "exec",
184
188
  *kamal_option_argv,
189
+ *(["--interactive"] if interactive),
185
190
  "--reuse",
186
191
  accessory_name,
187
192
  command
@@ -214,14 +219,14 @@ module KamalBackup
214
219
  argv
215
220
  end
216
221
 
217
- def capture_kamal(argv, stream: false)
222
+ def capture_kamal(argv, stream: false, log: !stream, stdout: @stdout, stderr: @stderr)
218
223
  spec = CommandSpec.new(argv: argv, env: kamal_stream_env(stream))
219
224
  options = {
220
225
  redactor: @redactor,
221
- log: !stream,
226
+ log: log,
222
227
  log_output: false,
223
- tee_stdout: stream ? @stdout : nil,
224
- tee_stderr: stream ? @stderr : nil
228
+ tee_stdout: stream ? stdout : nil,
229
+ tee_stderr: stream ? stderr : nil
225
230
  }
226
231
 
227
232
  if defined?(Bundler)
@@ -231,6 +236,87 @@ module KamalBackup
231
236
  end
232
237
  end
233
238
 
239
+ def execute_on_accessory_live(accessory_name:, command:, target:)
240
+ @stdout.puts("Launching command from existing container...")
241
+
242
+ spec = CommandSpec.new(
243
+ argv: ["docker", "exec", target.fetch(:service_name), *Shellwords.split(command)],
244
+ host: target.fetch(:host)
245
+ )
246
+ context = Command.output&.command_start(spec, redactor: @redactor)
247
+
248
+ result = capture_kamal(
249
+ kamal_exec_argv(accessory_name, command, interactive: true),
250
+ stream: true,
251
+ log: false,
252
+ stdout: filtered_interactive_stdout
253
+ )
254
+ Command.output&.command_exit(context, result.status) if context
255
+ result
256
+ rescue CommandError => e
257
+ Command.output&.command_exit(context, e.status || 1) if context
258
+ raise
259
+ end
260
+
261
+ def filtered_interactive_stdout
262
+ FilteringIO.new(@stdout) do |output|
263
+ output == "Launching interactive command via SSH from existing container...\n"
264
+ end
265
+ end
266
+
267
+ def live_accessory_target(accessory_name)
268
+ return unless defined?(@config)
269
+
270
+ accessory_config = accessory(accessory_name)
271
+ host = single_accessory_host(accessory_config)
272
+ service_name = fetch(accessory_config, :service) || default_accessory_service_name(accessory_name)
273
+
274
+ { host: host, service_name: service_name } if host && service_name
275
+ rescue ConfigurationError, KeyError, NoMethodError, TypeError
276
+ nil
277
+ end
278
+
279
+ def single_accessory_host(accessory_config)
280
+ hosts = if host = fetch(accessory_config, :host)
281
+ normalized_hosts(host)
282
+ else
283
+ normalized_hosts(fetch(accessory_config, :hosts))
284
+ end
285
+
286
+ hosts.first if hosts.size == 1
287
+ end
288
+
289
+ def normalized_hosts(value)
290
+ case value
291
+ when nil
292
+ []
293
+ when Array
294
+ value.map(&:to_s).reject(&:empty?)
295
+ else
296
+ [value.to_s].reject(&:empty?)
297
+ end
298
+ end
299
+
300
+ def default_accessory_service_name(accessory_name)
301
+ service = fetch(config, :service).to_s
302
+ "#{service}-#{accessory_name}" unless service.empty?
303
+ end
304
+
305
+ class FilteringIO
306
+ def initialize(io, &reject)
307
+ @io = io
308
+ @reject = reject
309
+ end
310
+
311
+ def print(output)
312
+ @io.print(output) unless @reject.call(output.to_s)
313
+ end
314
+
315
+ def flush
316
+ @io.flush if @io.respond_to?(:flush)
317
+ end
318
+ end
319
+
234
320
  def kamal_stream_env(stream)
235
321
  return {} unless stream
236
322
 
@@ -1,3 +1,3 @@
1
1
  module KamalBackup
2
- VERSION = "0.3.0.beta12"
2
+ VERSION = "0.3.0.beta14"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kamal-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.beta12
4
+ version: 0.3.0.beta14
5
5
  platform: ruby
6
6
  authors:
7
7
  - crmne