Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop into old main #2

Open
wants to merge 37 commits into
base: old-main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
f5d1620
Add -t argument to envify
Zeko369 Jun 22, 2023
2432032
Fix default value and add tests
Zeko369 Jun 22, 2023
17571eb
Add option to output and then read .env file from specific path
Zeko369 Jun 23, 2023
b4eee8a
Merge branch 'feature/add-env-outputs' into develop
Zeko369 Jun 23, 2023
27ce26b
Cleanup
Zeko369 Jun 26, 2023
78be2a8
Fix wrong logical assertion
Zeko369 Jun 26, 2023
490eb48
Merge branch 'feature/add-env-outputs' into develop
Zeko369 Jun 26, 2023
7db7b02
Merge branch 'feature/pass-custom-template-for-envify' into develop
Zeko369 Jun 26, 2023
abf4f5a
Fix
Zeko369 Jun 26, 2023
5472370
Make sure to create nested path if missing
Zeko369 Jun 26, 2023
b769d43
push all
Zeko369 Jun 26, 2023
bd71192
Remove unused import
Zeko369 Jun 26, 2023
2cb5d90
Merge branch 'feature/add-env-outputs' into develop
Zeko369 Jun 26, 2023
bb6ec8c
Ignore .vscode/.idea folders
Zeko369 Jun 27, 2023
c5ec8b1
Wip add base logic for optional secrets
Zeko369 Jun 27, 2023
2945880
Merge branch 'feature/optional-env-variables' into develop
Zeko369 Jun 27, 2023
e17e4a9
Add initial delay to healtchecks
Zeko369 Jun 27, 2023
e82eaaf
Merge branch 'feature/add-delay-to-healthchecks' into develop
Zeko369 Jun 27, 2023
8c54359
Cleanup output of `envify`
Zeko369 Jul 9, 2023
4a7984a
Fix typo
Zeko369 Jul 9, 2023
245bd78
Fix line replacement + add tests
Zeko369 Jul 9, 2023
b0cccc1
Ignore .idea folder
Zeko369 Jul 9, 2023
dd52a45
Cleanup output of envify
Zeko369 Jul 9, 2023
abfef80
Cleanup output of envify
Zeko369 Jul 9, 2023
f9e9232
Ignore .idea folder
Zeko369 Jul 13, 2023
0416363
Allow usage of .yml.erb and .yml files
Zeko369 Jul 13, 2023
a1a927b
Add tests for .yml.erb support
Zeko369 Jul 13, 2023
9ab4fdc
Simplify extension replacement
Zeko369 Jul 13, 2023
a43357f
Merge branch 'feature/support-yml-erb-files' into develop
Zeko369 Jul 13, 2023
33eb19c
Expose `MRSK_DESTINATION` when loading deploy.yml
Zeko369 Jul 13, 2023
1154bb8
Merge branch 'feature/pass-custom-template-for-envify' into develop
Zeko369 Jul 13, 2023
7d4ddf3
Fix clear overrides secrets
Zeko369 Jul 19, 2023
ac88495
fix wrong key
Zeko369 Jul 19, 2023
2991ca4
Fix again..
Zeko369 Jul 19, 2023
6d53e18
Return a lot more logs onn failure
Zeko369 Aug 24, 2023
dc899d1
Try loading the bin
Zeko369 Aug 27, 2023
e08435b
Setup load bin/mrsk if possible
Zeko369 Aug 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
coverage/*
.DS_Store
gemfiles/*.lock
.vscode/
.idea/
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions .idea/mrsk.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions bin/mrsk
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# Prevent failures from being reported twice.
Thread.report_on_exception = false

require_relative '../lib/loader'
p Loader.methods - Object.methods
Loader::load_local_bin # local bin is found this command exists so the rest of the code doesn't run

require "mrsk"

begin
Expand Down
28 changes: 28 additions & 0 deletions lib/loader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Loader
LOCAL_BIN = 'bin/mrsk'

def load_local_bin
original_cwd = Dir.pwd

loop do
if bin_exists?
exec LOCAL_BIN, *ARGV
end

# If we exhaust the search there is no executable, run bundled mrsk from original cwd
Dir.chdir(original_cwd) && return if Pathname.new(Dir.pwd).root?

# Otherwise keep moving upwards in search of an executable.
Dir.chdir("..")
end
end

private

def bin_exists?
return unless File.exist?(LOCAL_BIN) || File.executable?(LOCAL_BIN)
return unless File.read(LOCAL_BIN, 300).include?("This file was generated by Bundler")

true
end
end
7 changes: 4 additions & 3 deletions lib/mrsk/cli/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def self.exit_on_failure?() true end

class_option :config_file, aliases: "-c", default: "config/deploy.yml", desc: "Path to config file"
class_option :destination, aliases: "-d", desc: "Specify destination to be used for config file (staging -> deploy.staging.yml)"
class_option :env_path, aliases: "-e", default: ".env", desc: "Path to env file"

class_option :skip_hooks, aliases: "-H", type: :boolean, default: false, desc: "Don't run hooks"

Expand All @@ -30,10 +31,10 @@ def initialize(*)

private
def load_envs
if destination = options[:destination]
Dotenv.load(".env.#{destination}", ".env")
if (destination = options[:destination])
Dotenv.load("#{options[:env_path]}.#{destination}", options[:env_path])
else
Dotenv.load(".env")
Dotenv.load(options[:env_path])
end
end

Expand Down
25 changes: 17 additions & 8 deletions lib/mrsk/cli/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,9 @@ def init
puts "Created configuration file in config/deploy.yml"
end

unless (deploy_file = Pathname.new(File.expand_path(".env"))).exist?
unless (deploy_file = Pathname.new(File.expand_path(options[:env_path]))).exist?
FileUtils.cp_r Pathname.new(File.expand_path("templates/template.env", __dir__)), deploy_file
puts "Created .env file"
puts "Created #{options[:env_path]} file"
end

unless (hooks_dir = Pathname.new(File.expand_path(".mrsk/hooks"))).exist?
Expand All @@ -165,16 +165,25 @@ def init
end

desc "envify", "Create .env by evaluating .env.erb (or .env.staging.erb -> .env.staging when using -d staging)"
option :template, aliases: "-t", type: :string, desc: "Template to use"
def envify
if destination = options[:destination]
env_template_path = ".env.#{destination}.erb"
env_path = ".env.#{destination}"
if (destination = options[:destination])
env_template_path = options[:template] || ".env.#{destination}.erb"
env_path = "#{options[:env_path]}.#{destination}"
else
env_template_path = ".env.erb"
env_path = ".env"
env_template_path = options[:template] || ".env.erb"
env_path = options[:env_path]
end

File.write(env_path, ERB.new(File.read(env_template_path)).result, perm: 0600)
unless File.exist?(env_path) && env_path.include?('/')
FileUtils.mkdir_p(File.dirname(env_path))
end

ENV["MRSK_DESTINATION"] = destination.to_s if destination
output = ERB.new(File.read(env_template_path)).result
output = output.gsub(/\n{3,}/, "\n\n").gsub(/^(?![\r\n])\s+/, '')

File.write(env_path, output, perm: 0600)
end

desc "remove", "Remove Traefik, app, accessories, and registry session from servers"
Expand Down
2 changes: 1 addition & 1 deletion lib/mrsk/commands/healthcheck.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def container_health_log
end

def logs
pipe container_id, xargs(docker(:logs, "--tail", 50, "2>&1"))
pipe container_id, xargs(docker(:logs, "--tail", 200, "2>&1"))
end

def stop
Expand Down
18 changes: 12 additions & 6 deletions lib/mrsk/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,26 +14,32 @@ class Mrsk::Configuration

class << self
def create_from(config_file:, destination: nil, version: nil)
raw_config = load_config_files(config_file, *destination_config_file(config_file, destination))
raw_config = load_config_files(config_file, *destination_config_file(config_file, destination), destination: destination)

new raw_config, destination: destination, version: version
end

private
def load_config_files(*files)
files.inject({}) { |config, file| config.deep_merge! load_config_file(file) }
def load_config_files(*files, destination: nil)
files.inject({}) { |config, file| config.deep_merge! load_config_file(file, destination) }
end

def load_config_file(file)
def load_config_file(file, destination)
if file.exist?
ENV["MRSK_DESTINATION"] = destination.to_s if destination
YAML.load(ERB.new(IO.read(file)).result).symbolize_keys
else
raise "Configuration file not found in #{file}"
end
end

def destination_config_file(base_config_file, destination)
base_config_file.sub_ext(".#{destination}.yml") if destination
return unless destination

return base_config_file.sub(/\.yml$/, ".#{destination}.yml") if base_config_file.extname == ".yml"
return base_config_file.sub(/\.yml.erb$/, ".#{destination}.yml.erb") if base_config_file.extname == ".erb"

raise 'Unsupported config file extension. Please use .yml or .yml.erb'
end
end

Expand Down Expand Up @@ -158,7 +164,7 @@ def ssh_options


def healthcheck
{ "path" => "/up", "port" => 3000, "max_attempts" => 7 }.merge(raw_config.healthcheck || {})
{ "path" => "/up", "port" => 3000, "max_attempts" => 7, "initial_delay" => 0 }.merge(raw_config.healthcheck || {})
end

def readiness_delay
Expand Down
17 changes: 14 additions & 3 deletions lib/mrsk/configuration/role.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,27 @@ def merged_env
# Secrets are stored in an array, which won't merge by default, so have to do it by hand.
def merged_env_with_secrets
merged_env.tap do |new_env|
new_env["secret"] = Array(config.env["secret"]) + Array(specialized_env["secret"])

# If there's no secret/clear split, everything is clear
clear_app_env = config.env["secret"] ? Array(config.env["clear"]) : Array(config.env["clear"] || config.env)
clear_role_env = specialized_env["secret"] ? Array(specialized_env["clear"]) : Array(specialized_env["clear"] || specialized_env)

new_env["clear"] = (clear_app_env + clear_role_env).uniq

secrets_app_env = Array(config.env["secret"])
secrets_role_env = Array(specialized_env["secret"])
new_env["secret"] = (secrets_app_env + secrets_role_env).uniq.filter { |secret| filter_secret_env(secret, new_env) }
end
end

def filter_secret_env(secret, new_env)
# allow clear to override secret
return false if new_env['clear'].include?(secret)

# if we find FOO but FOO? exists, we keep the FOO?
return false if !secret.end_with?('?') && new_env['secret'].include?("#{secret}?")

true
end

def http_health_check(port:, path:)
"curl -f #{URI.join("http://localhost:#{port}", path)} || exit 1" if path.present? || port.present?
end
Expand Down
16 changes: 14 additions & 2 deletions lib/mrsk/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,24 @@ def argumentize(argument, attributes, sensitive: false)
# but redacts and expands secrets.
def argumentize_env_with_secrets(env)
if (secrets = env["secret"]).present?
argumentize("-e", secrets.to_h { |key| [ key, ENV.fetch(key) ] }, sensitive: true) + argumentize("-e", env["clear"])
argumentize("-e", handle_optional_secrets(secrets, env.fetch('clear', {})), sensitive: true) + argumentize("-e", env["clear"])
else
argumentize "-e", env.fetch("clear", env)
argumentize("-e", env.fetch("clear", env))
end
end

def handle_optional_secrets(secrets, clear_env)
secrets.to_h do |key|
if key.end_with? '?'
[ key.chop, ENV[key.chop] ]
elsif (index = clear_env.find_index { |pair| pair.first == key })
[ key, clear_env[index] ]
else
[ key, ENV.fetch(key) ]
end
end.compact
end

# Returns a list of shell-dashed option arguments. If the value is true, it's treated like a value-less option.
def optionize(args, with: nil)
options = if with
Expand Down
6 changes: 6 additions & 0 deletions lib/mrsk/utils/healthcheck_poller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ class << self
def wait_for_healthy(pause_after_ready: false, &block)
attempt = 1
max_attempts = MRSK.config.healthcheck["max_attempts"]
initial_delay = MRSK.config.healthcheck["initial_delay"]

if initial_delay > 0
info "Waiting #{initial_delay}s before checking container health..."
sleep initial_delay
end

begin
case status = block.call
Expand Down
Loading