kamal-backup 0.3.0.beta13 → 0.3.0.beta15

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: 3db60902f3b1adadb65d4cadd4c97939976e9fd2c9508ced7972417d63996e0f
4
- data.tar.gz: 61a0ec544ee7ca806c698e53fd5b22896b08d309bd8d51ccb23a9cd23a4110f0
3
+ metadata.gz: 7640fc151eabbf4abbcd390ce9633d85638fd7a9d9580652af69567be2c02178
4
+ data.tar.gz: 39976b40a0987b36f01b6ed835ea6f32486ef5a6e512eeae522c2e431d3b0c06
5
5
  SHA512:
6
- metadata.gz: 0b17700d7f5ffaf7db4a2f56ad4b2efd6378281242b32f90937e8e8f3a94e3007d403a8fc7e15a54ba06f69e5532b2abacec2d891ee4c6be9d3ecceddebea30a
7
- data.tar.gz: 95fb53b3513d242ea36b0b1beecbe5791d48a549b1320898941caa3e7e191930954ecef33171d3b1cfaf750b9c376691c2930ce6fd32814abcbe87c432d5afa4
6
+ metadata.gz: abae67de65b6c5e5af29da2f3cca84122e145ef6b2c460ee3bc71aa05c3d1c4bf67d2973a5ea5e65bf43437c5a64849a449b3e50909ea11dee7a1c2049f3c95b
7
+ data.tar.gz: a6d2036b16727cf72b13a1622ddf49e62eda37ca70fb9c48a41a730cfead991e75485aa6deb5160be0f7c3739f6f9147606c0755a7b9d7f2e72f085473016107
@@ -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,102 @@ 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
+ return hosts.first if hosts.size == 1
287
+ return if hosts.any?
288
+
289
+ all_hosts = normalized_hosts(fetch(config, :hosts))
290
+ all_hosts.first if all_hosts.size == 1
291
+ end
292
+
293
+ def normalized_hosts(value)
294
+ case value
295
+ when nil
296
+ []
297
+ when Array
298
+ value.map(&:to_s).reject(&:empty?)
299
+ else
300
+ [value.to_s].reject(&:empty?)
301
+ end
302
+ end
303
+
304
+ def default_accessory_service_name(accessory_name)
305
+ service = fetch(config, :service).to_s
306
+ service = service_from_rendered_config if service.empty?
307
+ "#{service}-#{accessory_name}" unless service.empty?
308
+ end
309
+
310
+ def service_from_rendered_config
311
+ service_with_version = fetch(config, :service_with_version).to_s
312
+ version = fetch(config, :version).to_s
313
+ suffix = "-#{version}"
314
+
315
+ if !service_with_version.empty? && !version.empty? && service_with_version.end_with?(suffix)
316
+ service_with_version.delete_suffix(suffix)
317
+ end
318
+ end
319
+
320
+ class FilteringIO
321
+ def initialize(io, &reject)
322
+ @io = io
323
+ @reject = reject
324
+ end
325
+
326
+ def print(output)
327
+ @io.print(output) unless @reject.call(output.to_s)
328
+ end
329
+
330
+ def flush
331
+ @io.flush if @io.respond_to?(:flush)
332
+ end
333
+ end
334
+
234
335
  def kamal_stream_env(stream)
235
336
  return {} unless stream
236
337
 
@@ -1,3 +1,3 @@
1
1
  module KamalBackup
2
- VERSION = "0.3.0.beta13"
2
+ VERSION = "0.3.0.beta15"
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.beta13
4
+ version: 0.3.0.beta15
5
5
  platform: ruby
6
6
  authors:
7
7
  - crmne