mrsk 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d8f3425abee6c013a917d960080160e02009976a7980bcf094bad847eb62631a
|
4
|
+
data.tar.gz: 153d6c0c396545ce451ac41470de8c325438331c05c0927c93f41d634f039c0d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e4de84f5283ee1dde444b9a2107e9d67ae7229d1c8ddc1b89679767ea8a5ba1568ace8f4f144712ceefcff15d7c85acbcd43079225b741d4b551c40aed55a7a4
|
7
|
+
data.tar.gz: b8bfca36906d4b6cfe3f1b332ed9fae1bd6077a10d4388a449a12bb5f308267681700b31d8d89a08a99fa784054f03167d4f776816b6aaff29ec5216bb7e5287
|
data/README.md
CHANGED
@@ -4,9 +4,23 @@ MRSK deploys web apps anywhere from bare metal to cloud VMs using Docker with ze
|
|
4
4
|
|
5
5
|
Watch the screencast: https://www.youtube.com/watch?v=LL1cV2FXZ5I
|
6
6
|
|
7
|
+
Join us on Discord: https://discord.gg/YgHVT7GCXS
|
8
|
+
|
7
9
|
## Installation
|
8
10
|
|
9
|
-
|
11
|
+
If you have a Ruby environment available, you can install MRSK globally with:
|
12
|
+
|
13
|
+
```sh
|
14
|
+
gem install mrsk
|
15
|
+
```
|
16
|
+
|
17
|
+
...otherwise, you can run a dockerized version via an alias (add this to your ${SHELL}rc to simplify re-use):
|
18
|
+
|
19
|
+
```sh
|
20
|
+
alias mrsk='docker run --rm -it -v $HOME/.ssh:/root/.ssh -v /var/run/docker.sock:/var/run/docker.sock -v ${PWD}/:/workdir ghcr.io/mrsked/mrsk'
|
21
|
+
```
|
22
|
+
|
23
|
+
Then, inside your app directory, run `mrsk init` (or `mrsk init --bundle` within Rails apps where you want a bin/mrsk binstub). Now edit the new file `config/deploy.yml`. It could look as simple as this:
|
10
24
|
|
11
25
|
```yaml
|
12
26
|
service: hey
|
@@ -23,7 +37,7 @@ env:
|
|
23
37
|
- RAILS_MASTER_KEY
|
24
38
|
```
|
25
39
|
|
26
|
-
Then edit your `.env` file to add your registry password as `MRSK_REGISTRY_PASSWORD` (and your `RAILS_MASTER_KEY` for production with a Rails app).
|
40
|
+
Then edit your `.env` file to add your registry password as `MRSK_REGISTRY_PASSWORD` (and your `RAILS_MASTER_KEY` for production with a Rails app).
|
27
41
|
|
28
42
|
Now you're ready to deploy to the servers:
|
29
43
|
|
@@ -34,7 +48,7 @@ mrsk deploy
|
|
34
48
|
This will:
|
35
49
|
|
36
50
|
1. Connect to the servers over SSH (using root by default, authenticated by your ssh key)
|
37
|
-
2. Install Docker on any server that might be missing it (using apt-get)
|
51
|
+
2. Install Docker on any server that might be missing it (using apt-get): root access is needed via ssh for this.
|
38
52
|
3. Log into the registry both locally and remotely
|
39
53
|
4. Build the image using the standard Dockerfile in the root of the application.
|
40
54
|
5. Push the image to the registry.
|
@@ -67,6 +81,16 @@ Docker Swarm is much simpler than Kubernetes, but it's still built on the same d
|
|
67
81
|
|
68
82
|
Ultimately, there are a myriad of ways to deploy web apps, but this is the toolkit we're using at [37signals](https://37signals.com) to bring [HEY](https://www.hey.com) [home from the cloud](https://world.hey.com/dhh/why-we-re-leaving-the-cloud-654b47e0) without losing the advantages of modern containerization tooling.
|
69
83
|
|
84
|
+
## Running MRSK from Docker
|
85
|
+
|
86
|
+
MRSK is packaged up in a Docker container similarly to [rails/docked](https://github.com/rails/docked). This will allow you to run MRSK (from your application directory) without having to install any dependencies other than Docker. Add the following alias to your profile configuration to make working with the container more convenient:
|
87
|
+
|
88
|
+
```bash
|
89
|
+
alias mrsk="docker run -it --rm -v '${PWD}:/workdir' -v '${SSH_AUTH_SOCK}:/ssh-agent' -v /var/run/docker.sock:/var/run/docker.sock -e 'SSH_AUTH_SOCK=/ssh-agent' ghcr.io/mrsked/mrsk:latest"
|
90
|
+
```
|
91
|
+
|
92
|
+
Since MRSK uses SSH to establish a remote connection, it will need access to your SSH agent. The above command uses a volume mount to make it available inside the container and configures the SSH agent inside the container to make use of it.
|
93
|
+
|
70
94
|
## Configuration
|
71
95
|
|
72
96
|
### Using .env file to load required environment variables
|
@@ -99,9 +123,9 @@ If you need separate env variables for different destinations, you can set them
|
|
99
123
|
|
100
124
|
#### Bitwarden as a secret store
|
101
125
|
|
102
|
-
If you are using open source secret store like bitwarden, you can create `.env.erb` as a template which looks up the secrets.
|
126
|
+
If you are using open source secret store like bitwarden, you can create `.env.erb` as a template which looks up the secrets.
|
103
127
|
|
104
|
-
You can store `SOME_SECRET` in a secure note in bitwarden vault.
|
128
|
+
You can store `SOME_SECRET` in a secure note in bitwarden vault.
|
105
129
|
|
106
130
|
```
|
107
131
|
$ bw list items --search SOME_SECRET | jq
|
@@ -140,7 +164,7 @@ SOME_SECRET=<%= `bw get notes 123123123-1232-4224-222f-234234234234 --session #{
|
|
140
164
|
<% else raise ArgumentError, "session_token token missing" end %>
|
141
165
|
```
|
142
166
|
|
143
|
-
Then everyone deploying the app can run `mrsk envify` and mrsk will generate `.env`
|
167
|
+
Then everyone deploying the app can run `mrsk envify` and mrsk will generate `.env`
|
144
168
|
|
145
169
|
|
146
170
|
### Using another registry than Docker Hub
|
@@ -150,9 +174,9 @@ The default registry is Docker Hub, but you can change it using `registry/server
|
|
150
174
|
```yaml
|
151
175
|
registry:
|
152
176
|
server: registry.digitalocean.com
|
153
|
-
username:
|
177
|
+
username:
|
154
178
|
- DOCKER_REGISTRY_TOKEN
|
155
|
-
password:
|
179
|
+
password:
|
156
180
|
- DOCKER_REGISTRY_TOKEN
|
157
181
|
```
|
158
182
|
|
@@ -222,6 +246,12 @@ volumes:
|
|
222
246
|
- "/local/path:/container/path"
|
223
247
|
```
|
224
248
|
|
249
|
+
### MRSK env variables
|
250
|
+
|
251
|
+
The following env variables are set when your container runs:
|
252
|
+
|
253
|
+
`MRSK_CONTAINER_NAME` : this contains the current container name and version
|
254
|
+
|
225
255
|
### Using different roles for servers
|
226
256
|
|
227
257
|
If your application uses separate hosts for running jobs or other roles beyond the default web running, you can specify these hosts in a dedicated role with a new entrypoint command like so:
|
@@ -256,12 +286,12 @@ servers:
|
|
256
286
|
|
257
287
|
You can specialize the default Traefik rules by setting labels on the containers that are being started:
|
258
288
|
|
259
|
-
```
|
289
|
+
```yaml
|
260
290
|
labels:
|
261
|
-
traefik.http.routers.hey.rule: Host(
|
291
|
+
traefik.http.routers.hey.rule: Host(`app.hey.com`)
|
262
292
|
```
|
263
293
|
|
264
|
-
Note: The
|
294
|
+
Note: The backticks are needed to ensure the rule is passed in correctly and not treated as command substitution by Bash!
|
265
295
|
|
266
296
|
This allows you to run multiple applications on the same server sharing the same Traefik instance and port.
|
267
297
|
See https://doc.traefik.io/traefik/routing/routers/#rule for a full list of available routing rules.
|
@@ -303,6 +333,29 @@ servers:
|
|
303
333
|
|
304
334
|
That'll start the job containers with `docker run ... --cap-add --cpu-count 4 ...`.
|
305
335
|
|
336
|
+
### Configuring logging
|
337
|
+
|
338
|
+
You can configure the logging driver and options passed to Docker using `logging`:
|
339
|
+
|
340
|
+
```yaml
|
341
|
+
logging:
|
342
|
+
driver: awslogs
|
343
|
+
options:
|
344
|
+
awslogs-region: "eu-central-2"
|
345
|
+
awslogs-group: "my-app"
|
346
|
+
```
|
347
|
+
|
348
|
+
If nothing is configured, the default option `max-size=10m` is used for all containers. The default logging driver of Docker is `json-file`.
|
349
|
+
|
350
|
+
### Using a different stop wait time
|
351
|
+
|
352
|
+
On a new deploy, each old running container is gracefully shut down with a `SIGTERM`, and after a grace period of `10` seconds a `SIGKILL` is sent.
|
353
|
+
You can configure this value via the `stop_wait_time` option:
|
354
|
+
|
355
|
+
```yaml
|
356
|
+
stop_wait_time: 30
|
357
|
+
```
|
358
|
+
|
306
359
|
### Using remote builder for native multi-arch
|
307
360
|
|
308
361
|
If you're developing on ARM64 (like Apple Silicon), but you want to deploy on AMD64 (x86 64-bit), you can use multi-architecture images. By default, MRSK will setup a local buildx configuration that does this through QEMU emulation. But this can be quite slow, especially on the first build.
|
@@ -408,6 +461,46 @@ traefik:
|
|
408
461
|
host_port: 8080
|
409
462
|
```
|
410
463
|
|
464
|
+
### Configure docker options for traefik
|
465
|
+
|
466
|
+
We allow users to pass additional docker options to the trafik container like
|
467
|
+
|
468
|
+
```yaml
|
469
|
+
traefik:
|
470
|
+
options:
|
471
|
+
publish:
|
472
|
+
- 8080:8080
|
473
|
+
volumes:
|
474
|
+
- /tmp/example.json:/tmp/example.json
|
475
|
+
memory: 512m
|
476
|
+
```
|
477
|
+
|
478
|
+
This will start the traefik container with a command like: `docker run ... --volume /tmp/example.json:/tmp/example.json --publish 8080:8080 `
|
479
|
+
|
480
|
+
|
481
|
+
### Configure alternate entrypoints for traefik
|
482
|
+
|
483
|
+
You can configure multiple entrypoints for traefik like so:
|
484
|
+
|
485
|
+
```yaml
|
486
|
+
service: myservice
|
487
|
+
|
488
|
+
labels:
|
489
|
+
traefik.tcp.routers.other.rule: 'HostSNI(`*`)'
|
490
|
+
traefik.tcp.routers.other.entrypoints: otherentrypoint
|
491
|
+
traefik.tcp.services.other.loadbalancer.server.port: 9000
|
492
|
+
traefik.http.routers.myservice.entrypoints: web
|
493
|
+
traefik.http.services.myservice.loadbalancer.server.port: 8080
|
494
|
+
|
495
|
+
traefik:
|
496
|
+
options:
|
497
|
+
publish:
|
498
|
+
- 9000:9000
|
499
|
+
args:
|
500
|
+
entrypoints.web.address: ':80'
|
501
|
+
entrypoints.otherentrypoint.address: ':9000'
|
502
|
+
```
|
503
|
+
|
411
504
|
### Configuring build args for new images
|
412
505
|
|
413
506
|
Build arguments that aren't secret can also be configured:
|
@@ -427,7 +520,7 @@ FROM ruby:$RUBY_VERSION-slim as base
|
|
427
520
|
|
428
521
|
### Using accessories for database, cache, search services
|
429
522
|
|
430
|
-
You can manage your accessory services via MRSK as well.
|
523
|
+
You can manage your accessory services via MRSK as well. Accessories are long-lived services that your app depends on. They are not updated when you deploy.
|
431
524
|
|
432
525
|
```yaml
|
433
526
|
accessories:
|
@@ -442,16 +535,44 @@ accessories:
|
|
442
535
|
- MYSQL_ROOT_PASSWORD
|
443
536
|
volumes:
|
444
537
|
- /var/lib/mysql:/var/lib/mysql
|
538
|
+
options:
|
539
|
+
cpus: 4
|
540
|
+
memory: "2GB"
|
445
541
|
redis:
|
446
542
|
image: redis:latest
|
447
|
-
|
543
|
+
role:
|
544
|
+
- web
|
448
545
|
port: "36379:6379"
|
449
546
|
volumes:
|
450
547
|
- /var/lib/redis:/data
|
548
|
+
internal-example:
|
549
|
+
image: registry.digitalocean.com/user/otherservice:latest
|
550
|
+
host: 1.1.1.5
|
551
|
+
port: 44444
|
552
|
+
```
|
553
|
+
|
554
|
+
The hosts that the accessories will run on can be specified by hosts or roles:
|
555
|
+
|
556
|
+
```yaml
|
557
|
+
# Single host
|
558
|
+
mysql:
|
559
|
+
host: 1.1.1.1
|
560
|
+
# Multiple hosts
|
561
|
+
redis:
|
562
|
+
hosts:
|
563
|
+
- 1.1.1.1
|
564
|
+
- 1.1.1.2
|
565
|
+
# By role
|
566
|
+
monitoring:
|
567
|
+
roles:
|
568
|
+
- web
|
569
|
+
- jobs
|
451
570
|
```
|
452
571
|
|
453
572
|
Now run `mrsk accessory start mysql` to start the MySQL server on 1.1.1.3. See `mrsk accessory` for all the commands possible.
|
454
573
|
|
574
|
+
Accessory images must be public or tagged in your private registry.
|
575
|
+
|
455
576
|
### Using Cron
|
456
577
|
|
457
578
|
You can use a specific container to run your Cron jobs:
|
@@ -616,6 +737,30 @@ Note that by default old containers are pruned after 3 days when you run `mrsk d
|
|
616
737
|
|
617
738
|
If you wish to remove the entire application, including Traefik, containers, images, and registry session, you can run `mrsk remove`. This will leave the servers clean.
|
618
739
|
|
740
|
+
## Locking
|
741
|
+
|
742
|
+
Commands that are unsafe to run concurrently will take a deploy lock while they run. The lock is the `mrsk_lock` directory on the primary server.
|
743
|
+
|
744
|
+
You can check the lock status with:
|
745
|
+
|
746
|
+
```
|
747
|
+
mrsk lock status
|
748
|
+
|
749
|
+
Locked by: AN Other at 2023-03-24 09:49:03 UTC
|
750
|
+
Version: 77f45c0686811c68989d6576748475a60bf53fc2
|
751
|
+
Message: Automatic deploy lock
|
752
|
+
```
|
753
|
+
|
754
|
+
You can also manually acquire and release the lock
|
755
|
+
|
756
|
+
```
|
757
|
+
mrsk lock acquire -m "Doing maintanence"
|
758
|
+
```
|
759
|
+
|
760
|
+
```
|
761
|
+
mrsk lock release
|
762
|
+
```
|
763
|
+
|
619
764
|
## Stage of development
|
620
765
|
|
621
766
|
This is beta software. Commands may still move around. But we're live in production at [37signals](https://37signals.com).
|
data/lib/mrsk/cli/accessory.rb
CHANGED
@@ -1,33 +1,38 @@
|
|
1
1
|
class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
2
2
|
desc "boot [NAME]", "Boot new accessory service on host (use NAME=all to boot all accessories)"
|
3
3
|
def boot(name)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
with_lock do
|
5
|
+
if name == "all"
|
6
|
+
MRSK.accessory_names.each { |accessory_name| boot(accessory_name) }
|
7
|
+
else
|
8
|
+
with_accessory(name) do |accessory|
|
9
|
+
directories(name)
|
10
|
+
upload(name)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
on(accessory.hosts) do
|
13
|
+
execute *MRSK.registry.login
|
14
|
+
execute *MRSK.auditor.record("Booted #{name} accessory"), verbosity: :debug
|
15
|
+
execute *accessory.run
|
16
|
+
end
|
15
17
|
|
16
|
-
|
18
|
+
audit_broadcast "Booted accessory #{name}" unless options[:skip_broadcast]
|
19
|
+
end
|
17
20
|
end
|
18
21
|
end
|
19
22
|
end
|
20
23
|
|
21
24
|
desc "upload [NAME]", "Upload accessory files to host", hide: true
|
22
25
|
def upload(name)
|
23
|
-
|
24
|
-
|
25
|
-
accessory.
|
26
|
-
accessory.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
with_lock do
|
27
|
+
with_accessory(name) do |accessory|
|
28
|
+
on(accessory.hosts) do
|
29
|
+
accessory.files.each do |(local, remote)|
|
30
|
+
accessory.ensure_local_file_present(local)
|
31
|
+
|
32
|
+
execute *accessory.make_directory_for(remote)
|
33
|
+
upload! local, remote
|
34
|
+
execute :chmod, "755", remote
|
35
|
+
end
|
31
36
|
end
|
32
37
|
end
|
33
38
|
end
|
@@ -35,10 +40,12 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
|
35
40
|
|
36
41
|
desc "directories [NAME]", "Create accessory directories on host", hide: true
|
37
42
|
def directories(name)
|
38
|
-
|
39
|
-
|
40
|
-
accessory.
|
41
|
-
|
43
|
+
with_lock do
|
44
|
+
with_accessory(name) do |accessory|
|
45
|
+
on(accessory.hosts) do
|
46
|
+
accessory.directories.keys.each do |host_path|
|
47
|
+
execute *accessory.make_directory(host_path)
|
48
|
+
end
|
42
49
|
end
|
43
50
|
end
|
44
51
|
end
|
@@ -46,38 +53,46 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
|
46
53
|
|
47
54
|
desc "reboot [NAME]", "Reboot existing accessory on host (stop container, remove container, start new container)"
|
48
55
|
def reboot(name)
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
56
|
+
with_lock do
|
57
|
+
with_accessory(name) do |accessory|
|
58
|
+
stop(name)
|
59
|
+
remove_container(name)
|
60
|
+
boot(name)
|
61
|
+
end
|
53
62
|
end
|
54
63
|
end
|
55
64
|
|
56
65
|
desc "start [NAME]", "Start existing accessory container on host"
|
57
66
|
def start(name)
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
67
|
+
with_lock do
|
68
|
+
with_accessory(name) do |accessory|
|
69
|
+
on(accessory.hosts) do
|
70
|
+
execute *MRSK.auditor.record("Started #{name} accessory"), verbosity: :debug
|
71
|
+
execute *accessory.start
|
72
|
+
end
|
62
73
|
end
|
63
74
|
end
|
64
75
|
end
|
65
76
|
|
66
77
|
desc "stop [NAME]", "Stop existing accessory container on host"
|
67
78
|
def stop(name)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
79
|
+
with_lock do
|
80
|
+
with_accessory(name) do |accessory|
|
81
|
+
on(accessory.hosts) do
|
82
|
+
execute *MRSK.auditor.record("Stopped #{name} accessory"), verbosity: :debug
|
83
|
+
execute *accessory.stop, raise_on_non_zero_exit: false
|
84
|
+
end
|
72
85
|
end
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
76
89
|
desc "restart [NAME]", "Restart existing accessory container on host"
|
77
90
|
def restart(name)
|
78
|
-
|
79
|
-
|
80
|
-
|
91
|
+
with_lock do
|
92
|
+
with_accessory(name) do
|
93
|
+
stop(name)
|
94
|
+
start(name)
|
95
|
+
end
|
81
96
|
end
|
82
97
|
end
|
83
98
|
|
@@ -87,7 +102,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
|
87
102
|
MRSK.accessory_names.each { |accessory_name| details(accessory_name) }
|
88
103
|
else
|
89
104
|
with_accessory(name) do |accessory|
|
90
|
-
on(accessory.
|
105
|
+
on(accessory.hosts) { puts capture_with_info(*accessory.info) }
|
91
106
|
end
|
92
107
|
end
|
93
108
|
end
|
@@ -108,14 +123,14 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
|
108
123
|
|
109
124
|
when options[:reuse]
|
110
125
|
say "Launching command from existing container...", :magenta
|
111
|
-
on(accessory.
|
126
|
+
on(accessory.hosts) do
|
112
127
|
execute *MRSK.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug
|
113
128
|
capture_with_info(*accessory.execute_in_existing_container(cmd))
|
114
129
|
end
|
115
130
|
|
116
131
|
else
|
117
132
|
say "Launching command from new container...", :magenta
|
118
|
-
on(accessory.
|
133
|
+
on(accessory.hosts) do
|
119
134
|
execute *MRSK.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug
|
120
135
|
capture_with_info(*accessory.execute_in_new_container(cmd))
|
121
136
|
end
|
@@ -134,7 +149,7 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
|
134
149
|
|
135
150
|
if options[:follow]
|
136
151
|
run_locally do
|
137
|
-
info "Following logs on #{accessory.
|
152
|
+
info "Following logs on #{accessory.hosts}..."
|
138
153
|
info accessory.follow_logs(grep: grep)
|
139
154
|
exec accessory.follow_logs(grep: grep)
|
140
155
|
end
|
@@ -142,25 +157,27 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
|
142
157
|
since = options[:since]
|
143
158
|
lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set
|
144
159
|
|
145
|
-
on(accessory.
|
160
|
+
on(accessory.hosts) do
|
146
161
|
puts capture_with_info(*accessory.logs(since: since, lines: lines, grep: grep))
|
147
162
|
end
|
148
163
|
end
|
149
164
|
end
|
150
165
|
end
|
151
166
|
|
152
|
-
desc "remove [NAME]", "Remove accessory container and
|
167
|
+
desc "remove [NAME]", "Remove accessory container, image and data directory from host (use NAME=all to remove all accessories)"
|
153
168
|
option :confirmed, aliases: "-y", type: :boolean, default: false, desc: "Proceed without confirmation question"
|
154
169
|
def remove(name)
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
170
|
+
with_lock do
|
171
|
+
if name == "all"
|
172
|
+
MRSK.accessory_names.each { |accessory_name| remove(accessory_name) }
|
173
|
+
else
|
174
|
+
if options[:confirmed] || ask("This will remove all containers, images and data directories for #{name}. Are you sure?", limited_to: %w( y N ), default: "N") == "y"
|
175
|
+
with_accessory(name) do
|
176
|
+
stop(name)
|
177
|
+
remove_container(name)
|
178
|
+
remove_image(name)
|
179
|
+
remove_service_directory(name)
|
180
|
+
end
|
164
181
|
end
|
165
182
|
end
|
166
183
|
end
|
@@ -168,29 +185,35 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
|
|
168
185
|
|
169
186
|
desc "remove_container [NAME]", "Remove accessory container from host", hide: true
|
170
187
|
def remove_container(name)
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
188
|
+
with_lock do
|
189
|
+
with_accessory(name) do |accessory|
|
190
|
+
on(accessory.hosts) do
|
191
|
+
execute *MRSK.auditor.record("Remove #{name} accessory container"), verbosity: :debug
|
192
|
+
execute *accessory.remove_container
|
193
|
+
end
|
175
194
|
end
|
176
195
|
end
|
177
196
|
end
|
178
197
|
|
179
198
|
desc "remove_image [NAME]", "Remove accessory image from host", hide: true
|
180
199
|
def remove_image(name)
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
200
|
+
with_lock do
|
201
|
+
with_accessory(name) do |accessory|
|
202
|
+
on(accessory.hosts) do
|
203
|
+
execute *MRSK.auditor.record("Removed #{name} accessory image"), verbosity: :debug
|
204
|
+
execute *accessory.remove_image
|
205
|
+
end
|
185
206
|
end
|
186
207
|
end
|
187
208
|
end
|
188
209
|
|
189
210
|
desc "remove_service_directory [NAME]", "Remove accessory directory used for uploaded files and data directories from host", hide: true
|
190
211
|
def remove_service_directory(name)
|
191
|
-
|
192
|
-
|
193
|
-
|
212
|
+
with_lock do
|
213
|
+
with_accessory(name) do |accessory|
|
214
|
+
on(accessory.hosts) do
|
215
|
+
execute *accessory.remove_service_directory
|
216
|
+
end
|
194
217
|
end
|
195
218
|
end
|
196
219
|
end
|