mrsk 0.0.3 → 0.2.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +193 -77
  3. data/bin/mrsk +5 -0
  4. data/lib/mrsk/cli/accessory.rb +85 -0
  5. data/lib/mrsk/cli/app.rb +123 -0
  6. data/lib/mrsk/cli/base.rb +48 -0
  7. data/lib/mrsk/cli/build.rb +53 -0
  8. data/lib/mrsk/cli/main.rb +110 -0
  9. data/lib/mrsk/cli/prune.rb +19 -0
  10. data/lib/mrsk/cli/registry.rb +18 -0
  11. data/lib/mrsk/cli/server.rb +8 -0
  12. data/lib/mrsk/cli/templates/deploy.yml +17 -0
  13. data/lib/mrsk/cli/traefik.rb +77 -0
  14. data/lib/mrsk/cli.rb +9 -0
  15. data/lib/mrsk/commander.rb +45 -5
  16. data/lib/mrsk/commands/accessory.rb +61 -0
  17. data/lib/mrsk/commands/app.rb +50 -10
  18. data/lib/mrsk/commands/base.rb +13 -9
  19. data/lib/mrsk/commands/builder/base.rb +26 -0
  20. data/lib/mrsk/commands/builder/multiarch/remote.rb +12 -4
  21. data/lib/mrsk/commands/builder/multiarch.rb +17 -9
  22. data/lib/mrsk/commands/builder/native/remote.rb +71 -0
  23. data/lib/mrsk/commands/builder/native.rb +3 -7
  24. data/lib/mrsk/commands/builder.rb +11 -7
  25. data/lib/mrsk/commands/traefik.rb +13 -3
  26. data/lib/mrsk/configuration/accessory.rb +60 -0
  27. data/lib/mrsk/configuration/role.rb +46 -14
  28. data/lib/mrsk/configuration.rb +86 -43
  29. data/lib/mrsk/sshkit_with_ext.rb +12 -0
  30. data/lib/mrsk/utils.rb +29 -0
  31. data/lib/mrsk/version.rb +1 -1
  32. data/lib/mrsk.rb +0 -1
  33. metadata +40 -18
  34. data/lib/mrsk/engine.rb +0 -4
  35. data/lib/tasks/mrsk/app.rake +0 -97
  36. data/lib/tasks/mrsk/build.rake +0 -52
  37. data/lib/tasks/mrsk/mrsk.rake +0 -37
  38. data/lib/tasks/mrsk/prune.rake +0 -18
  39. data/lib/tasks/mrsk/registry.rake +0 -16
  40. data/lib/tasks/mrsk/server.rake +0 -11
  41. data/lib/tasks/mrsk/setup.rb +0 -6
  42. data/lib/tasks/mrsk/templates/deploy.yml +0 -24
  43. data/lib/tasks/mrsk/templates/mrsk +0 -8
  44. data/lib/tasks/mrsk/traefik.rake +0 -41
@@ -15,12 +15,20 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult
15
15
  end
16
16
 
17
17
  private
18
+ def builder_name
19
+ super + "-remote"
20
+ end
21
+
22
+ def builder_name_with_arch(arch)
23
+ "#{builder_name}-#{arch}"
24
+ end
25
+
18
26
  def create_local_buildx
19
- docker :buildx, :create, "--use", "--name", "mrsk", "mrsk-#{local["arch"]}", "--platform", "linux/#{local["arch"]}"
27
+ docker :buildx, :create, "--name", builder_name, builder_name_with_arch(local["arch"]), "--platform", "linux/#{local["arch"]}"
20
28
  end
21
29
 
22
30
  def append_remote_buildx
23
- docker :buildx, :create, "--append", "--name", "mrsk", "mrsk-#{remote["arch"]}", "--platform", "linux/#{remote["arch"]}"
31
+ docker :buildx, :create, "--append", "--name", builder_name, builder_name_with_arch(remote["arch"]), "--platform", "linux/#{remote["arch"]}"
24
32
  end
25
33
 
26
34
  def create_contexts
@@ -30,7 +38,7 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult
30
38
  end
31
39
 
32
40
  def create_context(arch, host)
33
- docker :context, :create, "mrsk-#{arch}", "--description", "'MRSK #{arch} Native Host'", "--docker", "'host=#{host}'"
41
+ docker :context, :create, builder_name_with_arch(arch), "--description", "'#{builder_name} #{arch} native host'", "--docker", "'host=#{host}'"
34
42
  end
35
43
 
36
44
  def remove_contexts
@@ -40,7 +48,7 @@ class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Mult
40
48
  end
41
49
 
42
50
  def remove_context(arch)
43
- docker :context, :rm, "mrsk-#{arch}"
51
+ docker :context, :rm, builder_name_with_arch(arch)
44
52
  end
45
53
 
46
54
  def local
@@ -1,20 +1,23 @@
1
- require "mrsk/commands/base"
1
+ require "mrsk/commands/builder/base"
2
2
 
3
- class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Base
3
+ class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Builder::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
13
- docker :buildx, :build, "--push", "--platform linux/amd64,linux/arm64", "-t", config.absolute_image, "."
14
- end
15
-
16
- def pull
17
- docker :pull, config.absolute_image
13
+ docker :buildx, :build,
14
+ "--push",
15
+ "--platform", "linux/amd64,linux/arm64",
16
+ "--builder", builder_name,
17
+ "-t", config.absolute_image,
18
+ *build_args,
19
+ *build_secrets,
20
+ "."
18
21
  end
19
22
 
20
23
  def info
@@ -22,4 +25,9 @@ class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Base
22
25
  docker(:context, :ls),
23
26
  docker(:buildx, :ls)
24
27
  end
28
+
29
+ private
30
+ def builder_name
31
+ "mrsk-#{config.service}-multiarch"
32
+ end
25
33
  end
@@ -0,0 +1,71 @@
1
+ require "mrsk/commands/builder/native"
2
+
3
+ class Mrsk::Commands::Builder::Native::Remote < Mrsk::Commands::Builder::Native
4
+ def create
5
+ combine \
6
+ create_context,
7
+ create_buildx
8
+ end
9
+
10
+ def remove
11
+ combine \
12
+ remove_context,
13
+ remove_buildx
14
+ end
15
+
16
+ def push
17
+ docker :buildx, :build,
18
+ "--push",
19
+ "--platform", platform,
20
+ "--builder", builder_name,
21
+ "-t", config.absolute_image,
22
+ *build_args,
23
+ *build_secrets,
24
+ "."
25
+ end
26
+
27
+ def info
28
+ combine \
29
+ docker(:context, :ls),
30
+ docker(:buildx, :ls)
31
+ end
32
+
33
+
34
+ private
35
+ def arch
36
+ config.builder["remote"]["arch"]
37
+ end
38
+
39
+ def host
40
+ config.builder["remote"]["host"]
41
+ end
42
+
43
+ def builder_name
44
+ "mrsk-#{config.service}-native-remote"
45
+ end
46
+
47
+ def builder_name_with_arch
48
+ "#{builder_name}-#{arch}"
49
+ end
50
+
51
+ def platform
52
+ "linux/#{arch}"
53
+ end
54
+
55
+ def create_context
56
+ docker :context, :create,
57
+ builder_name_with_arch, "--description", "'#{builder_name} #{arch} native host'", "--docker", "'host=#{host}'"
58
+ end
59
+
60
+ def remove_context
61
+ docker :context, :rm, builder_name_with_arch
62
+ end
63
+
64
+ def create_buildx
65
+ docker :buildx, :create, "--name", builder_name, builder_name_with_arch, "--platform", platform
66
+ end
67
+
68
+ def remove_buildx
69
+ docker :buildx, :rm, builder_name
70
+ end
71
+ end
@@ -1,6 +1,6 @@
1
- require "mrsk/commands/base"
1
+ require "mrsk/commands/builder/base"
2
2
 
3
- class Mrsk::Commands::Builder::Native < Mrsk::Commands::Base
3
+ class Mrsk::Commands::Builder::Native < Mrsk::Commands::Builder::Base
4
4
  def create
5
5
  # No-op on native
6
6
  end
@@ -11,14 +11,10 @@ class Mrsk::Commands::Builder::Native < Mrsk::Commands::Base
11
11
 
12
12
  def push
13
13
  combine \
14
- docker(:build, "-t", config.absolute_image, "."),
14
+ docker(:build, "-t", *build_args, *build_secrets, config.absolute_image, "."),
15
15
  docker(:push, config.absolute_image)
16
16
  end
17
17
 
18
- def pull
19
- docker :pull, config.absolute_image
20
- end
21
-
22
18
  def info
23
19
  # No-op on native
24
20
  end
@@ -2,22 +2,21 @@ require "mrsk/commands/base"
2
2
 
3
3
  class Mrsk::Commands::Builder < Mrsk::Commands::Base
4
4
  delegate :create, :remove, :push, :pull, :info, to: :target
5
- delegate :native?, :multiarch?, :remote?, to: :name
6
5
 
7
6
  def name
8
- target.class.to_s.demodulize.downcase.inquiry
7
+ target.class.to_s.remove("Mrsk::Commands::Builder::").underscore
9
8
  end
10
9
 
11
10
  def target
12
11
  case
13
- when config.builder.nil?
14
- multiarch
15
- when config.builder["multiarch"] == false
12
+ when config.builder && config.builder["multiarch"] == false
16
13
  native
17
- when config.builder["local"] && config.builder["local"]
14
+ when config.builder && config.builder["local"] && config.builder["remote"]
18
15
  multiarch_remote
16
+ when config.builder && config.builder["remote"]
17
+ native_remote
19
18
  else
20
- raise ArgumentError, "Builder configuration incorrect: #{config.builder.inspect}"
19
+ multiarch
21
20
  end
22
21
  end
23
22
 
@@ -25,6 +24,10 @@ class Mrsk::Commands::Builder < Mrsk::Commands::Base
25
24
  @native ||= Mrsk::Commands::Builder::Native.new(config)
26
25
  end
27
26
 
27
+ def native_remote
28
+ @native ||= Mrsk::Commands::Builder::Native::Remote.new(config)
29
+ end
30
+
28
31
  def multiarch
29
32
  @multiarch ||= Mrsk::Commands::Builder::Multiarch.new(config)
30
33
  end
@@ -35,5 +38,6 @@ class Mrsk::Commands::Builder < Mrsk::Commands::Base
35
38
  end
36
39
 
37
40
  require "mrsk/commands/builder/native"
41
+ require "mrsk/commands/builder/native/remote"
38
42
  require "mrsk/commands/builder/multiarch"
39
43
  require "mrsk/commands/builder/multiarch/remote"
@@ -8,7 +8,8 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base
8
8
  "-p 80:80",
9
9
  "-v /var/run/docker.sock:/var/run/docker.sock",
10
10
  "traefik",
11
- "--providers.docker"
11
+ "--providers.docker",
12
+ "--log.level=DEBUG"
12
13
  end
13
14
 
14
15
  def start
@@ -23,8 +24,17 @@ class Mrsk::Commands::Traefik < Mrsk::Commands::Base
23
24
  docker :ps, "--filter", "name=traefik"
24
25
  end
25
26
 
26
- def logs
27
- docker :logs, "traefik", "-n", "100", "-t"
27
+ def logs(since: nil, lines: nil, grep: nil)
28
+ pipe \
29
+ docker(:logs, "traefik", (" --since #{since}" if since), (" -n #{lines}" if lines), "-t", "2>&1"),
30
+ ("grep '#{grep}'" if grep)
31
+ end
32
+
33
+ def follow_logs(host:, grep: nil)
34
+ run_over_ssh pipe(
35
+ docker(:logs, "traefik", "-t", "-n", "10", "-f", "2>&1"),
36
+ ("grep '#{grep}'" if grep)
37
+ ).join(" "), host: host
28
38
  end
29
39
 
30
40
  def remove_container
@@ -0,0 +1,60 @@
1
+ class Mrsk::Configuration::Assessory
2
+ delegate :argumentize, :argumentize_env_with_secrets, to: Mrsk::Utils
3
+
4
+ attr_accessor :name, :specifics
5
+
6
+ def initialize(name, config:)
7
+ @name, @config, @specifics = name.inquiry, config, config.raw_config["accessories"][name]
8
+ end
9
+
10
+ def service_name
11
+ "#{config.service}-#{name}"
12
+ end
13
+
14
+ def image
15
+ specifics["image"]
16
+ end
17
+
18
+ def host
19
+ specifics["host"] || raise(ArgumentError, "Missing host for accessory")
20
+ end
21
+
22
+ def port
23
+ if specifics["port"].to_s.include?(":")
24
+ specifics["port"]
25
+ else
26
+ "#{specifics["port"]}:#{specifics["port"]}"
27
+ end
28
+ end
29
+
30
+ def labels
31
+ default_labels.merge(specifics["labels"] || {})
32
+ end
33
+
34
+ def label_args
35
+ argumentize "--label", labels
36
+ end
37
+
38
+ def env
39
+ specifics["env"] || {}
40
+ end
41
+
42
+ def env_args
43
+ argumentize_env_with_secrets env
44
+ end
45
+
46
+ def volumes
47
+ specifics["volumes"] || []
48
+ end
49
+
50
+ def volume_args
51
+ argumentize "--volume", volumes
52
+ end
53
+
54
+ private
55
+ attr_accessor :config
56
+
57
+ def default_labels
58
+ { "service" => service_name }
59
+ end
60
+ end
@@ -1,5 +1,5 @@
1
1
  class Mrsk::Configuration::Role
2
- delegate :argumentize, to: Mrsk::Configuration
2
+ delegate :argumentize, :argumentize_env_with_secrets, to: Mrsk::Utils
3
3
 
4
4
  attr_accessor :name
5
5
 
@@ -12,21 +12,33 @@ class Mrsk::Configuration::Role
12
12
  end
13
13
 
14
14
  def labels
15
- if name.web?
16
- default_labels.merge(traefik_labels).merge(custom_labels)
17
- else
18
- default_labels.merge(custom_labels)
19
- end
15
+ default_labels.merge(traefik_labels).merge(custom_labels)
20
16
  end
21
17
 
22
18
  def label_args
23
19
  argumentize "--label", labels
24
20
  end
25
21
 
22
+ def env
23
+ if config.env && config.env["secret"]
24
+ merged_env_with_secrets
25
+ else
26
+ merged_env
27
+ end
28
+ end
29
+
30
+ def env_args
31
+ argumentize_env_with_secrets env
32
+ end
33
+
26
34
  def cmd
27
35
  specializations["cmd"]
28
36
  end
29
37
 
38
+ def running_traefik?
39
+ name.web? || specializations["traefik"]
40
+ end
41
+
30
42
  private
31
43
  attr_accessor :config
32
44
 
@@ -44,13 +56,17 @@ class Mrsk::Configuration::Role
44
56
  end
45
57
 
46
58
  def traefik_labels
47
- {
48
- "traefik.http.routers.#{config.service}.rule" => "'PathPrefix(`/`)'",
49
- "traefik.http.services.#{config.service}.loadbalancer.healthcheck.path" => "/up",
50
- "traefik.http.services.#{config.service}.loadbalancer.healthcheck.interval" => "1s",
51
- "traefik.http.middlewares.#{config.service}.retry.attempts" => "3",
52
- "traefik.http.middlewares.#{config.service}.retry.initialinterval" => "500ms"
53
- }
59
+ if running_traefik?
60
+ {
61
+ "traefik.http.routers.#{config.service}.rule" => "'PathPrefix(`/`)'",
62
+ "traefik.http.services.#{config.service}.loadbalancer.healthcheck.path" => "/up",
63
+ "traefik.http.services.#{config.service}.loadbalancer.healthcheck.interval" => "1s",
64
+ "traefik.http.middlewares.#{config.service}.retry.attempts" => "3",
65
+ "traefik.http.middlewares.#{config.service}.retry.initialinterval" => "500ms"
66
+ }
67
+ else
68
+ {}
69
+ end
54
70
  end
55
71
 
56
72
  def custom_labels
@@ -64,7 +80,23 @@ class Mrsk::Configuration::Role
64
80
  if config.servers.is_a?(Array) || config.servers[name].is_a?(Array)
65
81
  { }
66
82
  else
67
- config.servers[name].without("hosts")
83
+ config.servers[name].except("hosts")
84
+ end
85
+ end
86
+
87
+ def specialized_env
88
+ specializations["env"] || {}
89
+ end
90
+
91
+ def merged_env
92
+ config.env&.merge(specialized_env) || {}
93
+ end
94
+
95
+ # Secrets are stored in an array, which won't merge by default, so have to do it by hand.
96
+ def merged_env_with_secrets
97
+ merged_env.tap do |new_env|
98
+ new_env["secret"] = Array(config.env["secret"]) + Array(specialized_env["secret"])
99
+ new_env["clear"] = (Array(config.env["clear"] || config.env) + Array(specialized_env["clear"] || specialized_env)).uniq
68
100
  end
69
101
  end
70
102
  end
@@ -1,26 +1,44 @@
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"
6
+ require "mrsk/utils"
4
7
 
5
8
  class Mrsk::Configuration
6
- delegate :service, :image, :servers, :env, :labels, :registry, :builder, to: :config, allow_nil: true
9
+ delegate :service, :image, :servers, :env, :labels, :registry, :builder, to: :raw_config, allow_nil: true
10
+ delegate :argumentize, :argumentize_env_with_secrets, to: Mrsk::Utils
11
+
12
+ attr_accessor :raw_config
7
13
 
8
14
  class << self
9
- def load_file(file)
10
- if file.exist?
11
- new YAML.load(ERB.new(IO.read(file)).result).symbolize_keys
12
- else
13
- raise "Configuration file not found in #{file}"
14
- end
15
+ def create_from(base_config_file, destination: nil, version: "missing")
16
+ new(load_config_file(base_config_file).tap do |config|
17
+ if destination
18
+ config.merge! \
19
+ load_config_file destination_config_file(base_config_file, destination)
20
+ end
21
+ end, version: version)
15
22
  end
16
23
 
17
- def argumentize(argument, attributes)
18
- attributes.flat_map { |k, v| [ argument, "#{k}=#{v}" ] }
19
- end
24
+ private
25
+ def load_config_file(file)
26
+ if file.exist?
27
+ YAML.load(ERB.new(IO.read(file)).result).symbolize_keys
28
+ else
29
+ raise "Configuration file not found in #{file}"
30
+ end
31
+ end
32
+
33
+ def destination_config_file(base_config_file, destination)
34
+ dir, basename = base_config_file.split
35
+ dir.join basename.to_s.remove(".yml") + ".#{destination}.yml"
36
+ end
20
37
  end
21
38
 
22
- def initialize(config, validate: true)
23
- @config = ActiveSupport::InheritableOptions.new(config)
39
+ def initialize(raw_config, version: "missing", validate: true)
40
+ @raw_config = ActiveSupport::InheritableOptions.new(raw_config)
41
+ @version = version
24
42
  ensure_required_keys_present if validate
25
43
  end
26
44
 
@@ -33,36 +51,34 @@ class Mrsk::Configuration
33
51
  roles.detect { |r| r.name == name.to_s }
34
52
  end
35
53
 
36
- def hosts
37
- hosts =
38
- case
39
- when ENV["HOSTS"]
40
- ENV["HOSTS"].split(",")
41
- when ENV["ROLES"]
42
- role_names = ENV["ROLES"].split(",")
43
- roles.select { |r| role_names.include?(r.name) }.flat_map(&:hosts)
44
- else
45
- roles.flat_map(&:hosts)
46
- end
54
+ def accessories
55
+ @accessories ||= raw_config.accessories.keys.collect { |name| Mrsk::Configuration::Assessory.new(name, config: self) }
56
+ end
47
57
 
48
- if hosts.any?
49
- hosts
50
- else
51
- raise ArgumentError, "No hosts found"
52
- end
58
+ def accessory(name)
59
+ accessories.detect { |a| a.name == name.to_s }
60
+ end
61
+
62
+
63
+ def all_hosts
64
+ roles.flat_map(&:hosts)
53
65
  end
54
66
 
55
- def primary_host
67
+ def primary_web_host
56
68
  role(:web).hosts.first
57
69
  end
58
70
 
71
+ def traefik_hosts
72
+ roles.select(&:running_traefik?).flat_map(&:hosts)
73
+ end
74
+
59
75
 
60
76
  def version
61
- @version ||= ENV["VERSION"] || `git rev-parse HEAD`.strip
77
+ @version
62
78
  end
63
79
 
64
80
  def repository
65
- [ config.registry["server"], image ].compact.join("/")
81
+ [ raw_config.registry["server"], image ].compact.join("/")
66
82
  end
67
83
 
68
84
  def absolute_image
@@ -75,15 +91,23 @@ class Mrsk::Configuration
75
91
 
76
92
 
77
93
  def env_args
78
- if config.env.present?
79
- self.class.argumentize "-e", config.env
94
+ if raw_config.env.present?
95
+ argumentize_env_with_secrets(raw_config.env)
96
+ else
97
+ []
98
+ end
99
+ end
100
+
101
+ def volume_args
102
+ if raw_config.volumes.present?
103
+ argumentize "--volume", raw_config.volumes
80
104
  else
81
105
  []
82
106
  end
83
107
  end
84
108
 
85
109
  def ssh_user
86
- config.ssh_user || "root"
110
+ raw_config.ssh_user || "root"
87
111
  end
88
112
 
89
113
  def ssh_options
@@ -91,26 +115,45 @@ class Mrsk::Configuration
91
115
  end
92
116
 
93
117
  def master_key
94
- ENV["RAILS_MASTER_KEY"] || File.read(Rails.root.join("config/master.key"))
118
+ ENV["RAILS_MASTER_KEY"] || File.read(Pathname.new(File.expand_path("config/master.key")))
95
119
  end
96
120
 
121
+ def to_h
122
+ {
123
+ roles: role_names,
124
+ hosts: all_hosts,
125
+ primary_host: primary_web_host,
126
+ version: version,
127
+ repository: repository,
128
+ absolute_image: absolute_image,
129
+ service_with_version: service_with_version,
130
+ env_args: env_args,
131
+ volume_args: volume_args,
132
+ ssh_options: ssh_options,
133
+ builder: raw_config.builder
134
+ }.compact
135
+ end
97
136
 
98
- private
99
- attr_accessor :config
100
137
 
138
+ private
101
139
  def ensure_required_keys_present
102
- %i[ service image registry ].each do |key|
103
- raise ArgumentError, "Missing required configuration for #{key}" unless config[key].present?
140
+ %i[ service image registry servers ].each do |key|
141
+ raise ArgumentError, "Missing required configuration for #{key}" unless raw_config[key].present?
104
142
  end
105
143
 
106
- %w[ username password ].each do |key|
107
- raise ArgumentError, "Missing required configuration for registry/#{key}" unless config.registry[key].present?
108
- end
144
+ if raw_config.registry["username"].blank?
145
+ raise ArgumentError, "You must specify a username for the registry in config/deploy.yml"
146
+ end
147
+
148
+ if raw_config.registry["password"].blank?
149
+ raise ArgumentError, "You must specify a password for the registry in config/deploy.yml (or set the ENV variable if that's used)"
150
+ end
109
151
  end
110
152
 
111
153
  def role_names
112
- config.servers.is_a?(Array) ? [ "web" ] : config.servers.keys.sort
154
+ raw_config.servers.is_a?(Array) ? [ "web" ] : raw_config.servers.keys.sort
113
155
  end
114
156
  end
115
157
 
116
158
  require "mrsk/configuration/role"
159
+ require "mrsk/configuration/accessory"
@@ -0,0 +1,12 @@
1
+ require "sshkit"
2
+ require "sshkit/dsl"
3
+
4
+ class SSHKit::Backend::Abstract
5
+ def capture_with_info(*args)
6
+ capture(*args, verbosity: Logger::INFO)
7
+ end
8
+
9
+ def puts_by_host(host, output, type: "App")
10
+ puts "#{type} Host: #{host}\n#{output}\n\n"
11
+ end
12
+ end
data/lib/mrsk/utils.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Mrsk::Utils
2
+ extend self
3
+
4
+ # Return a list of shell arguments using the same named argument against the passed attributes (hash or array).
5
+ def argumentize(argument, attributes, redacted: false)
6
+ Array(attributes).flat_map do |k, v|
7
+ if v.present?
8
+ [ argument, redacted ? redact("#{k}=#{v}") : "#{k}=#{v}" ]
9
+ else
10
+ [ argument, k ]
11
+ end
12
+ end
13
+ end
14
+
15
+ # Return a list of shell arguments using the same named argument against the passed attributes,
16
+ # but redacts and expands secrets.
17
+ def argumentize_env_with_secrets(env)
18
+ if (secrets = env["secret"]).present?
19
+ argumentize("-e", secrets.to_h { |key| [ key, ENV.fetch(key) ] }, redacted: true) + argumentize("-e", env["clear"])
20
+ else
21
+ argumentize "-e", env
22
+ end
23
+ end
24
+
25
+ # Copied from SSHKit::Backend::Abstract#redact to be available inside Commands classes
26
+ def redact(arg) # Used in execute_command to hide redact() args a user passes in
27
+ arg.to_s.extend(SSHKit::Redaction) # to_s due to our inability to extend Integer, etc
28
+ end
29
+ end
data/lib/mrsk/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mrsk
2
- VERSION = "0.0.3"
2
+ VERSION = "0.2.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"