mrsk 0.2.0 → 0.3.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: 04a17f68f19cfaf130747feded6450c389fdcb01bb83c4d44b1acb0c33d6fb60
4
- data.tar.gz: 4d60e6c22acd3bf07fa22b0e488138166cf2265cedcd102ebb3245bb6318f5e0
3
+ metadata.gz: a3cbef66064bc4d1a20707788eefd3827d4054d1278d85a8e2b425c4c5ad643e
4
+ data.tar.gz: 26e48f594d93f1b1a409a4601cc43c6d62fc35e935c7000c17addd6d5f720ac9
5
5
  SHA512:
6
- metadata.gz: 379a355dafd696bbe470367c712e318e6ff9b215143059bde147dc1fdca2870bc7e46a1f47057976c2c6a5ec2601ca7cef722d928c33d3b0f1ee0700a1ee934c
7
- data.tar.gz: b0a6a7e0efa5824e116c3728726a3be1d6c9310903eefa992411a2d91731dddd8db6903d6a8697c5d5643b831b39adad9ec088ff28262d5b79e4f4aad3a90c46
6
+ metadata.gz: 3c84c6bada6dc82715349630807685d4f8a6c5dd64995760efd88666bc99a1c1b20230f47b23a7b71f8dfab5f4b2f34317d1fd2a5245b8c8a6b45575fa606002
7
+ data.tar.gz: 83565d28bcde4d782a829312685c2669512f6111233685309b015ed2b087ac5557456faae0460f472b18c480ef20892ae712a07f1b22de2cb2340a9f187c936b
data/README.md CHANGED
@@ -244,6 +244,14 @@ ARG RUBY_VERSION
244
244
  FROM ruby:$RUBY_VERSION-slim as base
245
245
  ```
246
246
 
247
+ ### Using without RAILS_MASTER_KEY
248
+
249
+ If you're using MRSK with older Rails apps that predate RAILS_MASTER_KEY, or with a non-Rails app, you can skip the default usage and reference:
250
+
251
+ ```yaml
252
+ skip_master_key: true
253
+ ```
254
+
247
255
  ### Using accessories for database, cache, search services
248
256
 
249
257
  You can manage your accessory services via MRSK as well. The services will build off public images, and will not be automatically updated when you deploy:
data/bin/mrsk CHANGED
@@ -1,5 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ # Prevent failures from being reported twice.
4
+ Thread.report_on_exception = false
5
+
3
6
  require "mrsk/cli"
4
7
 
5
- Mrsk::Cli::Main.start(ARGV)
8
+ begin
9
+ Mrsk::Cli::Main.start(ARGV)
10
+ rescue SSHKit::Runner::ExecuteError => e
11
+ puts " \e[31mERROR (#{e.cause.class}): #{e.cause.message}\e[0m"
12
+ puts e.cause.backtrace if ENV["VERBOSE"]
13
+ end
@@ -1,41 +1,104 @@
1
1
  require "mrsk/cli/base"
2
2
 
3
3
  class Mrsk::Cli::Accessory < Mrsk::Cli::Base
4
- desc "boot [NAME]", "Boot accessory service on host"
4
+ desc "boot [NAME]", "Boot accessory service on host (use NAME=all to boot all accessories)"
5
5
  def boot(name)
6
- accessory = MRSK.accessory(name)
7
- on(accessory.host) { execute *accessory.run }
6
+ if name == "all"
7
+ MRSK.accessory_names.each { |accessory_name| boot(accessory_name) }
8
+ else
9
+ with_accessory(name) do |accessory|
10
+ directories(name)
11
+ upload(name)
12
+ on(accessory.host) { execute *accessory.run }
13
+ end
14
+ end
15
+ end
16
+
17
+ desc "upload [NAME]", "Upload accessory files to host"
18
+ def upload(name)
19
+ with_accessory(name) do |accessory|
20
+ on(accessory.host) do
21
+ accessory.files.each do |(local, remote)|
22
+ accessory.ensure_local_file_present(local)
23
+
24
+ execute *accessory.make_directory_for(remote)
25
+ upload! local, remote
26
+ execute :chmod, "755", remote
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ desc "directories [NAME]", "Create accessory directories on host"
33
+ def directories(name)
34
+ with_accessory(name) do |accessory|
35
+ on(accessory.host) do
36
+ accessory.directories.keys.each do |host_path|
37
+ execute *accessory.make_directory(host_path)
38
+ end
39
+ end
40
+ end
8
41
  end
9
42
 
10
43
  desc "reboot [NAME]", "Reboot accessory on host (stop container, remove container, start new container)"
11
44
  def reboot(name)
12
- invoke :stop, [ name ]
13
- invoke :remove_container, [ name ]
14
- invoke :boot, [ name ]
45
+ with_accessory(name) do |accessory|
46
+ stop(name)
47
+ remove_container(name)
48
+ boot(name)
49
+ end
15
50
  end
16
51
 
17
52
  desc "start [NAME]", "Start existing accessory on host"
18
53
  def start(name)
19
- accessory = MRSK.accessory(name)
20
- on(accessory.host) { execute *accessory.start }
54
+ with_accessory(name) do |accessory|
55
+ on(accessory.host) { execute *accessory.start }
56
+ end
21
57
  end
22
58
 
23
59
  desc "stop [NAME]", "Stop accessory on host"
24
60
  def stop(name)
25
- accessory = MRSK.accessory(name)
26
- on(accessory.host) { execute *accessory.stop }
61
+ with_accessory(name) do |accessory|
62
+ on(accessory.host) { execute *accessory.stop, raise_on_non_zero_exit: false }
63
+ end
27
64
  end
28
65
 
29
66
  desc "restart [NAME]", "Restart accessory on host"
30
67
  def restart(name)
31
- invoke :stop, [ name ]
32
- invoke :start, [ name ]
68
+ with_accessory(name) do
69
+ stop(name)
70
+ start(name)
71
+ end
33
72
  end
34
73
 
35
- desc "details [NAME]", "Display details about accessory on host"
74
+ desc "details [NAME]", "Display details about accessory on host (use NAME=all to boot all accessories)"
36
75
  def details(name)
37
- accessory = MRSK.accessory(name)
38
- on(accessory.host) { puts capture_with_info(*accessory.info) }
76
+ if name == "all"
77
+ MRSK.accessory_names.each { |accessory_name| details(accessory_name) }
78
+ else
79
+ with_accessory(name) do |accessory|
80
+ on(accessory.host) { puts capture_with_info(*accessory.info) }
81
+ end
82
+ end
83
+ end
84
+
85
+ desc "exec [NAME] [CMD]", "Execute a custom command on accessory host"
86
+ option :run, type: :boolean, default: false, desc: "Start a new container to run the command rather than reusing existing"
87
+ def exec(name, cmd)
88
+ with_accessory(name) do |accessory|
89
+ runner = options[:run] ? :run_exec : :exec
90
+ on(accessory.host) { |host| puts_by_host host, capture_with_info(*accessory.send(runner, cmd)) }
91
+ end
92
+ end
93
+
94
+ desc "bash [NAME]", "Start a bash session on primary host (or specific host set by --hosts)"
95
+ def bash(name)
96
+ with_accessory(name) do |accessory|
97
+ run_locally do
98
+ info "Launching bash session on #{accessory.host}"
99
+ exec accessory.bash(host: accessory.host)
100
+ end
101
+ end
39
102
  end
40
103
 
41
104
  desc "logs [NAME]", "Show log lines from accessory on host"
@@ -44,42 +107,75 @@ class Mrsk::Cli::Accessory < Mrsk::Cli::Base
44
107
  option :grep, aliases: "-g", desc: "Show lines with grep match only (use this to fetch specific requests by id)"
45
108
  option :follow, aliases: "-f", desc: "Follow logs on primary server (or specific host set by --hosts)"
46
109
  def logs(name)
47
- accessory = MRSK.accessory(name)
48
-
49
- grep = options[:grep]
110
+ with_accessory(name) do |accessory|
111
+ grep = options[:grep]
50
112
 
51
- if options[:follow]
52
- run_locally do
53
- info "Following logs on #{accessory.host}..."
54
- info accessory.follow_logs(grep: grep)
55
- exec accessory.follow_logs(grep: grep)
56
- end
57
- else
58
- since = options[:since]
59
- lines = options[:lines]
113
+ if options[:follow]
114
+ run_locally do
115
+ info "Following logs on #{accessory.host}..."
116
+ info accessory.follow_logs(grep: grep)
117
+ exec accessory.follow_logs(grep: grep)
118
+ end
119
+ else
120
+ since = options[:since]
121
+ lines = options[:lines]
60
122
 
61
- on(accessory.host) do
62
- puts capture_with_info(*accessory.logs(since: since, lines: lines, grep: grep))
123
+ on(accessory.host) do
124
+ puts capture_with_info(*accessory.logs(since: since, lines: lines, grep: grep))
125
+ end
63
126
  end
64
127
  end
65
128
  end
66
129
 
67
- desc "remove [NAME]", "Remove accessory container and image from host"
130
+ desc "remove [NAME]", "Remove accessory container and image from host (use NAME=all to boot all accessories)"
68
131
  def remove(name)
69
- invoke :stop, [ name ]
70
- invoke :remove_container, [ name ]
71
- invoke :remove_image, [ name ]
132
+ if name == "all"
133
+ MRSK.accessory_names.each { |accessory_name| remove(accessory_name) }
134
+ else
135
+ with_accessory(name) do
136
+ stop(name)
137
+ remove_container(name)
138
+ remove_image(name)
139
+ remove_service_directory(name)
140
+ end
141
+ end
72
142
  end
73
143
 
74
144
  desc "remove_container [NAME]", "Remove accessory container from host"
75
145
  def remove_container(name)
76
- accessory = MRSK.accessory(name)
77
- on(accessory.host) { execute *accessory.remove_container }
146
+ with_accessory(name) do |accessory|
147
+ on(accessory.host) { execute *accessory.remove_container }
148
+ end
78
149
  end
79
150
 
80
- desc "remove_container [NAME]", "Remove accessory image from servers"
151
+ desc "remove_container [NAME]", "Remove accessory image from host"
81
152
  def remove_image(name)
82
- accessory = MRSK.accessory(name)
83
- on(accessory.host) { execute *accessory.remove_image }
153
+ with_accessory(name) do |accessory|
154
+ on(accessory.host) { execute *accessory.remove_image }
155
+ end
156
+ end
157
+
158
+ desc "remove_service_directory [NAME]", "Remove accessory directory used for uploaded files and data directories from host"
159
+ def remove_service_directory(name)
160
+ with_accessory(name) do |accessory|
161
+ on(accessory.host) { execute *accessory.remove_service_directory }
162
+ end
84
163
  end
164
+
165
+ private
166
+ def with_accessory(name)
167
+ if accessory = MRSK.accessory(name)
168
+ yield accessory
169
+ else
170
+ error_on_missing_accessory(name)
171
+ end
172
+ end
173
+
174
+ def error_on_missing_accessory(name)
175
+ options = MRSK.accessory_names.presence
176
+
177
+ error \
178
+ "No accessory by the name of '#{name}'" +
179
+ (options ? " (options: #{options.to_sentence})" : "")
180
+ end
85
181
  end
data/lib/mrsk/cli/app.rb CHANGED
@@ -40,10 +40,24 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
40
40
  end
41
41
 
42
42
  desc "exec [CMD]", "Execute a custom command on servers"
43
- option :run, type: :boolean, default: false, desc: "Start a new container to run the command rather than reusing existing"
43
+ option :method, aliases: "-m", default: "exec", desc: "Execution method: [exec] perform inside app container / [run] perform in new container / [ssh] perform over ssh"
44
44
  def exec(cmd)
45
- runner = options[:run] ? :run_exec : :exec
46
- on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.send(runner, 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)
57
+ end
58
+ else
59
+ on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.send(runner, cmd)) }
60
+ end
47
61
  end
48
62
 
49
63
  desc "console", "Start Rails Console on primary host (or specific host set by --hosts)"
@@ -10,14 +10,21 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base
10
10
  desc "push", "Build locally and push app image to registry"
11
11
  def push
12
12
  verbose = options[:verbose]
13
+ cli = self
13
14
 
14
15
  run_locally do
15
16
  begin
16
17
  MRSK.verbosity(:debug) { execute *MRSK.builder.push }
17
18
  rescue SSHKit::Command::Failed => e
18
- error "Missing compatible builder, so creating a new one first"
19
- execute *MRSK.builder.create
20
- MRSK.verbosity(:debug) { execute *MRSK.builder.push }
19
+ if e.message =~ /(no builder)|(no such file or directory)/
20
+ error "Missing compatible builder, so creating a new one first"
21
+
22
+ if cli.create
23
+ MRSK.verbosity(:debug) { execute *MRSK.builder.push }
24
+ end
25
+ else
26
+ raise
27
+ end
21
28
  end
22
29
  end
23
30
  end
@@ -30,8 +37,17 @@ class Mrsk::Cli::Build < Mrsk::Cli::Base
30
37
  desc "create", "Create a local build setup"
31
38
  def create
32
39
  run_locally do
33
- debug "Using builder: #{MRSK.builder.name}"
34
- execute *MRSK.builder.create
40
+ begin
41
+ debug "Using builder: #{MRSK.builder.name}"
42
+ execute *MRSK.builder.create
43
+ rescue SSHKit::Command::Failed => e
44
+ if e.message =~ /stderr=(.*)/
45
+ error "Couldn't create remote builder: #{$1}"
46
+ false
47
+ else
48
+ raise
49
+ end
50
+ end
35
51
  end
36
52
  end
37
53
 
data/lib/mrsk/cli/main.rb CHANGED
@@ -9,6 +9,15 @@ require "mrsk/cli/server"
9
9
  require "mrsk/cli/traefik"
10
10
 
11
11
  class Mrsk::Cli::Main < Mrsk::Cli::Base
12
+ desc "setup", "Setup all accessories and deploy the app to servers"
13
+ def setup
14
+ print_runtime do
15
+ invoke "mrsk:cli:server:bootstrap"
16
+ invoke "mrsk:cli:accessory:boot", [ "all" ]
17
+ deploy
18
+ end
19
+ end
20
+
12
21
  desc "deploy", "Deploy the app to servers"
13
22
  def deploy
14
23
  print_runtime do
@@ -43,12 +52,13 @@ class Mrsk::Cli::Main < Mrsk::Cli::Base
43
52
  def details
44
53
  invoke "mrsk:cli:traefik:details"
45
54
  invoke "mrsk:cli:app:details"
55
+ invoke "mrsk:cli:accessory:details", [ "all" ]
46
56
  end
47
57
 
48
58
  desc "config", "Show combined config"
49
59
  def config
50
60
  run_locally do
51
- pp MRSK.config.to_h
61
+ puts MRSK.config.to_h.to_yaml
52
62
  end
53
63
  end
54
64
 
@@ -3,6 +3,6 @@ require "mrsk/cli/base"
3
3
  class Mrsk::Cli::Server < Mrsk::Cli::Base
4
4
  desc "bootstrap", "Ensure Docker is installed on the servers"
5
5
  def bootstrap
6
- on(MRSK.hosts) { execute "which docker || (apt-get update -y && apt-get install docker.io -y)" }
6
+ on(MRSK.hosts + MRSK.accessory_hosts) { execute "which docker || (apt-get update -y && apt-get install docker.io -y)" }
7
7
  end
8
8
  end
@@ -48,6 +48,10 @@ class Mrsk::Commander
48
48
  specific_hosts || config.accessories.collect(&:host)
49
49
  end
50
50
 
51
+ def accessory_names
52
+ config.accessories&.collect(&:name) || []
53
+ end
54
+
51
55
 
52
56
  def app
53
57
  @app ||= Mrsk::Commands::App.new(config)
@@ -70,7 +74,7 @@ class Mrsk::Commander
70
74
  end
71
75
 
72
76
  def accessory(name)
73
- (@accessories ||= {})[name] ||= Mrsk::Commands::Accessory.new(config, name: name)
77
+ config.accessories.detect { |a| a.name == name }
74
78
  end
75
79
 
76
80
 
@@ -2,7 +2,7 @@ require "mrsk/commands/base"
2
2
 
3
3
  class Mrsk::Commands::Accessory < Mrsk::Commands::Base
4
4
  attr_reader :accessory_config
5
- delegate :service_name, :image, :host, :port, :env_args, :volume_args, :label_args, to: :accessory_config
5
+ delegate :service_name, :image, :host, :port, :files, :directories, :env_args, :volume_args, :label_args, to: :accessory_config
6
6
 
7
7
  def initialize(config, name:)
8
8
  super(config)
@@ -46,6 +46,47 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
46
46
  ).join(" "), host: host
47
47
  end
48
48
 
49
+ def exec(*command, interactive: false)
50
+ docker :exec,
51
+ ("-it" if interactive),
52
+ *env_args,
53
+ *volume_args,
54
+ service_name,
55
+ *command
56
+ end
57
+
58
+ def run_exec(*command, interactive: false)
59
+ docker :run,
60
+ ("-it" if interactive),
61
+ "--rm",
62
+ *env_args,
63
+ *volume_args,
64
+ image,
65
+ *command
66
+ end
67
+
68
+ def bash(host:)
69
+ exec_over_ssh "bash", host: host
70
+ end
71
+
72
+ def ensure_local_file_present(local_file)
73
+ if !local_file.is_a?(StringIO) && !Pathname.new(local_file).exist?
74
+ raise "Missing file: #{local_file}"
75
+ end
76
+ end
77
+
78
+ def make_directory_for(remote_file)
79
+ make_directory Pathname.new(remote_file).dirname.to_s
80
+ end
81
+
82
+ def make_directory(path)
83
+ [ :mkdir, "-p", path ]
84
+ end
85
+
86
+ def remove_service_directory
87
+ [ :rm, "-rf", service_name ]
88
+ end
89
+
49
90
  def remove_container
50
91
  docker :container, :prune, "-f", *service_filter
51
92
  end
@@ -55,6 +96,10 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
55
96
  end
56
97
 
57
98
  private
99
+ def exec_over_ssh(*command, host:)
100
+ run_over_ssh run_exec(*command, interactive: true).join(" "), host: host
101
+ end
102
+
58
103
  def service_filter
59
104
  [ "--filter", "label=service=#{service_name}" ]
60
105
  end
@@ -60,6 +60,10 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
60
60
  *command
61
61
  end
62
62
 
63
+ def exec_over_ssh(*command, host:)
64
+ run_over_ssh run_exec(*command, interactive: true).join(" "), host: host
65
+ end
66
+
63
67
  def follow_logs(host:, grep: nil)
64
68
  run_over_ssh pipe(
65
69
  current_container_id,
@@ -89,15 +93,15 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
89
93
  end
90
94
 
91
95
  private
92
- def exec_over_ssh(*command, host:)
93
- run_over_ssh run_exec(*command, interactive: true).join(" "), host: host
94
- end
95
-
96
96
  def service_filter
97
97
  [ "--filter", "label=service=#{config.service}" ]
98
98
  end
99
99
 
100
100
  def rails_master_key_arg
101
- [ "-e", redact("RAILS_MASTER_KEY=#{config.master_key}") ]
101
+ if master_key = config.master_key
102
+ [ "-e", redact("RAILS_MASTER_KEY=#{master_key}") ]
103
+ else
104
+ []
105
+ end
102
106
  end
103
107
  end
@@ -16,6 +16,10 @@ module Mrsk::Commands
16
16
  .tap { |commands| commands.pop } # Remove trailing combiner
17
17
  end
18
18
 
19
+ def chain(*commands)
20
+ combine *commands, by: ";"
21
+ end
22
+
19
23
  def pipe(*commands)
20
24
  combine *commands, by: "|"
21
25
  end
@@ -2,13 +2,13 @@ require "mrsk/commands/builder/native"
2
2
 
3
3
  class Mrsk::Commands::Builder::Native::Remote < Mrsk::Commands::Builder::Native
4
4
  def create
5
- combine \
5
+ chain \
6
6
  create_context,
7
7
  create_buildx
8
8
  end
9
9
 
10
10
  def remove
11
- combine \
11
+ chain \
12
12
  remove_context,
13
13
  remove_buildx
14
14
  end
@@ -25,7 +25,7 @@ class Mrsk::Commands::Builder::Native::Remote < Mrsk::Commands::Builder::Native
25
25
  end
26
26
 
27
27
  def info
28
- combine \
28
+ chain \
29
29
  docker(:context, :ls),
30
30
  docker(:buildx, :ls)
31
31
  end
@@ -43,8 +43,22 @@ class Mrsk::Configuration::Assessory
43
43
  argumentize_env_with_secrets env
44
44
  end
45
45
 
46
+ def files
47
+ specifics["files"]&.to_h do |local_to_remote_mapping|
48
+ local_file, remote_file = local_to_remote_mapping.split(":")
49
+ [ expand_local_file(local_file), expand_remote_file(remote_file) ]
50
+ end || {}
51
+ end
52
+
53
+ def directories
54
+ specifics["directories"]&.to_h do |host_to_container_mapping|
55
+ host_relative_path, container_path = host_to_container_mapping.split(":")
56
+ [ expand_host_path(host_relative_path), container_path ]
57
+ end || {}
58
+ end
59
+
46
60
  def volumes
47
- specifics["volumes"] || []
61
+ specific_volumes + remote_files_as_volumes + remote_directories_as_volumes
48
62
  end
49
63
 
50
64
  def volume_args
@@ -57,4 +71,46 @@ class Mrsk::Configuration::Assessory
57
71
  def default_labels
58
72
  { "service" => service_name }
59
73
  end
74
+
75
+ def expand_local_file(local_file)
76
+ if local_file.end_with?("erb")
77
+ read_dynamic_file(local_file)
78
+ else
79
+ Pathname.new(File.expand_path(local_file)).to_s
80
+ end
81
+ end
82
+
83
+ def read_dynamic_file(local_file)
84
+ StringIO.new(ERB.new(IO.read(local_file)).result)
85
+ end
86
+
87
+ def expand_remote_file(remote_file)
88
+ service_name + remote_file
89
+ end
90
+
91
+ def specific_volumes
92
+ specifics["volumes"] || []
93
+ end
94
+
95
+ def remote_files_as_volumes
96
+ specifics["files"]&.collect do |local_to_remote_mapping|
97
+ _, remote_file = local_to_remote_mapping.split(":")
98
+ "#{service_data_directory + remote_file}:#{remote_file}"
99
+ end || []
100
+ end
101
+
102
+ def remote_directories_as_volumes
103
+ specifics["directories"]&.collect do |host_to_container_mapping|
104
+ host_relative_path, container_path = host_to_container_mapping.split(":")
105
+ [ expand_host_path(host_relative_path), container_path ].join(":")
106
+ end || []
107
+ end
108
+
109
+ def expand_host_path(host_relative_path)
110
+ "#{service_data_directory}/#{host_relative_path}"
111
+ end
112
+
113
+ def service_data_directory
114
+ "$PWD/#{service_name}"
115
+ end
60
116
  end
@@ -15,7 +15,7 @@ class Mrsk::Configuration
15
15
  def create_from(base_config_file, destination: nil, version: "missing")
16
16
  new(load_config_file(base_config_file).tap do |config|
17
17
  if destination
18
- config.merge! \
18
+ config.deep_merge! \
19
19
  load_config_file destination_config_file(base_config_file, destination)
20
20
  end
21
21
  end, version: version)
@@ -52,7 +52,7 @@ class Mrsk::Configuration
52
52
  end
53
53
 
54
54
  def accessories
55
- @accessories ||= raw_config.accessories.keys.collect { |name| Mrsk::Configuration::Assessory.new(name, config: self) }
55
+ @accessories ||= raw_config.accessories&.keys&.collect { |name| Mrsk::Configuration::Assessory.new(name, config: self) } || []
56
56
  end
57
57
 
58
58
  def accessory(name)
@@ -115,7 +115,9 @@ class Mrsk::Configuration
115
115
  end
116
116
 
117
117
  def master_key
118
- ENV["RAILS_MASTER_KEY"] || File.read(Pathname.new(File.expand_path("config/master.key")))
118
+ unless raw_config.skip_master_key
119
+ ENV["RAILS_MASTER_KEY"] || File.read(Pathname.new(File.expand_path("config/master.key")))
120
+ end
119
121
  end
120
122
 
121
123
  def to_h
@@ -130,7 +132,8 @@ class Mrsk::Configuration
130
132
  env_args: env_args,
131
133
  volume_args: volume_args,
132
134
  ssh_options: ssh_options,
133
- builder: raw_config.builder
135
+ builder: raw_config.builder,
136
+ accessories: raw_config.accessories
134
137
  }.compact
135
138
  end
136
139
 
data/lib/mrsk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mrsk
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.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.2.0
4
+ version: 0.3.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-23 00:00:00.000000000 Z
11
+ date: 2023-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -113,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  - !ruby/object:Gem::Version
114
114
  version: '0'
115
115
  requirements: []
116
- rubygems_version: 3.4.1
116
+ rubygems_version: 3.4.5
117
117
  signing_key:
118
118
  specification_version: 4
119
119
  summary: Deploy Rails apps in containers to servers running Docker with zero downtime.