mrsk 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b7f4333081763cf001d3891931c1615eeb46bc29c2a8754ec863db67259f542
4
- data.tar.gz: 809cc3d35b9c9f445299f3e188cd74b32e504dd7747d7dfcd0b11a698b34ebf9
3
+ metadata.gz: d7f288f243a0192ea977464282b13b71f4ba585db01db7e7d7ae805e5509cffe
4
+ data.tar.gz: e96ababf967b92aa6236339d7eb24382207789a3b2c2b64d95caff08fabda32c
5
5
  SHA512:
6
- metadata.gz: 675b6e985621e236c9a3cde0b19d245bb8ac68ce9ae0ceef68c574c3427b1d8255bcd84f4547f9329eca535994a66b6cc6e88470181ca3ef74ea4e06e1a88244
7
- data.tar.gz: 701df3deb670cfcd323a57d0baa5ded62e267657a7ad2198d226c809b89ace6eda46a282146d18123b569db4ef72d996ea487fd157ec8f0f7b639dbb56bf1fa4
6
+ metadata.gz: b1e33f7d1598785b107a4c7610df678c341c2d26899b2c6e67739991ed573f9fcfeb511ac422f78b1447c5952f8e90d4c581795729f3503bc18f89b6334c3686
7
+ data.tar.gz: 1d3db7364c2574a3222ec1ab5c03c91ad1c1d55c83d0d397075b9d86fd41d2dc3e9d67068b619a3d5495036357301b7d2d2be618e58e2b8e40c972534da95c89
data/README.md CHANGED
@@ -302,9 +302,9 @@ Now run `mrsk accessory start mysql` to start the MySQL server on 1.1.1.3. See `
302
302
 
303
303
  ## Commands
304
304
 
305
- ### Running remote execution and runners
305
+ ### Running commands on servers
306
306
 
307
- If you need to execute commands inside the Rails containers, you can use `mrsk app exec` and `mrsk app runner`. Examples:
307
+ You can execute one-off commands on the servers:
308
308
 
309
309
  ```bash
310
310
  # Runs command on all servers
@@ -347,13 +347,25 @@ Database adapter sqlite3
347
347
  Database schema version 20221231233303
348
348
 
349
349
  # Run Rails runner on primary server
350
- mrsk app runner -p 'puts Rails.application.config.time_zone'
350
+ mrsk app exec -p 'bin/rails runner "puts Rails.application.config.time_zone"'
351
351
  UTC
352
352
  ```
353
353
 
354
- ### Running a Rails console
354
+ ### Running interactive commands over SSH
355
+
356
+ You can run interactive commands, like a Rails console or a bash session, on a server (default is primary, use `--hosts` to connect to another):
357
+
358
+ ```bash
359
+ # Starts a bash session in a new container made from the most recent app image
360
+ mrsk app exec -i bash
361
+
362
+ # Starts a bash session in the currently running container for the app
363
+ mrsk app exec -i --reuse bash
364
+
365
+ # Starts a Rails console in a new container made from the most recent app image
366
+ mrsk app exec -i 'bin/rails console'
367
+ ```
355
368
 
356
- If you need to interact with the production console for the app, you can use `mrsk app console`, which will start a Rails console session on the primary host. You can start the console on a different host using `mrsk app console --host 192.168.0.2`. Be mindful that this is a live wire! Any changes made to the production database will take effect immeditately.
357
369
 
358
370
  ### Running details to see state of containers
359
371
 
@@ -82,39 +82,27 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
82
82
  end
83
83
  end
84
84
 
85
- desc "exec [NAME] [CMD]", "Execute a custom command on accessory host"
86
- option :method, aliases: "-m", default: "exec", desc: "Execution method: [exec] perform inside container / [run] perform in new container / [ssh] perform over ssh"
85
+ desc "exec [NAME] [CMD]", "Execute a custom command on servers"
86
+ option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
87
+ option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
87
88
  def exec(name, cmd)
88
- runner = \
89
- case options[:method]
90
- when "exec" then "exec"
91
- when "run" then "run_exec"
92
- when "ssh_exec" then "exec_over_ssh"
93
- when "ssh_run" then "run_over_ssh"
94
- else raise "Unknown method: #{options[:method]}"
95
- end.inquiry
96
-
97
89
  with_accessory(name) do |accessory|
98
- if runner.exec_over_ssh? || runner.run_over_ssh?
99
- run_locally do
100
- info "Launching command on #{accessory.host}"
101
- exec accessory.send(runner, cmd)
102
- end
103
- else
104
- on(accessory.host) do
105
- info "Launching command on #{accessory.host}"
106
- execute *accessory.send(runner, cmd)
107
- end
108
- end
109
- end
110
- end
90
+ case
91
+ when options[:interactive] && options[:reuse]
92
+ say "Launching interactive command with via SSH from existing container...", :magenta
93
+ run_locally { exec accessory.execute_in_existing_container_over_ssh(cmd) }
111
94
 
112
- desc "bash [NAME]", "Start a bash session on primary host (or specific host set by --hosts)"
113
- def bash(name)
114
- with_accessory(name) do |accessory|
115
- run_locally do
116
- info "Launching bash session on #{accessory.host}"
117
- exec accessory.bash
95
+ when options[:interactive]
96
+ say "Launching interactive command via SSH from new container...", :magenta
97
+ run_locally { exec accessory.execute_in_new_container_over_ssh(cmd) }
98
+
99
+ when options[:reuse]
100
+ say "Launching command from existing container...", :magenta
101
+ on(accessory.host) { capture_with_info(*accessory.execute_in_existing_container(cmd)) }
102
+
103
+ else
104
+ say "Launching command from new container...", :magenta
105
+ on(accessory.host) { capture_with_info(*accessory.execute_in_new_container(cmd)) }
118
106
  end
119
107
  end
120
108
  end
@@ -166,7 +154,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
166
154
  end
167
155
  end
168
156
 
169
- desc "remove_container [NAME]", "Remove accessory image from host"
157
+ desc "remove_image [NAME]", "Remove accessory image from host"
170
158
  def remove_image(name)
171
159
  with_accessory(name) do |accessory|
172
160
  on(accessory.host) { execute *accessory.remove_image }
data/lib/mrsk/cli/app.rb CHANGED
@@ -1,32 +1,39 @@
1
1
  require "mrsk/cli/base"
2
2
 
3
3
  class Mrsk::Cli::App < Mrsk::Cli::Base
4
- desc "boot", "Boot app on servers (or start them if they've already been booted)"
4
+ desc "boot", "Boot app on servers (or reboot app if already running)"
5
5
  def boot
6
- MRSK.config.roles.each do |role|
7
- on(role.hosts) do |host|
8
- begin
9
- execute *MRSK.app.run(role: role.name)
10
- rescue SSHKit::Command::Failed => e
11
- if e.message =~ /already in use/
12
- error "Container with same version already deployed on #{host}, starting that instead"
13
- execute *MRSK.app.start, host: host
14
- else
15
- raise
6
+ cli = self
7
+
8
+ say "Ensure no other version of the app is running...", :magenta
9
+ stop
10
+
11
+ say "Get most recent version available as an image...", :magenta unless options[:version]
12
+ using_version(options[:version] || most_recent_version_available) do |version|
13
+ say "Start container with version #{version} (or reboot if already running)...", :magenta
14
+
15
+ MRSK.config.roles.each do |role|
16
+ on(role.hosts) do |host|
17
+ begin
18
+ execute *MRSK.app.run(role: role.name)
19
+ rescue SSHKit::Command::Failed => e
20
+ if e.message =~ /already in use/
21
+ error "Rebooting container with same version already deployed on #{host}"
22
+
23
+ cli.remove_container version
24
+ execute *MRSK.app.run(role: role.name)
25
+ else
26
+ raise
27
+ end
16
28
  end
17
29
  end
18
30
  end
19
31
  end
20
32
  end
21
-
33
+
22
34
  desc "start", "Start existing app on servers (use --version=<git-hash> to designate specific version)"
23
- option :version, desc: "Defaults to the most recent git-hash in local repository"
24
35
  def start
25
- if (version = options[:version]).present?
26
- on(MRSK.hosts) { execute *MRSK.app.start(version: version) }
27
- else
28
- on(MRSK.hosts) { execute *MRSK.app.start, raise_on_non_zero_exit: false }
29
- end
36
+ on(MRSK.hosts) { execute *MRSK.app.start, raise_on_non_zero_exit: false }
30
37
  end
31
38
 
32
39
  desc "stop", "Stop app on servers"
@@ -40,45 +47,38 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
40
47
  end
41
48
 
42
49
  desc "exec [CMD]", "Execute a custom command on servers"
43
- option :method, aliases: "-m", default: "exec", desc: "Execution method: [exec] perform inside app container / [run] perform in new container / [ssh] perform over ssh"
50
+ option :interactive, aliases: "-i", type: :boolean, default: false, desc: "Execute command over ssh for an interactive shell (use for console/bash)"
51
+ option :reuse, type: :boolean, default: false, desc: "Reuse currently running container instead of starting a new one"
44
52
  def exec(cmd)
45
- runner = \
46
- case options[:method]
47
- when "exec" then "exec"
48
- when "run" then "run_exec"
49
- when "ssh" then "exec_over_ssh"
50
- else raise "Unknown method: #{options[:method]}"
51
- end.inquiry
52
-
53
- if runner.exec_over_ssh?
54
- run_locally do
55
- info "Launching command on #{MRSK.primary_host}"
56
- exec MRSK.app.exec_over_ssh(cmd, host: MRSK.primary_host)
53
+ case
54
+ when options[:interactive] && options[:reuse]
55
+ say "Get current version of running container...", :magenta unless options[:version]
56
+ using_version(options[:version] || current_running_version) do |version|
57
+ say "Launching interactive command with version #{version} via SSH from existing container on #{MRSK.primary_host}...", :magenta
58
+ run_locally { exec MRSK.app.execute_in_existing_container_over_ssh(cmd, host: MRSK.primary_host) }
57
59
  end
58
- else
59
- on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.send(runner, cmd)) }
60
- end
61
- end
62
60
 
63
- desc "console", "Start Rails Console on primary host (or specific host set by --hosts)"
64
- def console
65
- run_locally do
66
- info "Launching Rails console on #{MRSK.primary_host}"
67
- exec MRSK.app.console(host: MRSK.primary_host)
68
- end
69
- end
61
+ when options[:interactive]
62
+ say "Get most recent version available as an image...", :magenta unless options[:version]
63
+ using_version(options[:version] || most_recent_version_available) do |version|
64
+ say "Launching interactive command with version #{version} via SSH from new container on #{MRSK.primary_host}...", :magenta
65
+ run_locally { exec MRSK.app.execute_in_new_container_over_ssh(cmd, host: MRSK.primary_host) }
66
+ end
70
67
 
71
- desc "bash", "Start a bash session on primary host (or specific host set by --hosts)"
72
- def bash
73
- run_locally do
74
- info "Launching bash session on #{MRSK.primary_host}"
75
- exec MRSK.app.bash(host: MRSK.primary_host)
76
- end
77
- end
68
+ when options[:reuse]
69
+ say "Get current version of running container...", :magenta unless options[:version]
70
+ using_version(options[:version] || current_running_version) do |version|
71
+ say "Launching command with version #{version} from existing container on #{MRSK.primary_host}...", :magenta
72
+ on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.execute_in_existing_container(cmd)) }
73
+ end
78
74
 
79
- desc "runner [EXPRESSION]", "Execute Rails runner with given expression"
80
- def runner(expression)
81
- on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.exec("bin/rails", "runner", "'#{expression}'")) }
75
+ else
76
+ say "Get most recent version available as an image...", :magenta unless options[:version]
77
+ using_version(options[:version] || most_recent_version_available) do |version|
78
+ say "Launching command with version #{version} from new container on #{MRSK.primary_host}...", :magenta
79
+ on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.execute_in_new_container(cmd)) }
80
+ end
81
+ end
82
82
  end
83
83
 
84
84
  desc "containers", "List all the app containers currently on servers"
@@ -86,6 +86,11 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
86
86
  on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.list_containers) }
87
87
  end
88
88
 
89
+ desc "images", "List all the app images currently on servers"
90
+ def images
91
+ on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.list_images) }
92
+ end
93
+
89
94
  desc "current", "Return the current running container ID"
90
95
  def current
91
96
  on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.current_container_id) }
@@ -122,16 +127,55 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
122
127
  end
123
128
 
124
129
  desc "remove", "Remove app containers and images from servers"
125
- option :only, default: "", desc: "Use 'containers' or 'images'"
126
130
  def remove
127
- case options[:only]
128
- when "containers"
129
- on(MRSK.hosts) { execute *MRSK.app.remove_containers }
130
- when "images"
131
- on(MRSK.hosts) { execute *MRSK.app.remove_images }
132
- else
133
- on(MRSK.hosts) { execute *MRSK.app.remove_containers }
134
- on(MRSK.hosts) { execute *MRSK.app.remove_images }
135
- end
131
+ remove_containers
132
+ remove_images
133
+ end
134
+
135
+ desc "remove_container [VERSION]", "Remove app container with given version from servers"
136
+ def remove_container(version)
137
+ on(MRSK.hosts) { execute *MRSK.app.remove_container(version: version) }
136
138
  end
139
+
140
+ desc "remove_containers", "Remove all app containers from servers"
141
+ def remove_containers
142
+ on(MRSK.hosts) { execute *MRSK.app.remove_containers }
143
+ end
144
+
145
+ desc "remove_images", "Remove all app images from servers"
146
+ def remove_images
147
+ on(MRSK.hosts) { execute *MRSK.app.remove_images }
148
+ end
149
+
150
+ desc "current_version", "Shows the version currently running"
151
+ def current_version
152
+ on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.current_running_version).strip }
153
+ end
154
+
155
+ private
156
+ def using_version(new_version)
157
+ if new_version
158
+ begin
159
+ old_version = MRSK.config.version
160
+ MRSK.config.version = new_version
161
+ yield new_version
162
+ ensure
163
+ MRSK.config.version = old_version
164
+ end
165
+ else
166
+ yield MRSK.config.version
167
+ end
168
+ end
169
+
170
+ def most_recent_version_available(host: MRSK.primary_host)
171
+ version = nil
172
+ on(host) { version = capture_with_info(*MRSK.app.most_recent_version_from_available_images).strip }
173
+ version.presence
174
+ end
175
+
176
+ def current_running_version(host: MRSK.primary_host)
177
+ version = nil
178
+ on(host) { version = capture_with_info(*MRSK.app.current_running_version).strip }
179
+ version.presence
180
+ end
137
181
  end
data/lib/mrsk/cli/main.rb CHANGED
@@ -21,12 +21,21 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
21
21
  desc "deploy", "Deploy the app to servers"
22
22
  def deploy
23
23
  print_runtime do
24
+ say "Ensure Docker is installed...", :magenta
24
25
  invoke "mrsk:cli:server:bootstrap"
26
+
27
+ say "Log into image registry...", :magenta
25
28
  invoke "mrsk:cli:registry:login"
29
+
30
+ say "Build and push app image...", :magenta
26
31
  invoke "mrsk:cli:build:deliver"
32
+
33
+ say "Ensure Traefik is running...", :magenta
27
34
  invoke "mrsk:cli:traefik:boot"
28
- invoke "mrsk:cli:app:stop"
35
+
29
36
  invoke "mrsk:cli:app:boot"
37
+
38
+ say "Prune old containers and images...", :magenta
30
39
  invoke "mrsk:cli:prune:all"
31
40
  end
32
41
  end
@@ -34,17 +43,23 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
34
43
  desc "redeploy", "Deploy new version of the app to servers (without bootstrapping servers, starting Traefik, pruning, and registry login)"
35
44
  def redeploy
36
45
  print_runtime do
46
+ say "Build and push app image...", :magenta
37
47
  invoke "mrsk:cli:build:deliver"
38
- invoke "mrsk:cli:app:stop"
48
+
39
49
  invoke "mrsk:cli:app:boot"
40
50
  end
41
51
  end
42
52
 
43
- desc "rollback [VERSION]", "Rollback the app to VERSION (that must already be on servers)"
53
+ desc "rollback [VERSION]", "Rollback the app to VERSION"
44
54
  def rollback(version)
55
+ MRSK.version = version
56
+
57
+ cli = self
58
+
59
+ cli.say "Stop current version, then start version #{version}...", :magenta
45
60
  on(MRSK.hosts) do
46
61
  execute *MRSK.app.stop, raise_on_non_zero_exit: false
47
- execute *MRSK.app.start(version: version)
62
+ execute *MRSK.app.start
48
63
  end
49
64
  end
50
65
 
@@ -86,6 +86,13 @@ class Mrsk::Commander
86
86
  SSHKit.config.output_verbosity = old_level
87
87
  end
88
88
 
89
+ # Test-induced damage!
90
+ def reset
91
+ @config = @config_file = @destination = @version = nil
92
+ @app = @builder = @traefik = @registry = @prune = nil
93
+ @verbosity = :info
94
+ end
95
+
89
96
  private
90
97
  def cascading_version
91
98
  version.presence || ENV["VERSION"] || `git rev-parse HEAD`.strip
@@ -33,6 +33,7 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
33
33
  docker :ps, *service_filter
34
34
  end
35
35
 
36
+
36
37
  def logs(since: nil, lines: nil, grep: nil)
37
38
  pipe \
38
39
  docker(:logs, service_name, (" --since #{since}" if since), (" -n #{lines}" if lines), "-t", "2>&1"),
@@ -46,14 +47,15 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
46
47
  ).join(" ")
47
48
  end
48
49
 
49
- def exec(*command, interactive: false)
50
+
51
+ def execute_in_existing_container(*command, interactive: false)
50
52
  docker :exec,
51
53
  ("-it" if interactive),
52
54
  service_name,
53
55
  *command
54
56
  end
55
57
 
56
- def run_exec(*command, interactive: false)
58
+ def execute_in_new_container(*command, interactive: false)
57
59
  docker :run,
58
60
  ("-it" if interactive),
59
61
  "--rm",
@@ -63,18 +65,19 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
63
65
  *command
64
66
  end
65
67
 
66
- def run_over_ssh(command)
67
- super command, host: host
68
+ def execute_in_existing_container_over_ssh(*command)
69
+ run_over_ssh execute_in_existing_container(*command, interactive: true).join(" ")
68
70
  end
69
71
 
70
- def exec_over_ssh(*command)
71
- run_over_ssh run_exec(*command, interactive: true).join(" ")
72
+ def execute_in_new_container_over_ssh(*command)
73
+ run_over_ssh execute_in_new_container(*command, interactive: true).join(" ")
72
74
  end
73
75
 
74
- def bash
75
- exec_over_ssh "bash"
76
+ def run_over_ssh(command)
77
+ super command, host: host
76
78
  end
77
79
 
80
+
78
81
  def ensure_local_file_present(local_file)
79
82
  if !local_file.is_a?(StringIO) && !Pathname.new(local_file).exist?
80
83
  raise "Missing file: #{local_file}"
@@ -7,7 +7,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
7
7
  docker :run,
8
8
  "-d",
9
9
  "--restart unless-stopped",
10
- "--name", config.service_with_version,
10
+ "--name", service_with_version,
11
11
  *rails_master_key_arg,
12
12
  *role.env_args,
13
13
  *config.volume_args,
@@ -16,22 +16,19 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
16
16
  role.cmd
17
17
  end
18
18
 
19
- def start(version: config.version)
20
- docker :start, "#{config.service}-#{version}"
21
- end
22
-
23
- def current_container_id
24
- docker :ps, "-q", *service_filter
19
+ def start
20
+ docker :start, service_with_version
25
21
  end
26
22
 
27
23
  def stop
28
- pipe current_container_id, "xargs docker stop"
24
+ pipe current_container_id, xargs(docker(:stop))
29
25
  end
30
26
 
31
27
  def info
32
28
  docker :ps, *service_filter
33
29
  end
34
30
 
31
+
35
32
  def logs(since: nil, lines: nil, grep: nil)
36
33
  pipe \
37
34
  current_container_id,
@@ -39,14 +36,23 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
39
36
  ("grep '#{grep}'" if grep)
40
37
  end
41
38
 
42
- def exec(*command, interactive: false)
39
+ def follow_logs(host:, grep: nil)
40
+ run_over_ssh pipe(
41
+ current_container_id,
42
+ "xargs docker logs -t -n 10 -f 2>&1",
43
+ (%(grep "#{grep}") if grep)
44
+ ).join(" "), host: host
45
+ end
46
+
47
+
48
+ def execute_in_existing_container(*command, interactive: false)
43
49
  docker :exec,
44
50
  ("-it" if interactive),
45
51
  config.service_with_version,
46
52
  *command
47
53
  end
48
54
 
49
- def run_exec(*command, interactive: false)
55
+ def execute_in_new_container(*command, interactive: false)
50
56
  docker :run,
51
57
  ("-it" if interactive),
52
58
  "--rm",
@@ -57,39 +63,70 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
57
63
  *command
58
64
  end
59
65
 
60
- def exec_over_ssh(*command, host:)
61
- run_over_ssh run_exec(*command, interactive: true).join(" "), host: host
66
+ def execute_in_existing_container_over_ssh(*command, host:)
67
+ run_over_ssh execute_in_existing_container(*command, interactive: true).join(" "), host: host
62
68
  end
63
69
 
64
- def follow_logs(host:, grep: nil)
65
- run_over_ssh pipe(
66
- current_container_id,
67
- "xargs docker logs -t -n 10 -f 2>&1",
68
- (%(grep "#{grep}") if grep)
69
- ).join(" "), host: host
70
+ def execute_in_new_container_over_ssh(*command, host:)
71
+ run_over_ssh execute_in_new_container(*command, interactive: true).join(" "), host: host
70
72
  end
71
73
 
72
- def console(host:)
73
- exec_over_ssh "bin/rails", "c", host: host
74
+
75
+ def current_container_id
76
+ docker :ps, "-q", *service_filter
77
+ end
78
+
79
+ def container_id_for(container_name:)
80
+ docker :container, :ls, "-a", "-f", "name=#{container_name}", "-q"
74
81
  end
75
82
 
76
- def bash(host:)
77
- exec_over_ssh "bash", host: host
83
+ def current_running_version
84
+ # FIXME: Find more graceful way to extract the version from "app-version" than using sed and tail!
85
+ pipe \
86
+ docker(:ps, "--filter", "label=service=#{config.service}", "--format", '"{{.Names}}"'),
87
+ %(sed 's/-/\\n/g'),
88
+ "tail -n 1"
78
89
  end
79
90
 
91
+ def most_recent_version_from_available_images
92
+ pipe \
93
+ docker(:image, :ls, "--format", '"{{.Tag}}"', config.repository),
94
+ "head -n 1"
95
+ end
96
+
97
+
80
98
  def list_containers
81
99
  docker :container, :ls, "-a", *service_filter
82
100
  end
83
101
 
102
+ def remove_container(version:)
103
+ pipe \
104
+ container_id_for(container_name: service_with_version(version)),
105
+ xargs(docker(:container, :rm))
106
+ end
107
+
84
108
  def remove_containers
85
109
  docker :container, :prune, "-f", *service_filter
86
110
  end
87
111
 
112
+ def list_images
113
+ docker :image, :ls, config.repository
114
+ end
115
+
88
116
  def remove_images
89
117
  docker :image, :prune, "-a", "-f", *service_filter
90
118
  end
91
119
 
120
+
92
121
  private
122
+ def service_with_version(version = nil)
123
+ if version
124
+ "#{config.service}-#{version}"
125
+ else
126
+ config.service_with_version
127
+ end
128
+ end
129
+
93
130
  def service_filter
94
131
  [ "--filter", "label=service=#{config.service}" ]
95
132
  end
@@ -28,6 +28,10 @@ module Mrsk::Commands
28
28
  combine *commands, by: "|"
29
29
  end
30
30
 
31
+ def xargs(command)
32
+ [ :xargs, command ].flatten
33
+ end
34
+
31
35
  def docker(*args)
32
36
  args.compact.unshift :docker
33
37
  end
@@ -1,4 +1,4 @@
1
- class Mrsk::Configuration::Assessory
1
+ class Mrsk::Configuration::Accessory
2
2
  delegate :argumentize, :argumentize_env_with_secrets, to: Mrsk::Utils
3
3
 
4
4
  attr_accessor :name, :specifics
@@ -9,6 +9,7 @@ class Mrsk::Configuration
9
9
  delegate :service, :image, :servers, :env, :labels, :registry, :builder, to: :raw_config, allow_nil: true
10
10
  delegate :argumentize, :argumentize_env_with_secrets, to: Mrsk::Utils
11
11
 
12
+ attr_accessor :version
12
13
  attr_accessor :raw_config
13
14
 
14
15
  class << self
@@ -52,7 +53,7 @@ class Mrsk::Configuration
52
53
  end
53
54
 
54
55
  def accessories
55
- @accessories ||= raw_config.accessories&.keys&.collect { |name| Mrsk::Configuration::Assessory.new(name, config: self) } || []
56
+ @accessories ||= raw_config.accessories&.keys&.collect { |name| Mrsk::Configuration::Accessory.new(name, config: self) } || []
56
57
  end
57
58
 
58
59
  def accessory(name)
@@ -73,10 +74,6 @@ class Mrsk::Configuration
73
74
  end
74
75
 
75
76
 
76
- def version
77
- @version
78
- end
79
-
80
77
  def repository
81
78
  [ raw_config.registry["server"], image ].compact.join("/")
82
79
  end
data/lib/mrsk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mrsk
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mrsk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-01 00:00:00.000000000 Z
11
+ date: 2023-02-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  - !ruby/object:Gem::Version
128
128
  version: '0'
129
129
  requirements: []
130
- rubygems_version: 3.4.5
130
+ rubygems_version: 3.4.6
131
131
  signing_key:
132
132
  specification_version: 4
133
133
  summary: Deploy Rails apps in containers to servers running Docker with zero downtime.