mrsk 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0f5260e6f41ed0ae04931d800b7c2da3b0bc32f0042d2e140fcb2860b1a9e12a
4
- data.tar.gz: 0c94b286b4a9ce9339678a4a4662c65dcefd6947795227c2464db50e7bf727e0
3
+ metadata.gz: 45be50e3f2f3c5c629b1ec46ee23394b1913c758385ee431d44553506f40cc01
4
+ data.tar.gz: fe11053be553d9af7d090b03b019dd09d1578bed94050b6be5699f99f6711be8
5
5
  SHA512:
6
- metadata.gz: 0f980ac1468ac3581f1b8bd8206c2471b5e79d7bc84c274f1bef2a761ceccc25905308774770a04156e68e5b1fd73d8d83926d235d287a11118fb9ea8f7fb619
7
- data.tar.gz: 720ac72cfd88a494049a237140e774b37288f3a142cb70e3a672a91aa7094a019c0eb938c3ca9a146cd64b1d33d811b2c4b8d0373d7b9457bfaf8499bfd86943
6
+ metadata.gz: 6eee63c66d3f6585c2ac142d78ffdf952b141073793a8f8dd8d7b1551fbd5a1a98f12c590e83517f8e52e1ac58b07ebd48b55571ebe66c3c8a2ec677c47ef00d
7
+ data.tar.gz: f46b8fc945be5c43427f7bf2300cbd95e80e30598fd8294e327f83253b25430937d44c255c8edb1d6b0fce613224acb367972bbeef125e7615293c83c23ddb2c
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # MRSK
2
2
 
3
- MRSK ships zero-downtime deploys of Rails apps packed as containers to any host. It uses the dynamic reverse-proxy Traefik to hold requests while the new application container is started and the old one is wound down. It works seamlessly across multiple hosts, using SSHKit to execute commands.
3
+ MRSK deploys Rails apps in containers to servers running Docker with zero downtime. It uses the dynamic reverse-proxy Traefik to hold requests while the new application container is started and the old one is stopped. It works seamlessly across multiple hosts, using SSHKit to execute commands.
4
4
 
5
5
  ## Installation
6
6
 
7
- Add the gem with `bundle add mrsk`, then run `rake mrsk:init`, and then edit the new file in `config/deploy.yml`. It could look as simple as this:
7
+ Install MRSK globally with `gem install mrsk`. Then, inside your app directory, run `mrsk install`. Now edit the new file `config/deploy.yml`. It could look as simple as this:
8
8
 
9
9
  ```yaml
10
10
  service: hey
@@ -13,34 +13,27 @@ servers:
13
13
  - 192.168.0.1
14
14
  - 192.168.0.2
15
15
  registry:
16
- username: <%= Rails.application.credentials.registry["username"] %>
17
- password: <%= Rails.application.credentials.registry["password"] %>
18
- ```
19
-
20
- Then ensure your encrypted credentials have the registry username + password by editing them with `rails credentials:edit`:
21
-
22
- ```
23
- registry:
24
- username: real-user-name
25
- password: real-registry-password-or-token
16
+ username: registry-user-name
17
+ password: <%= ENV["MRSK_REGISTRY_PASSWORD"] %>
26
18
  ```
27
19
 
28
20
  Now you're ready to deploy a multi-arch image to the servers:
29
21
 
30
22
  ```
31
- ./bin/mrsk deploy
23
+ mrsk deploy
32
24
  ```
33
25
 
34
26
  This will:
35
27
 
36
- 1. Log into the registry both locally and remotely
37
- 2. Build the image using the standard Dockerfile in the root of the application.
38
- 3. Push the image to the registry.
39
- 4. Pull the image from the registry on the servers.
40
- 5. Ensure Traefik is running and accepting traffic on port 80.
41
- 6. Stop any containers running a previous versions of the app.
42
- 7. Start a new container with the version of the app that matches the current git version hash.
43
- 8. Prune unused images and stopped containers to ensure servers don't fill up.
28
+ 1. Install Docker on any server that might be missing it (using apt-get)
29
+ 2. Log into the registry both locally and remotely
30
+ 3. Build the image using the standard Dockerfile in the root of the application.
31
+ 4. Push the image to the registry.
32
+ 5. Pull the image from the registry on the servers.
33
+ 6. Ensure Traefik is running and accepting traffic on port 80.
34
+ 7. Stop any containers running a previous versions of the app.
35
+ 8. Start a new container with the version of the app that matches the current git version hash.
36
+ 9. Prune unused images and stopped containers to ensure servers don't fill up.
44
37
 
45
38
  Voila! All the servers are now serving the app on port 80. If you're just running a single server, you're ready to go. If you're running multiple servers, you need to put a load balancer in front of them.
46
39
 
@@ -53,8 +46,8 @@ The default registry for Docker is Docker Hub. If you'd like to use a different
53
46
  ```yaml
54
47
  registry:
55
48
  server: registry.digitalocean.com
56
- username: <%= Rails.application.credentials.registry["username"] %>
57
- password: <%= Rails.application.credentials.registry["password"] %>
49
+ username: registry-user-name
50
+ password: <%= ENV["MRSK_REGISTRY_PASSWORD"] %>
58
51
  ```
59
52
 
60
53
  ### Using a different SSH user than root
@@ -141,7 +134,7 @@ builder:
141
134
 
142
135
  Note: You must have Docker running on the remote host being used as a builder.
143
136
 
144
- With that configuration in place, you can setup the local/remote configuration using `./bin/mrsk build:remote:create`. If you wish to remove the contexts and buildx instances again, you can run `./bin/mrsk build:remote:remove`. If you had already built using the standard emulation setup, run `./bin/mrsk build:remove` before doing `./bin/mrsk build:remote:create`.
137
+ With that configuration in place, you can setup the local/remote configuration using `mrsk build create`. If you wish to remove the contexts and buildx instances again, you can run `mrsk build remove`. If you had already built using the standard emulation setup, run `mrsk build remove` before doing `mrsk build remote`.
145
138
 
146
139
  ### Configuring native builder when multi-arch isn't needed
147
140
 
@@ -156,11 +149,11 @@ builder:
156
149
 
157
150
  ### Remote execution
158
151
 
159
- If you need to execute commands inside the Rails containers, you can use `./bin/mrsk app:exec`, `./bin/mrsk app:exec:once`, `./bin/mrsk app:exec:rails`, and `./bin/mrsk app:exec:once:rails`. Examples:
152
+ If you need to execute commands inside the Rails containers, you can use `mrsk app exec`, `mrsk app exec --once`, `mrsk app runner`, and `mrsk app runner --once`. Examples:
160
153
 
161
154
  ```bash
162
155
  # Runs command on all servers
163
- ./bin/mrsk app:exec CMD='ruby -v'
156
+ mrsk app exec 'ruby -v'
164
157
  App Host: xxx.xxx.xxx.xxx
165
158
  ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
166
159
 
@@ -168,11 +161,11 @@ App Host: xxx.xxx.xxx.xxx
168
161
  ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux]
169
162
 
170
163
  # Runs command on first server
171
- ./bin/mrsk app:exec:once CMD='cat .ruby-version'
164
+ mrsk app exec --once 'cat .ruby-version'
172
165
  3.1.3
173
166
 
174
167
  # Runs Rails command on all servers
175
- ./bin/mrsk app:exec:rails CMD=about
168
+ mrsk app exec 'bin/rails about'
176
169
  App Host: xxx.xxx.xxx.xxx
177
170
  About your application's environment
178
171
  Rails version 7.1.0.alpha
@@ -197,19 +190,18 @@ Environment production
197
190
  Database adapter sqlite3
198
191
  Database schema version 20221231233303
199
192
 
200
- # Runs Rails command on first server
201
- ./bin/mrsk app:exec:once:rails CMD='db:version'
202
- database: storage/production.sqlite3
203
- Current version: 20221231233303
193
+ # Runs Rails runner on first server
194
+ mrsk app runner 'puts Rails.application.config.time_zone'
195
+ UTC
204
196
  ```
205
197
 
206
198
  ### Running a Rails console on the primary host
207
199
 
208
- If you need to interact with the production console for the app, you can use `./bin/mrsk app:console`, which will start a Rails console session on the primary host. Be mindful that this is a live wire! Any changes made to the production database will take effect immeditately.
200
+ 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.
209
201
 
210
202
  ### Inspecting
211
203
 
212
- You can see the state of your servers by running `./bin/mrsk info`. It'll show something like this:
204
+ You can see the state of your servers by running `mrsk details`. It'll show something like this:
213
205
 
214
206
  ```
215
207
  Traefik Host: xxx.xxx.xxx.xxx
@@ -229,11 +221,11 @@ CONTAINER ID IMAGE
229
221
  1d3c91ed1f55 registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483f86d05a123 "/rails/bin/docker-e…" 13 minutes ago Up 13 minutes 3000/tcp chat-6ef8a6a84c525b123c5245345a8483f86d05a123
230
222
  ```
231
223
 
232
- You can also see just info for app containers with `./bin/mrsk app:info` or just for Traefik with `./bin/mrsk traefik:info`.
224
+ You can also see just info for app containers with `mrsk app details` or just for Traefik with `mrsk traefik details`.
233
225
 
234
226
  ### Rollback
235
227
 
236
- If you've discovered a bad deploy, you can quickly rollback by reactivating the old, paused container image. You can see what old containers are available for rollback by running `./bin/mrsk app:containers`. It'll give you a presentation similar to `./bin/mrsk app:info`, but include all the old containers as well. Showing something like this:
228
+ If you've discovered a bad deploy, you can quickly rollback by reactivating the old, paused container image. You can see what old containers are available for rollback by running `mrsk app containers`. It'll give you a presentation similar to `mrsk app details`, but include all the old containers as well. Showing something like this:
237
229
 
238
230
  ```
239
231
  App Host: 164.92.105.119
@@ -247,20 +239,17 @@ badb1aa51db4 registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483
247
239
  6f170d1172ae registry.digitalocean.com/user/app:e5d9d7c2b898289dfbc5f7f1334140d984eedae4 "/rails/bin/docker-e…" 31 minutes ago Exited (1) 27 minutes ago chat-e5d9d7c2b898289dfbc5f7f1334140d984eedae4
248
240
  ```
249
241
 
250
- From the example above, we can see that `e5d9d7c2b898289dfbc5f7f1334140d984eedae4` was the last version, so it's available as a rollback target. We can perform this rollback by running `./bin/mrsk rollback VERSION=e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. That'll stop `6ef8a6a84c525b123c5245345a8483f86d05a123` and then start `e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. Because the old container is still available, this is very quick. Nothing to download from the registry.
242
+ From the example above, we can see that `e5d9d7c2b898289dfbc5f7f1334140d984eedae4` was the last version, so it's available as a rollback target. We can perform this rollback by running `mrsk rollback e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. That'll stop `6ef8a6a84c525b123c5245345a8483f86d05a123` and then start `e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. Because the old container is still available, this is very quick. Nothing to download from the registry.
251
243
 
252
- Note that by default old containers are pruned after 3 days when you run `./bin/mrsk deploy`.
244
+ Note that by default old containers are pruned after 3 days when you run `mrsk deploy`.
253
245
 
254
246
  ### Removing
255
247
 
256
- If you wish to remove the entire application, including Traefik, containers, images, and registry session, you can run `./bin/mrsk remove`. This will leave the servers clean.
248
+ 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.
257
249
 
258
250
  ## Stage of development
259
251
 
260
- This is alpha software. Lots of stuff is missing. Here are some of the areas we seek to improve:
261
-
262
- - Adapterize commands to work with Podman and other container runners
263
- - Integrate with cloud CI pipelines
252
+ This is alpha software. Lots of stuff is missing. Lots of stuff will keep moving around for a while.
264
253
 
265
254
  ## License
266
255
 
data/bin/mrsk ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "mrsk/cli"
4
+
5
+ Mrsk::Cli::Main.start(ARGV)
@@ -0,0 +1,97 @@
1
+ require "mrsk/cli/base"
2
+
3
+ class Mrsk::Cli::App < Mrsk::Cli::Base
4
+ desc "boot", "Boot app on servers (or start them if they've already been booted)"
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
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ 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
+ def start
25
+ if (version = options[:version]).present?
26
+ on(MRSK.config.hosts) { execute *MRSK.app.start(version: version) }
27
+ else
28
+ on(MRSK.config.hosts) { execute *MRSK.app.start, raise_on_non_zero_exit: false }
29
+ end
30
+ end
31
+
32
+ desc "stop", "Stop app on servers"
33
+ def stop
34
+ on(MRSK.config.hosts) { execute *MRSK.app.stop, raise_on_non_zero_exit: false }
35
+ end
36
+
37
+ desc "details", "Display details about app containers"
38
+ def details
39
+ on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.info, verbosity: Logger::INFO) + "\n\n" }
40
+ end
41
+
42
+ desc "exec [CMD]", "Execute a custom task on servers passed in as CMD='bin/rake some:task'"
43
+ option :once, type: :boolean, default: false
44
+ def exec(cmd)
45
+ if options[:once]
46
+ on(MRSK.config.primary_host) { puts capture(*MRSK.app.exec(cmd), verbosity: Logger::INFO) }
47
+ else
48
+ on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.exec(cmd), verbosity: Logger::INFO) + "\n\n" }
49
+ end
50
+ end
51
+
52
+ desc "console", "Start Rails Console on primary host"
53
+ option :host, desc: "Start console on a different host"
54
+ def console
55
+ host = options[:host] || MRSK.config.primary_host
56
+
57
+ run_locally do
58
+ puts "Launching Rails console on #{host}..."
59
+ exec MRSK.app.console(host: host)
60
+ end
61
+ end
62
+
63
+ desc "runner [EXPRESSION]", "Execute Rails runner with given expression"
64
+ option :once, type: :boolean, default: false, desc:
65
+ def runner(expression)
66
+ if options[:once]
67
+ on(MRSK.config.primary_host) { puts capture(*MRSK.app.exec("bin/rails", "runner", "'#{expression}'"), verbosity: Logger::INFO) }
68
+ else
69
+ on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.exec("bin/rails", "runner", "'#{expression}'"), verbosity: Logger::INFO) + "\n\n" }
70
+ end
71
+ end
72
+
73
+ desc "containers", "List all the app containers currently on servers"
74
+ def containers
75
+ on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.list_containers, verbosity: Logger::INFO) + "\n\n" }
76
+ end
77
+
78
+ desc "logs", "Show last 100 log lines from app on servers"
79
+ def logs
80
+ # FIXME: Catch when app containers aren't running
81
+ on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.logs) + "\n\n" }
82
+ end
83
+
84
+ desc "remove", "Remove app containers and images from servers"
85
+ option :only, default: "", desc: "Use 'containers' or 'images'"
86
+ def remove
87
+ case options[:only]
88
+ when "containers"
89
+ on(MRSK.config.hosts) { execute *MRSK.app.remove_containers }
90
+ when "images"
91
+ on(MRSK.config.hosts) { execute *MRSK.app.remove_images }
92
+ else
93
+ on(MRSK.config.hosts) { execute *MRSK.app.remove_containers }
94
+ on(MRSK.config.hosts) { execute *MRSK.app.remove_images }
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,27 @@
1
+ require "thor"
2
+ require "sshkit"
3
+ require "sshkit/dsl"
4
+
5
+ module Mrsk::Cli
6
+ class Base < Thor
7
+ include SSHKit::DSL
8
+
9
+ def self.exit_on_failure?() true end
10
+
11
+ class_option :verbose, type: :boolean, aliases: "-v", desc: "Detailed logging"
12
+
13
+ def initialize(*)
14
+ super
15
+ MRSK.verbose = options[:verbose]
16
+ end
17
+
18
+ private
19
+ def print_runtime
20
+ started_at = Time.now
21
+ yield
22
+ ensure
23
+ runtime = Time.now - started_at
24
+ puts " Finished all in #{sprintf("%.1f seconds", runtime)}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,53 @@
1
+ require "mrsk/cli/base"
2
+
3
+ class Mrsk::Cli::Build < Mrsk::Cli::Base
4
+ desc "deliver", "Deliver a newly built app image to servers"
5
+ def deliver
6
+ invoke :push
7
+ invoke :pull
8
+ end
9
+
10
+ desc "push", "Build locally and push app image to registry"
11
+ def push
12
+ run_locally do
13
+ begin
14
+ debug "Using builder: #{MRSK.builder.name}"
15
+ info "Building image may take a while (run with --verbose for progress logging)"
16
+ execute *MRSK.builder.push
17
+ rescue SSHKit::Command::Failed => e
18
+ error "Missing compatible builder, so creating a new one first"
19
+ execute *MRSK.builder.create
20
+ execute *MRSK.builder.push
21
+ end
22
+ end
23
+ end
24
+
25
+ desc "pull", "Pull app image from the registry onto servers"
26
+ def pull
27
+ on(MRSK.config.hosts) { execute *MRSK.builder.pull }
28
+ end
29
+
30
+ desc "create", "Create a local build setup"
31
+ def create
32
+ run_locally do
33
+ debug "Using builder: #{MRSK.builder.name}"
34
+ execute *MRSK.builder.create
35
+ end
36
+ end
37
+
38
+ desc "remove", "Remove local build setup"
39
+ def remove
40
+ run_locally do
41
+ debug "Using builder: #{MRSK.builder.name}"
42
+ execute *MRSK.builder.remove
43
+ end
44
+ end
45
+
46
+ desc "details", "Show the name of the configured builder"
47
+ def details
48
+ run_locally do
49
+ puts "Builder: #{MRSK.builder.name} (#{MRSK.builder.target.class.name})"
50
+ puts capture(*MRSK.builder.info)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,99 @@
1
+ require "mrsk/cli/base"
2
+
3
+ require "mrsk/cli/app"
4
+ require "mrsk/cli/build"
5
+ require "mrsk/cli/prune"
6
+ require "mrsk/cli/registry"
7
+ require "mrsk/cli/server"
8
+ require "mrsk/cli/traefik"
9
+
10
+ class Mrsk::Cli::Main < Mrsk::Cli::Base
11
+ desc "deploy", "Deploy the app to servers"
12
+ def deploy
13
+ print_runtime do
14
+ invoke "mrsk:cli:server:bootstrap"
15
+ invoke "mrsk:cli:registry:login"
16
+ invoke "mrsk:cli:build:deliver"
17
+ invoke "mrsk:cli:traefik:boot"
18
+ invoke "mrsk:cli:app:stop"
19
+ invoke "mrsk:cli:app:boot"
20
+ invoke "mrsk:cli:prune:all"
21
+ end
22
+ end
23
+
24
+ desc "redeploy", "Deploy new version of the app to servers (without bootstrapping servers, starting Traefik, pruning, and registry login)"
25
+ def redeploy
26
+ print_runtime do
27
+ invoke "mrsk:cli:build:deliver"
28
+ invoke "mrsk:cli:app:stop"
29
+ invoke "mrsk:cli:app:boot"
30
+ end
31
+ end
32
+
33
+ desc "rollback [VERSION]", "Rollback the app to VERSION (that must already be on servers)"
34
+ def rollback(version)
35
+ on(MRSK.config.hosts) do
36
+ execute *MRSK.app.stop, raise_on_non_zero_exit: false
37
+ execute *MRSK.app.start(version: version)
38
+ end
39
+ end
40
+
41
+ desc "details", "Display details about Traefik and app containers"
42
+ def details
43
+ invoke "mrsk:cli:traefik:details"
44
+ invoke "mrsk:cli:app:details"
45
+ end
46
+
47
+ desc "install", "Create config stub in config/deploy.yml and binstub in bin/mrsk"
48
+ option :skip_binstub, type: :boolean, default: false, desc: "Skip adding MRSK to the Gemfile and creating bin/mrsk binstub"
49
+ def install
50
+ require "fileutils"
51
+
52
+ if (deploy_file = Pathname.new(File.expand_path("config/deploy.yml"))).exist?
53
+ puts "Config file already exists in config/deploy.yml (remove first to create a new one)"
54
+ else
55
+ FileUtils.cp_r Pathname.new(File.expand_path("templates/deploy.yml", __dir__)), deploy_file
56
+ puts "Created configuration file in config/deploy.yml"
57
+ end
58
+
59
+ unless options[:skip_binstub]
60
+ if (binstub = Pathname.new(File.expand_path("bin/mrsk"))).exist?
61
+ puts "Binstub already exists in bin/mrsk (remove first to create a new one)"
62
+ else
63
+ `bundle add mrsk`
64
+ `bundle binstubs mrsk`
65
+ puts "Created binstub file in bin/mrsk"
66
+ end
67
+ end
68
+ end
69
+
70
+ desc "remove", "Remove Traefik, app, and registry session from servers"
71
+ def remove
72
+ invoke "mrsk:cli:traefik:remove"
73
+ invoke "mrsk:cli:app:remove"
74
+ invoke "mrsk:cli:registry:logout"
75
+ end
76
+
77
+ desc "version", "Display the MRSK version"
78
+ def version
79
+ puts Mrsk::VERSION
80
+ end
81
+
82
+ desc "app", "Manage the application"
83
+ subcommand "app", Mrsk::Cli::App
84
+
85
+ desc "build", "Build the application image"
86
+ subcommand "build", Mrsk::Cli::Build
87
+
88
+ desc "prune", "Prune old application images and containers"
89
+ subcommand "prune", Mrsk::Cli::Prune
90
+
91
+ desc "registry", "Login and out of the image registry"
92
+ subcommand "registry", Mrsk::Cli::Registry
93
+
94
+ desc "server", "Bootstrap servers with Docker"
95
+ subcommand "server", Mrsk::Cli::Server
96
+
97
+ desc "traefik", "Manage the Traefik load balancer"
98
+ subcommand "traefik", Mrsk::Cli::Traefik
99
+ end
@@ -0,0 +1,19 @@
1
+ require "mrsk/cli/base"
2
+
3
+ class Mrsk::Cli::Prune < Mrsk::Cli::Base
4
+ desc "all", "Prune unused images and stopped containers"
5
+ def all
6
+ invoke :containers
7
+ invoke :images
8
+ end
9
+
10
+ desc "images", "Prune unused images older than 30 days"
11
+ def images
12
+ on(MRSK.config.hosts) { execute *MRSK.prune.images }
13
+ end
14
+
15
+ desc "containers", "Prune stopped containers for the service older than 3 days"
16
+ def containers
17
+ on(MRSK.config.hosts) { execute *MRSK.prune.containers }
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+ require "mrsk/cli/base"
2
+
3
+ class Mrsk::Cli::Registry < Mrsk::Cli::Base
4
+ desc "login", "Login to the registry locally and remotely"
5
+ def login
6
+ run_locally { execute *MRSK.registry.login }
7
+ on(MRSK.config.hosts) { execute *MRSK.registry.login }
8
+ end
9
+
10
+ desc "logout", "Logout of the registry remotely"
11
+ def logout
12
+ on(MRSK.config.hosts) { execute *MRSK.registry.logout }
13
+ end
14
+ end
@@ -0,0 +1,8 @@
1
+ require "mrsk/cli/base"
2
+
3
+ class Mrsk::Cli::Server < Mrsk::Cli::Base
4
+ desc "bootstrap", "Ensure Docker is installed on the servers"
5
+ def bootstrap
6
+ on(MRSK.config.hosts) { execute "which docker || apt-get install docker.io -y" }
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ # Name of your application. Used to uniquely configuring Traefik and app containers.
2
+ # Your Dockerfile should set LABEL service=the-same-value to ensure image pruning works.
3
+ service: my-app
4
+
5
+ # Name of the container image.
6
+ image: user/my-app
7
+
8
+ # Deploy to these servers.
9
+ servers:
10
+ - 192.168.0.1
11
+
12
+ # Credentials for your image host.
13
+ registry:
14
+ # Specify the registry server, if you're not using Docker Hub
15
+ # server: registry.digitalocean.com / ghcr.io / ...
16
+ username: my-user
17
+ password: my-password-should-go-somewhere-safe
@@ -0,0 +1,44 @@
1
+ require "mrsk/cli/base"
2
+
3
+ class Mrsk::Cli::Traefik < Mrsk::Cli::Base
4
+ desc "boot", "Boot Traefik on servers"
5
+ def boot
6
+ on(MRSK.config.role(:web).hosts) { execute *MRSK.traefik.run, raise_on_non_zero_exit: false }
7
+ end
8
+
9
+ desc "start", "Start existing Traefik on servers"
10
+ def start
11
+ on(MRSK.config.role(:web).hosts) { execute *MRSK.traefik.start, raise_on_non_zero_exit: false }
12
+ end
13
+
14
+ desc "stop", "Stop Traefik on servers"
15
+ def stop
16
+ on(MRSK.config.role(:web).hosts) { execute *MRSK.traefik.stop, raise_on_non_zero_exit: false }
17
+ end
18
+
19
+ desc "restart", "Restart Traefik on servers"
20
+ def restart
21
+ invoke :stop
22
+ invoke :start
23
+ end
24
+
25
+ desc "details", "Display details about Traefik containers from servers"
26
+ def details
27
+ on(MRSK.config.role(:web).hosts) { |host| puts "Traefik Host: #{host}\n" + capture(*MRSK.traefik.info, verbosity: Logger::INFO) + "\n\n" }
28
+ end
29
+
30
+ desc "logs", "Show last 100 log lines from Traefik on servers"
31
+ def logs
32
+ on(MRSK.config.hosts) { |host| puts "Traefik Host: #{host}\n" + capture(*MRSK.traefik.logs) + "\n\n" }
33
+ end
34
+
35
+ desc "remove", "Remove Traefik container and image from servers"
36
+ def remove
37
+ invoke :stop
38
+
39
+ on(MRSK.config.role(:web).hosts) do
40
+ execute *MRSK.traefik.remove_container
41
+ execute *MRSK.traefik.remove_image
42
+ end
43
+ end
44
+ end
data/lib/mrsk/cli.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "mrsk"
2
+
3
+ MRSK = Mrsk::Commander.new \
4
+ config_file: Pathname.new(File.expand_path("config/deploy.yml"))
5
+
6
+ module Mrsk::Cli
7
+ end
8
+
9
+ require "mrsk/cli/main"
@@ -6,14 +6,15 @@ require "mrsk/commands/traefik"
6
6
  require "mrsk/commands/registry"
7
7
 
8
8
  class Mrsk::Commander
9
- attr_reader :config_file, :config, :verbose
9
+ attr_reader :config
10
+ attr_accessor :verbose
10
11
 
11
- def initialize(config_file:, verbose: false)
12
- @config_file, @verbose = config_file, verbose
12
+ def initialize(config_file:)
13
+ @config_file = config_file
13
14
  end
14
15
 
15
16
  def config
16
- @config ||= Mrsk::Configuration.load_file(config_file).tap { |config| setup_with(config) }
17
+ @config ||= Mrsk::Configuration.load_file(@config_file).tap { |config| setup_with(config) }
17
18
  end
18
19
 
19
20
 
@@ -15,8 +15,8 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
15
15
  role.cmd
16
16
  end
17
17
 
18
- def start
19
- docker :start, config.service_with_version
18
+ def start(version: config.version)
19
+ docker :start, "#{config.service}-#{version}"
20
20
  end
21
21
 
22
22
  def stop
@@ -40,8 +40,8 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
40
40
  *command
41
41
  end
42
42
 
43
- def console
44
- "ssh -t #{config.ssh_user}@#{config.primary_host} '#{exec("bin/rails", "c", interactive: true).join(" ")}'"
43
+ def console(host: config.primary_host)
44
+ "ssh -t #{config.ssh_user}@#{host} '#{exec("bin/rails", "c", interactive: true).join(" ")}'"
45
45
  end
46
46
 
47
47
  def list_containers
@@ -16,11 +16,11 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult
16
16
 
17
17
  private
18
18
  def create_local_buildx
19
- docker :buildx, :create, "--use", "--name", "mrsk", "mrsk-#{local["arch"]}", "--platform", "linux/#{local["arch"]}"
19
+ docker :buildx, :create, "--use", "--name", builder_name, builder_name_with_arch(local["arch"]), "--platform", "linux/#{local["arch"]}"
20
20
  end
21
21
 
22
22
  def append_remote_buildx
23
- docker :buildx, :create, "--append", "--name", "mrsk", "mrsk-#{remote["arch"]}", "--platform", "linux/#{remote["arch"]}"
23
+ docker :buildx, :create, "--append", "--name", builder_name, builder_name_with_arch(remote["arch"]), "--platform", "linux/#{remote["arch"]}"
24
24
  end
25
25
 
26
26
  def create_contexts
@@ -30,7 +30,7 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult
30
30
  end
31
31
 
32
32
  def create_context(arch, host)
33
- docker :context, :create, "mrsk-#{arch}", "--description", "'MRSK #{arch} Native Host'", "--docker", "'host=#{host}'"
33
+ docker :context, :create, builder_name_with_arch(arch), "--description", "'#{builder_name} #{arch} native host'", "--docker", "'host=#{host}'"
34
34
  end
35
35
 
36
36
  def remove_contexts
@@ -40,7 +40,7 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult
40
40
  end
41
41
 
42
42
  def remove_context(arch)
43
- docker :context, :rm, "mrsk-#{arch}"
43
+ docker :context, :rm, builder_name_with_arch(arch)
44
44
  end
45
45
 
46
46
  def local
@@ -50,4 +50,9 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult
50
50
  def remote
51
51
  config.builder["remote"]
52
52
  end
53
+
54
+ private
55
+ def builder_name_with_arch(arch)
56
+ "#{builder_name}-#{arch}"
57
+ end
53
58
  end
@@ -2,11 +2,11 @@ require "mrsk/commands/base"
2
2
 
3
3
  class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Base
4
4
  def create
5
- docker :buildx, :create, "--use", "--name", "mrsk"
5
+ docker :buildx, :create, "--use", "--name", builder_name
6
6
  end
7
7
 
8
8
  def remove
9
- docker :buildx, :rm, "mrsk"
9
+ docker :buildx, :rm, builder_name
10
10
  end
11
11
 
12
12
  def push
@@ -22,4 +22,9 @@ class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Base
22
22
  docker(:context, :ls),
23
23
  docker(:buildx, :ls)
24
24
  end
25
+
26
+ private
27
+ def builder_name
28
+ "mrsk-#{config.service}"
29
+ end
25
30
  end
@@ -1,5 +1,7 @@
1
1
  require "active_support/ordered_options"
2
2
  require "active_support/core_ext/string/inquiry"
3
+ require "active_support/core_ext/module/delegation"
4
+ require "pathname"
3
5
  require "erb"
4
6
 
5
7
  class Mrsk::Configuration
@@ -91,7 +93,7 @@ class Mrsk::Configuration
91
93
  end
92
94
 
93
95
  def master_key
94
- ENV["RAILS_MASTER_KEY"] || File.read(Rails.root.join("config/master.key"))
96
+ ENV["RAILS_MASTER_KEY"] || File.read(Pathname.new(File.expand_path("config/master.key")))
95
97
  end
96
98
 
97
99
 
data/lib/mrsk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mrsk
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/mrsk.rb CHANGED
@@ -2,5 +2,4 @@ module Mrsk
2
2
  end
3
3
 
4
4
  require "mrsk/version"
5
- require "mrsk/engine"
6
5
  require "mrsk/commander"
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mrsk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.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-01-13 00:00:00.000000000 Z
11
+ date: 2023-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: railties
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 7.0.0
19
+ version: '7.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 7.0.0
26
+ version: '7.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: sshkit
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,15 +38,41 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.21'
41
+ - !ruby/object:Gem::Dependency
42
+ name: thor
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.2'
41
55
  description:
42
56
  email: dhh@hey.com
43
- executables: []
57
+ executables:
58
+ - mrsk
44
59
  extensions: []
45
60
  extra_rdoc_files: []
46
61
  files:
47
62
  - MIT-LICENSE
48
63
  - README.md
64
+ - bin/mrsk
49
65
  - lib/mrsk.rb
66
+ - lib/mrsk/cli.rb
67
+ - lib/mrsk/cli/app.rb
68
+ - lib/mrsk/cli/base.rb
69
+ - lib/mrsk/cli/build.rb
70
+ - lib/mrsk/cli/main.rb
71
+ - lib/mrsk/cli/prune.rb
72
+ - lib/mrsk/cli/registry.rb
73
+ - lib/mrsk/cli/server.rb
74
+ - lib/mrsk/cli/templates/deploy.yml
75
+ - lib/mrsk/cli/traefik.rb
50
76
  - lib/mrsk/commander.rb
51
77
  - lib/mrsk/commands.rb
52
78
  - lib/mrsk/commands/app.rb
@@ -60,18 +86,7 @@ files:
60
86
  - lib/mrsk/commands/traefik.rb
61
87
  - lib/mrsk/configuration.rb
62
88
  - lib/mrsk/configuration/role.rb
63
- - lib/mrsk/engine.rb
64
89
  - lib/mrsk/version.rb
65
- - lib/tasks/mrsk/app.rake
66
- - lib/tasks/mrsk/build.rake
67
- - lib/tasks/mrsk/mrsk.rake
68
- - lib/tasks/mrsk/prune.rake
69
- - lib/tasks/mrsk/registry.rake
70
- - lib/tasks/mrsk/server.rake
71
- - lib/tasks/mrsk/setup.rb
72
- - lib/tasks/mrsk/templates/deploy.yml
73
- - lib/tasks/mrsk/templates/mrsk
74
- - lib/tasks/mrsk/traefik.rake
75
90
  homepage: https://github.com/rails/mrsk
76
91
  licenses:
77
92
  - MIT
@@ -94,5 +109,5 @@ requirements: []
94
109
  rubygems_version: 3.4.1
95
110
  signing_key:
96
111
  specification_version: 4
97
- summary: Deploy Docker containers with zero downtime to any host.
112
+ summary: Deploy Rails apps in containers to servers running Docker with zero downtime.
98
113
  test_files: []
data/lib/mrsk/engine.rb DELETED
@@ -1,4 +0,0 @@
1
- module Mrsk
2
- class Engine < ::Rails::Engine
3
- end
4
- end
@@ -1,97 +0,0 @@
1
- require_relative "setup"
2
-
3
- namespace :mrsk do
4
- namespace :app do
5
- desc "Run app on servers (or start them if they've already been run)"
6
- task :run do
7
- MRSK.config.roles.each do |role|
8
- on(role.hosts) do |host|
9
- begin
10
- execute *MRSK.app.run(role: role.name)
11
- rescue SSHKit::Command::Failed => e
12
- if e.message =~ /already in use/
13
- error "Container with same version already deployed on #{host}, starting that instead"
14
- execute *MRSK.app.start, host: host
15
- else
16
- raise
17
- end
18
- end
19
- end
20
- end
21
- end
22
-
23
- desc "Start existing app on servers (use VERSION=<git-hash> to designate which version)"
24
- task :start do
25
- on(MRSK.config.hosts) { execute *MRSK.app.start, raise_on_non_zero_exit: false }
26
- end
27
-
28
- desc "Stop app on servers"
29
- task :stop do
30
- on(MRSK.config.hosts) { execute *MRSK.app.stop, raise_on_non_zero_exit: false }
31
- end
32
-
33
- desc "Start app on servers (use VERSION=<git-hash> to designate which version)"
34
- task restart: %i[ stop start ]
35
-
36
- desc "Display information about app containers"
37
- task :info do
38
- on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.info) + "\n\n" }
39
- end
40
-
41
- desc "Execute a custom task on servers passed in as CMD='bin/rake some:task'"
42
- task :exec do
43
- on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.exec(ENV["CMD"])) + "\n\n" }
44
- end
45
-
46
- desc "Start Rails Console on primary host"
47
- task :console do
48
- puts "Launching Rails console on #{MRSK.config.primary_host}..."
49
- exec app.console
50
- end
51
-
52
- namespace :exec do
53
- desc "Execute Rails command on servers, like CMD='runner \"puts %(Hello World)\""
54
- task :rails do
55
- on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.exec("bin/rails", ENV["CMD"])) + "\n\n" }
56
- end
57
-
58
- desc "Execute a custom task on the first defined server"
59
- task :once do
60
- on(MRSK.config.primary_host) { puts capture(*MRSK.app.exec(ENV["CMD"])) }
61
- end
62
-
63
- namespace :once do
64
- desc "Execute Rails command on the first defined server, like CMD='runner \"puts %(Hello World)\""
65
- task :rails do
66
- on(MRSK.config.primary_host) { puts capture(*MRSK.app.exec("bin/rails", ENV["CMD"])) }
67
- end
68
- end
69
- end
70
-
71
- desc "List all the app containers currently on servers"
72
- task :containers do
73
- on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.list_containers) + "\n\n" }
74
- end
75
-
76
- desc "Show last 100 log lines from app on servers"
77
- task :logs do
78
- # FIXME: Catch when app containers aren't running
79
- on(MRSK.config.hosts) { |host| puts "App Host: #{host}\n" + capture(*MRSK.app.logs) + "\n\n" }
80
- end
81
-
82
- desc "Remove app containers and images from servers"
83
- task remove: %w[ remove:containers remove:images ]
84
-
85
- namespace :remove do
86
- desc "Remove app containers from servers"
87
- task :containers do
88
- on(MRSK.config.hosts) { execute *MRSK.app.remove_containers }
89
- end
90
-
91
- desc "Remove app images from servers"
92
- task :images do
93
- on(MRSK.config.hosts) { execute *MRSK.app.remove_images }
94
- end
95
- end
96
- end
97
- end
@@ -1,52 +0,0 @@
1
- require_relative "setup"
2
-
3
- namespace :mrsk do
4
- namespace :build do
5
- desc "Deliver a newly built app image to servers"
6
- task deliver: %i[ push pull ]
7
-
8
- desc "Build locally and push app image to registry"
9
- task :push do
10
- run_locally do
11
- begin
12
- debug "Using builder: #{MRSK.builder.name}"
13
- info "Building image may take a while (run with VERBOSE=1 for progress logging)"
14
- execute *MRSK.builder.push
15
- rescue SSHKit::Command::Failed => e
16
- error "Missing compatible builder, so creating a new one first"
17
- execute *MRSK.builder.create
18
- execute *MRSK.builder.push
19
- end
20
- end unless ENV["VERSION"]
21
- end
22
-
23
- desc "Pull app image from the registry onto servers"
24
- task :pull do
25
- on(MRSK.config.hosts) { execute *MRSK.builder.pull }
26
- end
27
-
28
- desc "Create a local build setup"
29
- task :create do
30
- run_locally do
31
- debug "Using builder: #{MRSK.builder.name}"
32
- execute *MRSK.builder.create
33
- end
34
- end
35
-
36
- desc "Remove local build setup"
37
- task :remove do
38
- run_locally do
39
- debug "Using builder: #{MRSK.builder.name}"
40
- execute *MRSK.builder.remove
41
- end
42
- end
43
-
44
- desc "Show the name of the configured builder"
45
- task :info do
46
- run_locally do
47
- puts "Builder: #{MRSK.builder.name} (#{MRSK.builder.target.class.name})"
48
- puts capture(*MRSK.builder.info)
49
- end
50
- end
51
- end
52
- end
@@ -1,37 +0,0 @@
1
- require_relative "setup"
2
-
3
- namespace :mrsk do
4
- desc "Deploy app for the first time to a fresh server"
5
- task fresh: %w[ server:bootstrap registry:login build:deliver traefik:run app:stop app:run ]
6
-
7
- desc "Push the latest version of the app, ensure Traefik is running, then restart app"
8
- task deploy: %w[ registry:login build:deliver traefik:run app:stop app:run prune ]
9
-
10
- desc "Rollback to VERSION=x that was already run as a container on servers"
11
- task rollback: %w[ app:restart ]
12
-
13
- desc "Display information about Traefik and app containers"
14
- task info: %w[ traefik:info app:info ]
15
-
16
- desc "Create config stub in config/deploy.yml"
17
- task :init do
18
- require "fileutils"
19
-
20
- if (deploy_file = Rails.root.join("config/deploy.yml")).exist?
21
- puts "Config file already exists in config/deploy.yml (remove first to create a new one)"
22
- else
23
- FileUtils.cp_r Pathname.new(File.expand_path("templates/deploy.yml", __dir__)), deploy_file
24
- puts "Created configuration file in config/deploy.yml"
25
- end
26
-
27
- if (binstub = Rails.root.join("bin/mrsk")).exist?
28
- puts "Binstub already exists in bin/mrsk (remove first to create a new one)"
29
- else
30
- FileUtils.cp_r Pathname.new(File.expand_path("templates/mrsk", __dir__)), binstub
31
- puts "Created binstub file in bin/mrsk"
32
- end
33
- end
34
-
35
- desc "Remove Traefik, app, and registry session from servers"
36
- task remove: %w[ traefik:remove app:remove registry:logout ]
37
- end
@@ -1,18 +0,0 @@
1
- require_relative "setup"
2
-
3
- namespace :mrsk do
4
- desc "Prune unused images and stopped containers"
5
- task prune: %w[ prune:containers prune:images ]
6
-
7
- namespace :prune do
8
- desc "Prune unused images older than 30 days"
9
- task :images do
10
- on(MRSK.config.hosts) { MRSK.verbosity(:debug) { execute *MRSK.prune.images } }
11
- end
12
-
13
- desc "Prune stopped containers for the service older than 3 days"
14
- task :containers do
15
- on(MRSK.config.hosts) { MRSK.verbosity(:debug) { execute *MRSK.prune.containers } }
16
- end
17
- end
18
- end
@@ -1,16 +0,0 @@
1
- require_relative "setup"
2
-
3
- namespace :mrsk do
4
- namespace :registry do
5
- desc "Login to the registry locally and remotely"
6
- task :login do
7
- run_locally { execute *MRSK.registry.login }
8
- on(MRSK.config.hosts) { execute *MRSK.registry.login }
9
- end
10
-
11
- desc "Logout of the registry remotely"
12
- task :logout do
13
- on(MRSK.config.hosts) { execute *MRSK.registry.logout }
14
- end
15
- end
16
- end
@@ -1,11 +0,0 @@
1
- require_relative "setup"
2
-
3
- namespace :mrsk do
4
- namespace :server do
5
- desc "Setup Docker on the remote servers"
6
- task :bootstrap do
7
- # FIXME: Detect when apt-get is not available and use the appropriate alternative
8
- on(MRSK.config.hosts) { execute "apt-get install docker.io -y" }
9
- end
10
- end
11
- end
@@ -1,6 +0,0 @@
1
- require "sshkit"
2
- require "sshkit/dsl"
3
-
4
- include SSHKit::DSL
5
-
6
- MRSK = Mrsk::Commander.new config_file: Rails.root.join("config/deploy.yml"), verbose: ENV["VERBOSE"]
@@ -1,24 +0,0 @@
1
- # Name of your application will be used for uniquely configuring Traefik and app containers.
2
- # Your Dockerfile should set LABEL service=the-same-value to ensure image pruning works.
3
- service: my-app
4
-
5
- # Name of the container image
6
- image: user/my-app
7
-
8
- # All the servers targeted for deploy. You can reference a single server for a command by using SERVERS=192.168.0.1
9
- servers:
10
- - 192.168.0.1
11
-
12
- # The following envs are made available to the container when started
13
- env:
14
- # Remember never to put passwords or tokens directly into this file, use encrypted credentials
15
- # REDIS_URL: redis://x/y
16
-
17
- # Where your images will be hosted
18
- registry:
19
- # Specify the registry server, if you're not using Docker Hub
20
- # server: registry.digitalocean.com / ghcr.io / ...
21
-
22
- # Set credentials with bin/rails credentials:edit
23
- username: my-user
24
- password: my-password-should-go-in-credentials
@@ -1,8 +0,0 @@
1
- #!/bin/bash
2
-
3
- if [ "${*}" == "" ]; then
4
- # Improve so list matches
5
- exec bin/rake -T mrsk
6
- else
7
- exec bin/rake "mrsk:$@"
8
- fi
@@ -1,41 +0,0 @@
1
- require_relative "setup"
2
-
3
- namespace :mrsk do
4
- namespace :traefik do
5
- desc "Run Traefik on servers"
6
- task :run do
7
- on(MRSK.config.role(:web).hosts) { execute *MRSK.traefik.run, raise_on_non_zero_exit: false }
8
- end
9
-
10
- desc "Start existing Traefik on servers"
11
- task :start do
12
- on(MRSK.config.role(:web).hosts) { execute *MRSK.traefik.start, raise_on_non_zero_exit: false }
13
- end
14
-
15
- desc "Stop Traefik on servers"
16
- task :stop do
17
- on(MRSK.config.role(:web).hosts) { execute *MRSK.traefik.stop, raise_on_non_zero_exit: false }
18
- end
19
-
20
- desc "Restart Traefik on servers"
21
- task restart: %i[ stop start ]
22
-
23
- desc "Display information about Traefik containers from servers"
24
- task :info do
25
- on(MRSK.config.role(:web).hosts) { |host| puts "Traefik Host: #{host}\n" + capture(*MRSK.traefik.info) + "\n\n" }
26
- end
27
-
28
- desc "Show last 100 log lines from Traefik on servers"
29
- task :logs do
30
- on(MRSK.config.hosts) { |host| puts "Traefik Host: #{host}\n" + capture(*MRSK.traefik.logs) + "\n\n" }
31
- end
32
-
33
- desc "Remove Traefik container and image from servers"
34
- task remove: %i[ stop ] do
35
- on(MRSK.config.role(:web).hosts) do
36
- execute *MRSK.traefik.remove_container
37
- execute *MRSK.traefik.remove_image
38
- end
39
- end
40
- end
41
- end