mrsk 0.9.1 → 0.10.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/README.md +158 -13
- data/lib/mrsk/cli/accessory.rb +87 -64
- data/lib/mrsk/cli/app.rb +103 -65
- data/lib/mrsk/cli/base.rb +46 -9
- data/lib/mrsk/cli/build.rb +40 -30
- data/lib/mrsk/cli/lock.rb +37 -0
- data/lib/mrsk/cli/main.rb +91 -49
- data/lib/mrsk/cli/prune.rb +14 -8
- data/lib/mrsk/cli/server.rb +9 -7
- data/lib/mrsk/cli/templates/deploy.yml +2 -0
- data/lib/mrsk/cli/traefik.rb +37 -21
- data/lib/mrsk/commander.rb +40 -34
- data/lib/mrsk/commands/accessory.rb +9 -6
- data/lib/mrsk/commands/app.rb +39 -37
- data/lib/mrsk/commands/auditor.rb +20 -5
- data/lib/mrsk/commands/base.rb +6 -4
- data/lib/mrsk/commands/builder/base.rb +1 -0
- data/lib/mrsk/commands/builder/native.rb +2 -1
- data/lib/mrsk/commands/healthcheck.rb +5 -3
- data/lib/mrsk/commands/lock.rb +63 -0
- data/lib/mrsk/commands/traefik.rb +13 -7
- data/lib/mrsk/configuration/accessory.rb +53 -7
- data/lib/mrsk/configuration/role.rb +13 -4
- data/lib/mrsk/configuration.rb +59 -17
- data/lib/mrsk/utils.rb +18 -2
- data/lib/mrsk/version.rb +1 -1
- data/lib/mrsk.rb +1 -0
- metadata +47 -3
data/lib/mrsk/cli/main.rb
CHANGED
@@ -1,77 +1,104 @@
|
|
1
1
|
class Mrsk::Cli::Main < Mrsk::Cli::Base
|
2
2
|
desc "setup", "Setup all accessories and deploy app to servers"
|
3
3
|
def setup
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
with_lock do
|
5
|
+
print_runtime do
|
6
|
+
invoke "mrsk:cli:server:bootstrap"
|
7
|
+
invoke "mrsk:cli:accessory:boot", [ "all" ]
|
8
|
+
deploy
|
9
|
+
end
|
8
10
|
end
|
9
11
|
end
|
10
12
|
|
11
13
|
desc "deploy", "Deploy app to servers"
|
14
|
+
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
12
15
|
def deploy
|
13
|
-
|
14
|
-
|
15
|
-
invoke "mrsk:cli:server:bootstrap"
|
16
|
+
with_lock do
|
17
|
+
invoke_options = deploy_options
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
runtime = print_runtime do
|
20
|
+
say "Ensure curl and Docker are installed...", :magenta
|
21
|
+
invoke "mrsk:cli:server:bootstrap", [], invoke_options
|
19
22
|
|
20
|
-
|
21
|
-
|
23
|
+
say "Log into image registry...", :magenta
|
24
|
+
invoke "mrsk:cli:registry:login", [], invoke_options
|
22
25
|
|
23
|
-
|
24
|
-
|
26
|
+
if options[:skip_push]
|
27
|
+
say "Pull app image...", :magenta
|
28
|
+
invoke "mrsk:cli:build:pull", [], invoke_options
|
29
|
+
else
|
30
|
+
say "Build and push app image...", :magenta
|
31
|
+
invoke "mrsk:cli:build:deliver", [], invoke_options
|
32
|
+
end
|
25
33
|
|
26
|
-
|
27
|
-
|
34
|
+
say "Ensure Traefik is running...", :magenta
|
35
|
+
invoke "mrsk:cli:traefik:boot", [], invoke_options
|
28
36
|
|
29
|
-
|
37
|
+
say "Ensure app can pass healthcheck...", :magenta
|
38
|
+
invoke "mrsk:cli:healthcheck:perform", [], invoke_options
|
30
39
|
|
31
|
-
|
32
|
-
invoke "mrsk:cli:prune:all"
|
33
|
-
end
|
40
|
+
invoke "mrsk:cli:app:boot", [], invoke_options
|
34
41
|
|
35
|
-
|
42
|
+
say "Prune old containers and images...", :magenta
|
43
|
+
invoke "mrsk:cli:prune:all", [], invoke_options
|
44
|
+
end
|
45
|
+
|
46
|
+
audit_broadcast "Deployed #{service_version} in #{runtime.round} seconds" unless options[:skip_broadcast]
|
47
|
+
end
|
36
48
|
end
|
37
49
|
|
38
50
|
desc "redeploy", "Deploy app to servers without bootstrapping servers, starting Traefik, pruning, and registry login"
|
51
|
+
option :skip_push, aliases: "-P", type: :boolean, default: false, desc: "Skip image build and push"
|
39
52
|
def redeploy
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
53
|
+
with_lock do
|
54
|
+
invoke_options = deploy_options
|
55
|
+
|
56
|
+
runtime = print_runtime do
|
57
|
+
if options[:skip_push]
|
58
|
+
say "Pull app image...", :magenta
|
59
|
+
invoke "mrsk:cli:build:pull", [], invoke_options
|
60
|
+
else
|
61
|
+
say "Build and push app image...", :magenta
|
62
|
+
invoke "mrsk:cli:build:deliver", [], invoke_options
|
63
|
+
end
|
64
|
+
|
65
|
+
say "Ensure app can pass healthcheck...", :magenta
|
66
|
+
invoke "mrsk:cli:healthcheck:perform", [], invoke_options
|
67
|
+
|
68
|
+
invoke "mrsk:cli:app:boot", [], invoke_options
|
69
|
+
end
|
46
70
|
|
47
|
-
|
71
|
+
audit_broadcast "Redeployed #{service_version} in #{runtime.round} seconds" unless options[:skip_broadcast]
|
48
72
|
end
|
49
|
-
|
50
|
-
audit_broadcast "Redeployed app in #{runtime.to_i} seconds" unless options[:skip_broadcast]
|
51
73
|
end
|
52
74
|
|
53
75
|
desc "rollback [VERSION]", "Rollback app to VERSION"
|
54
76
|
def rollback(version)
|
55
|
-
|
77
|
+
with_lock do
|
78
|
+
MRSK.config.version = version
|
56
79
|
|
57
|
-
|
58
|
-
|
80
|
+
if container_name_available?(MRSK.config.service_with_version)
|
81
|
+
say "Start version #{version}, then wait #{MRSK.config.readiness_delay}s for app to boot before stopping the old version...", :magenta
|
59
82
|
|
60
|
-
|
83
|
+
cli = self
|
84
|
+
old_version = nil
|
61
85
|
|
62
|
-
|
63
|
-
|
86
|
+
on(MRSK.hosts) do |host|
|
87
|
+
old_version = capture_with_info(*MRSK.app.current_running_version).strip.presence
|
64
88
|
|
65
|
-
|
89
|
+
execute *MRSK.app.start
|
66
90
|
|
67
|
-
|
91
|
+
if old_version
|
92
|
+
sleep MRSK.config.readiness_delay
|
68
93
|
|
69
|
-
|
70
|
-
|
94
|
+
execute *MRSK.app.stop(version: old_version), raise_on_non_zero_exit: false
|
95
|
+
end
|
96
|
+
end
|
71
97
|
|
72
|
-
|
73
|
-
|
74
|
-
|
98
|
+
audit_broadcast "Rolled back #{service_version(Mrsk::Utils.abbreviate_version(old_version))} to #{service_version}" unless options[:skip_broadcast]
|
99
|
+
else
|
100
|
+
say "The app version '#{version}' is not available as a container (use 'mrsk app containers' for available versions)", :red
|
101
|
+
end
|
75
102
|
end
|
76
103
|
end
|
77
104
|
|
@@ -119,8 +146,10 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
|
|
119
146
|
puts "Binstub already exists in bin/mrsk (remove first to create a new one)"
|
120
147
|
else
|
121
148
|
puts "Adding MRSK to Gemfile and bundle..."
|
122
|
-
|
123
|
-
|
149
|
+
run_locally do
|
150
|
+
execute :bundle, :add, :mrsk
|
151
|
+
execute :bundle, :binstubs, :mrsk
|
152
|
+
end
|
124
153
|
puts "Created binstub file in bin/mrsk"
|
125
154
|
end
|
126
155
|
end
|
@@ -142,11 +171,13 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
|
|
142
171
|
desc "remove", "Remove Traefik, app, accessories, and registry session from servers"
|
143
172
|
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
144
173
|
def remove
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
174
|
+
with_lock do
|
175
|
+
if options[:confirmed] || ask("This will remove all containers and images. Are you sure?", limited_to: %w( y N ), default: "N") == "y"
|
176
|
+
invoke "mrsk:cli:traefik:remove", [], options.without(:confirmed)
|
177
|
+
invoke "mrsk:cli:app:remove", [], options.without(:confirmed)
|
178
|
+
invoke "mrsk:cli:accessory:remove", [ "all" ], options
|
179
|
+
invoke "mrsk:cli:registry:logout", [], options.without(:confirmed)
|
180
|
+
end
|
150
181
|
end
|
151
182
|
end
|
152
183
|
|
@@ -179,10 +210,21 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
|
|
179
210
|
desc "traefik", "Manage Traefik load balancer"
|
180
211
|
subcommand "traefik", Mrsk::Cli::Traefik
|
181
212
|
|
213
|
+
desc "lock", "Manage the deploy lock"
|
214
|
+
subcommand "lock", Mrsk::Cli::Lock
|
215
|
+
|
182
216
|
private
|
183
217
|
def container_name_available?(container_name, host: MRSK.primary_host)
|
184
218
|
container_names = nil
|
185
219
|
on(host) { container_names = capture_with_info(*MRSK.app.list_container_names).split("\n") }
|
186
220
|
Array(container_names).include?(container_name)
|
187
221
|
end
|
222
|
+
|
223
|
+
def deploy_options
|
224
|
+
{ "version" => MRSK.config.version }.merge(options.without("skip_push"))
|
225
|
+
end
|
226
|
+
|
227
|
+
def service_version(version = MRSK.config.abbreviated_version)
|
228
|
+
[ MRSK.config.service, version ].compact.join("@")
|
229
|
+
end
|
188
230
|
end
|
data/lib/mrsk/cli/prune.rb
CHANGED
@@ -1,23 +1,29 @@
|
|
1
1
|
class Mrsk::Cli::Prune < Mrsk::Cli::Base
|
2
2
|
desc "all", "Prune unused images and stopped containers"
|
3
3
|
def all
|
4
|
-
|
5
|
-
|
4
|
+
with_lock do
|
5
|
+
containers
|
6
|
+
images
|
7
|
+
end
|
6
8
|
end
|
7
9
|
|
8
10
|
desc "images", "Prune unused images older than 7 days"
|
9
11
|
def images
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
with_lock do
|
13
|
+
on(MRSK.hosts) do
|
14
|
+
execute *MRSK.auditor.record("Pruned images"), verbosity: :debug
|
15
|
+
execute *MRSK.prune.images
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
16
20
|
desc "containers", "Prune stopped containers older than 3 days"
|
17
21
|
def containers
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
with_lock do
|
23
|
+
on(MRSK.hosts) do
|
24
|
+
execute *MRSK.auditor.record("Pruned containers"), verbosity: :debug
|
25
|
+
execute *MRSK.prune.containers
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
data/lib/mrsk/cli/server.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
class Mrsk::Cli::Server < Mrsk::Cli::Base
|
2
2
|
desc "bootstrap", "Ensure curl and Docker are installed on servers"
|
3
3
|
def bootstrap
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
with_lock do
|
5
|
+
on(MRSK.hosts + MRSK.accessory_hosts) do
|
6
|
+
dependencies_to_install = Array.new.tap do |dependencies|
|
7
|
+
dependencies << "curl" unless execute "which curl", raise_on_non_zero_exit: false
|
8
|
+
dependencies << "docker.io" unless execute "which docker", raise_on_non_zero_exit: false
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
if dependencies_to_install.any?
|
12
|
+
execute "apt-get update -y && apt-get install #{dependencies_to_install.join(" ")} -y"
|
13
|
+
end
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
@@ -13,6 +13,8 @@ registry:
|
|
13
13
|
# Specify the registry server, if you're not using Docker Hub
|
14
14
|
# server: registry.digitalocean.com / ghcr.io / ...
|
15
15
|
username: my-user
|
16
|
+
|
17
|
+
# Always use an access token rather than real password when possible.
|
16
18
|
password:
|
17
19
|
- MRSK_REGISTRY_PASSWORD
|
18
20
|
|
data/lib/mrsk/cli/traefik.rb
CHANGED
@@ -1,36 +1,46 @@
|
|
1
1
|
class Mrsk::Cli::Traefik < Mrsk::Cli::Base
|
2
2
|
desc "boot", "Boot Traefik on servers"
|
3
3
|
def boot
|
4
|
-
|
4
|
+
with_lock do
|
5
|
+
on(MRSK.traefik_hosts) { execute *MRSK.traefik.run, raise_on_non_zero_exit: false }
|
6
|
+
end
|
5
7
|
end
|
6
8
|
|
7
9
|
desc "reboot", "Reboot Traefik on servers (stop container, remove container, start new container)"
|
8
10
|
def reboot
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
with_lock do
|
12
|
+
stop
|
13
|
+
remove_container
|
14
|
+
boot
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
desc "start", "Start existing Traefik container on servers"
|
15
19
|
def start
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
with_lock do
|
21
|
+
on(MRSK.traefik_hosts) do
|
22
|
+
execute *MRSK.auditor.record("Started traefik"), verbosity: :debug
|
23
|
+
execute *MRSK.traefik.start, raise_on_non_zero_exit: false
|
24
|
+
end
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
22
28
|
desc "stop", "Stop existing Traefik container on servers"
|
23
29
|
def stop
|
24
|
-
|
25
|
-
|
26
|
-
|
30
|
+
with_lock do
|
31
|
+
on(MRSK.traefik_hosts) do
|
32
|
+
execute *MRSK.auditor.record("Stopped traefik"), verbosity: :debug
|
33
|
+
execute *MRSK.traefik.stop, raise_on_non_zero_exit: false
|
34
|
+
end
|
27
35
|
end
|
28
36
|
end
|
29
37
|
|
30
38
|
desc "restart", "Restart existing Traefik container on servers"
|
31
39
|
def restart
|
32
|
-
|
33
|
-
|
40
|
+
with_lock do
|
41
|
+
stop
|
42
|
+
start
|
43
|
+
end
|
34
44
|
end
|
35
45
|
|
36
46
|
desc "details", "Show details about Traefik container from servers"
|
@@ -64,24 +74,30 @@ class Mrsk::Cli::Traefik < Mrsk::Cli::Base
|
|
64
74
|
|
65
75
|
desc "remove", "Remove Traefik container and image from servers"
|
66
76
|
def remove
|
67
|
-
|
68
|
-
|
69
|
-
|
77
|
+
with_lock do
|
78
|
+
stop
|
79
|
+
remove_container
|
80
|
+
remove_image
|
81
|
+
end
|
70
82
|
end
|
71
83
|
|
72
84
|
desc "remove_container", "Remove Traefik container from servers", hide: true
|
73
85
|
def remove_container
|
74
|
-
|
75
|
-
|
76
|
-
|
86
|
+
with_lock do
|
87
|
+
on(MRSK.traefik_hosts) do
|
88
|
+
execute *MRSK.auditor.record("Removed traefik container"), verbosity: :debug
|
89
|
+
execute *MRSK.traefik.remove_container
|
90
|
+
end
|
77
91
|
end
|
78
92
|
end
|
79
93
|
|
80
94
|
desc "remove_container", "Remove Traefik image from servers", hide: true
|
81
95
|
def remove_image
|
82
|
-
|
83
|
-
|
84
|
-
|
96
|
+
with_lock do
|
97
|
+
on(MRSK.traefik_hosts) do
|
98
|
+
execute *MRSK.auditor.record("Removed traefik image"), verbosity: :debug
|
99
|
+
execute *MRSK.traefik.remove_image
|
100
|
+
end
|
85
101
|
end
|
86
102
|
end
|
87
103
|
end
|
data/lib/mrsk/commander.rb
CHANGED
@@ -1,35 +1,57 @@
|
|
1
1
|
require "active_support/core_ext/enumerable"
|
2
|
+
require "active_support/core_ext/module/delegation"
|
2
3
|
|
3
4
|
class Mrsk::Commander
|
4
|
-
attr_accessor :
|
5
|
+
attr_accessor :verbosity, :lock_count
|
5
6
|
|
6
|
-
def initialize
|
7
|
-
|
7
|
+
def initialize
|
8
|
+
self.verbosity = :info
|
9
|
+
self.lock_count = 0
|
8
10
|
end
|
9
11
|
|
10
12
|
def config
|
11
|
-
@config ||=
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
@config ||= Mrsk::Configuration.create_from(**@config_kwargs).tap do |config|
|
14
|
+
@config_kwargs = nil
|
15
|
+
configure_sshkit_with(config)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def configure(**kwargs)
|
20
|
+
@config, @config_kwargs = nil, kwargs
|
15
21
|
end
|
16
22
|
|
17
|
-
|
23
|
+
attr_reader :specific_roles, :specific_hosts
|
18
24
|
|
19
25
|
def specific_primary!
|
20
26
|
self.specific_hosts = [ config.primary_web_host ]
|
21
27
|
end
|
22
28
|
|
23
29
|
def specific_roles=(role_names)
|
24
|
-
|
30
|
+
@specific_roles = config.roles.select { |r| role_names.include?(r.name) } if role_names.present?
|
31
|
+
end
|
32
|
+
|
33
|
+
def specific_hosts=(hosts)
|
34
|
+
@specific_hosts = config.all_hosts & hosts if hosts.present?
|
25
35
|
end
|
26
36
|
|
27
37
|
def primary_host
|
28
38
|
specific_hosts&.first || config.primary_web_host
|
29
39
|
end
|
30
40
|
|
41
|
+
def roles
|
42
|
+
(specific_roles || config.roles).select do |role|
|
43
|
+
((specific_hosts || config.all_hosts) & role.hosts).any?
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
31
47
|
def hosts
|
32
|
-
specific_hosts || config.all_hosts
|
48
|
+
(specific_hosts || config.all_hosts).select do |host|
|
49
|
+
(specific_roles || config.roles).flat_map(&:hosts).include?(host)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def roles_on(host)
|
54
|
+
roles.select { |role| role.hosts.include?(host.to_s) }.map(&:name)
|
33
55
|
end
|
34
56
|
|
35
57
|
def traefik_hosts
|
@@ -37,7 +59,7 @@ class Mrsk::Commander
|
|
37
59
|
end
|
38
60
|
|
39
61
|
def accessory_hosts
|
40
|
-
specific_hosts || config.accessories.
|
62
|
+
specific_hosts || config.accessories.flat_map(&:hosts)
|
41
63
|
end
|
42
64
|
|
43
65
|
def accessory_names
|
@@ -45,16 +67,16 @@ class Mrsk::Commander
|
|
45
67
|
end
|
46
68
|
|
47
69
|
|
48
|
-
def app
|
49
|
-
|
70
|
+
def app(role: nil)
|
71
|
+
Mrsk::Commands::App.new(config, role: role)
|
50
72
|
end
|
51
73
|
|
52
74
|
def accessory(name)
|
53
75
|
Mrsk::Commands::Accessory.new(config, name: name)
|
54
76
|
end
|
55
77
|
|
56
|
-
def auditor
|
57
|
-
|
78
|
+
def auditor(role: nil)
|
79
|
+
Mrsk::Commands::Auditor.new(config, role: role)
|
58
80
|
end
|
59
81
|
|
60
82
|
def builder
|
@@ -77,6 +99,9 @@ class Mrsk::Commander
|
|
77
99
|
@traefik ||= Mrsk::Commands::Traefik.new(config)
|
78
100
|
end
|
79
101
|
|
102
|
+
def lock
|
103
|
+
@lock ||= Mrsk::Commands::Lock.new(config)
|
104
|
+
end
|
80
105
|
|
81
106
|
def with_verbosity(level)
|
82
107
|
old_level = self.verbosity
|
@@ -90,26 +115,7 @@ class Mrsk::Commander
|
|
90
115
|
SSHKit.config.output_verbosity = old_level
|
91
116
|
end
|
92
117
|
|
93
|
-
# Test-induced damage!
|
94
|
-
def reset
|
95
|
-
@config = @config_file = @destination = @version = nil
|
96
|
-
@app = @builder = @traefik = @registry = @prune = @auditor = nil
|
97
|
-
@verbosity = :info
|
98
|
-
end
|
99
|
-
|
100
118
|
private
|
101
|
-
def cascading_version
|
102
|
-
version.presence || ENV["VERSION"] || current_commit_hash
|
103
|
-
end
|
104
|
-
|
105
|
-
def current_commit_hash
|
106
|
-
if system("git rev-parse")
|
107
|
-
`git rev-parse HEAD`.strip
|
108
|
-
else
|
109
|
-
raise "Can't use commit hash as version, no git repository found in #{Dir.pwd}"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
119
|
# Lazy setup of SSHKit
|
114
120
|
def configure_sshkit_with(config)
|
115
121
|
SSHKit::Backend::Netssh.configure { |ssh| ssh.ssh_options = config.ssh_options }
|
@@ -1,6 +1,7 @@
|
|
1
1
|
class Mrsk::Commands::Accessory < Mrsk::Commands::Base
|
2
2
|
attr_reader :accessory_config
|
3
|
-
delegate :service_name, :image, :
|
3
|
+
delegate :service_name, :image, :hosts, :port, :files, :directories, :cmd,
|
4
|
+
:publish_args, :env_args, :volume_args, :label_args, :option_args, to: :accessory_config
|
4
5
|
|
5
6
|
def initialize(config, name:)
|
6
7
|
super(config)
|
@@ -12,12 +13,14 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
|
|
12
13
|
"--name", service_name,
|
13
14
|
"--detach",
|
14
15
|
"--restart", "unless-stopped",
|
15
|
-
|
16
|
-
|
16
|
+
*config.logging_args,
|
17
|
+
*publish_args,
|
17
18
|
*env_args,
|
18
19
|
*volume_args,
|
19
20
|
*label_args,
|
20
|
-
|
21
|
+
*option_args,
|
22
|
+
image,
|
23
|
+
cmd
|
21
24
|
end
|
22
25
|
|
23
26
|
def start
|
@@ -73,7 +76,7 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
|
|
73
76
|
end
|
74
77
|
|
75
78
|
def run_over_ssh(command)
|
76
|
-
super command, host:
|
79
|
+
super command, host: hosts.first
|
77
80
|
end
|
78
81
|
|
79
82
|
|
@@ -100,7 +103,7 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
|
|
100
103
|
end
|
101
104
|
|
102
105
|
def remove_image
|
103
|
-
docker :image, :
|
106
|
+
docker :image, :rm, "--force", image
|
104
107
|
end
|
105
108
|
|
106
109
|
private
|