Merge branch 'main' into global-logging-config
This commit is contained in:
@@ -526,6 +526,9 @@ accessories:
|
|||||||
- MYSQL_ROOT_PASSWORD
|
- MYSQL_ROOT_PASSWORD
|
||||||
volumes:
|
volumes:
|
||||||
- /var/lib/mysql:/var/lib/mysql
|
- /var/lib/mysql:/var/lib/mysql
|
||||||
|
options:
|
||||||
|
cpus: 4
|
||||||
|
memory: "2GB"
|
||||||
redis:
|
redis:
|
||||||
image: redis:latest
|
image: redis:latest
|
||||||
host: 1.1.1.4
|
host: 1.1.1.4
|
||||||
|
|||||||
@@ -7,24 +7,26 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
|
|||||||
|
|
||||||
cli = self
|
cli = self
|
||||||
|
|
||||||
MRSK.config.roles.each do |role|
|
on(MRSK.hosts) do |host|
|
||||||
on(role.hosts) do |host|
|
roles = MRSK.roles_on(host)
|
||||||
execute *MRSK.auditor.record("Booted app version #{version}"), verbosity: :debug
|
|
||||||
|
roles.each do |role|
|
||||||
|
execute *MRSK.auditor(role: role).record("Booted app version #{version}"), verbosity: :debug
|
||||||
|
|
||||||
begin
|
begin
|
||||||
old_version = capture_with_info(*MRSK.app.current_running_version).strip
|
old_version = capture_with_info(*MRSK.app(role: role).current_running_version).strip
|
||||||
execute *MRSK.app.run(role: role.name)
|
execute *MRSK.app(role: role).run
|
||||||
sleep MRSK.config.readiness_delay
|
sleep MRSK.config.readiness_delay
|
||||||
execute *MRSK.app.stop(version: old_version), raise_on_non_zero_exit: false if old_version.present?
|
execute *MRSK.app(role: role).stop(version: old_version), raise_on_non_zero_exit: false if old_version.present?
|
||||||
|
|
||||||
rescue SSHKit::Command::Failed => e
|
rescue SSHKit::Command::Failed => e
|
||||||
if e.message =~ /already in use/
|
if e.message =~ /already in use/
|
||||||
error "Rebooting container with same version #{version} already deployed on #{host} (may cause gap in zero-downtime promise!)"
|
error "Rebooting container with same version #{version} already deployed on #{host} (may cause gap in zero-downtime promise!)"
|
||||||
execute *MRSK.auditor.record("Rebooted app version #{version}"), verbosity: :debug
|
execute *MRSK.auditor(role: role).record("Rebooted app version #{version}"), verbosity: :debug
|
||||||
|
|
||||||
execute *MRSK.app.stop(version: version)
|
execute *MRSK.app(role: role).stop(version: version)
|
||||||
execute *MRSK.app.remove_container(version: version)
|
execute *MRSK.app(role: role).remove_container(version: version)
|
||||||
execute *MRSK.app.run(role: role.name)
|
execute *MRSK.app(role: role).run
|
||||||
else
|
else
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
@@ -36,24 +38,38 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
|
|||||||
|
|
||||||
desc "start", "Start existing app container on servers"
|
desc "start", "Start existing app container on servers"
|
||||||
def start
|
def start
|
||||||
on(MRSK.hosts) do
|
on(MRSK.hosts) do |host|
|
||||||
execute *MRSK.auditor.record("Started app version #{MRSK.config.version}"), verbosity: :debug
|
roles = MRSK.roles_on(host)
|
||||||
execute *MRSK.app.start, raise_on_non_zero_exit: false
|
|
||||||
|
roles.each do |role|
|
||||||
|
execute *MRSK.auditor.record("Started app version #{MRSK.config.version}"), verbosity: :debug
|
||||||
|
execute *MRSK.app(role: role).start, raise_on_non_zero_exit: false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "stop", "Stop app container on servers"
|
desc "stop", "Stop app container on servers"
|
||||||
def stop
|
def stop
|
||||||
on(MRSK.hosts) do
|
on(MRSK.hosts) do |host|
|
||||||
execute *MRSK.auditor.record("Stopped app"), verbosity: :debug
|
roles = MRSK.roles_on(host)
|
||||||
execute *MRSK.app.stop, raise_on_non_zero_exit: false
|
|
||||||
|
roles.each do |role|
|
||||||
|
execute *MRSK.auditor(role: role).record("Stopped app"), verbosity: :debug
|
||||||
|
execute *MRSK.app(role: role).stop, raise_on_non_zero_exit: false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# FIXME: Drop in favor of just containers?
|
# FIXME: Drop in favor of just containers?
|
||||||
desc "details", "Show details about app containers"
|
desc "details", "Show details about app containers"
|
||||||
def details
|
def details
|
||||||
on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.info) }
|
on(MRSK.hosts) do |host|
|
||||||
|
roles = MRSK.roles_on(host)
|
||||||
|
|
||||||
|
roles.each do |role|
|
||||||
|
puts_by_host host, capture_with_info(*MRSK.app(role: role).info)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "exec [CMD]", "Execute a custom command on servers (use --help to show options)"
|
desc "exec [CMD]", "Execute a custom command on servers (use --help to show options)"
|
||||||
@@ -65,7 +81,7 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
|
|||||||
say "Get current version of running container...", :magenta unless options[:version]
|
say "Get current version of running container...", :magenta unless options[:version]
|
||||||
using_version(options[:version] || current_running_version) do |version|
|
using_version(options[:version] || current_running_version) do |version|
|
||||||
say "Launching interactive command with version #{version} via SSH from existing container on #{MRSK.primary_host}...", :magenta
|
say "Launching interactive command with version #{version} via SSH from existing container on #{MRSK.primary_host}...", :magenta
|
||||||
run_locally { exec MRSK.app.execute_in_existing_container_over_ssh(cmd, host: MRSK.primary_host) }
|
run_locally { exec MRSK.app(role: "web").execute_in_existing_container_over_ssh(cmd, host: MRSK.primary_host) }
|
||||||
end
|
end
|
||||||
|
|
||||||
when options[:interactive]
|
when options[:interactive]
|
||||||
@@ -81,8 +97,12 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
|
|||||||
say "Launching command with version #{version} from existing container...", :magenta
|
say "Launching command with version #{version} from existing container...", :magenta
|
||||||
|
|
||||||
on(MRSK.hosts) do |host|
|
on(MRSK.hosts) do |host|
|
||||||
execute *MRSK.auditor.record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug
|
roles = MRSK.roles_on(host)
|
||||||
puts_by_host host, capture_with_info(*MRSK.app.execute_in_existing_container(cmd))
|
|
||||||
|
roles.each do |role|
|
||||||
|
execute *MRSK.auditor(role: role).record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug
|
||||||
|
puts_by_host host, capture_with_info(*MRSK.app(role: role).execute_in_existing_container(cmd))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -147,17 +167,25 @@ class Mrsk::Cli::App < Mrsk::Cli::Base
|
|||||||
|
|
||||||
desc "remove_container [VERSION]", "Remove app container with given version from servers", hide: true
|
desc "remove_container [VERSION]", "Remove app container with given version from servers", hide: true
|
||||||
def remove_container(version)
|
def remove_container(version)
|
||||||
on(MRSK.hosts) do
|
on(MRSK.hosts) do |host|
|
||||||
execute *MRSK.auditor.record("Removed app container with version #{version}"), verbosity: :debug
|
roles = MRSK.roles_on(host)
|
||||||
execute *MRSK.app.remove_container(version: version)
|
|
||||||
|
roles.each do |role|
|
||||||
|
execute *MRSK.auditor(role: role).record("Removed app container with version #{version}"), verbosity: :debug
|
||||||
|
execute *MRSK.app(role: role).remove_container(version: version)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "remove_containers", "Remove all app containers from servers", hide: true
|
desc "remove_containers", "Remove all app containers from servers", hide: true
|
||||||
def remove_containers
|
def remove_containers
|
||||||
on(MRSK.hosts) do
|
on(MRSK.hosts) do |host|
|
||||||
execute *MRSK.auditor.record("Removed all app containers"), verbosity: :debug
|
roles = MRSK.roles_on(host)
|
||||||
execute *MRSK.app.remove_containers
|
|
||||||
|
roles.each do |role|
|
||||||
|
execute *MRSK.auditor(role: role).record("Removed all app containers"), verbosity: :debug
|
||||||
|
execute *MRSK.app(role: role).remove_containers
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ class Mrsk::Commander
|
|||||||
self.verbosity = :info
|
self.verbosity = :info
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def config
|
def config
|
||||||
@config ||= Mrsk::Configuration.create_from(**@config_kwargs).tap do |config|
|
@config ||= Mrsk::Configuration.create_from(**@config_kwargs).tap do |config|
|
||||||
@config_kwargs = nil
|
@config_kwargs = nil
|
||||||
@@ -20,23 +19,38 @@ class Mrsk::Commander
|
|||||||
@config, @config_kwargs = nil, kwargs
|
@config, @config_kwargs = nil, kwargs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attr_reader :specific_roles, :specific_hosts
|
||||||
attr_accessor :specific_hosts
|
|
||||||
|
|
||||||
def specific_primary!
|
def specific_primary!
|
||||||
self.specific_hosts = [ config.primary_web_host ]
|
self.specific_hosts = [ config.primary_web_host ]
|
||||||
end
|
end
|
||||||
|
|
||||||
def specific_roles=(role_names)
|
def specific_roles=(role_names)
|
||||||
self.specific_hosts = config.roles.select { |r| role_names.include?(r.name) }.flat_map(&:hosts) if role_names.present?
|
@specific_roles = config.roles.select { |r| role_names.include?(r.name) } if role_names.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def specific_hosts=(hosts)
|
||||||
|
@specific_hosts = config.all_hosts & hosts if hosts.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def primary_host
|
def primary_host
|
||||||
specific_hosts&.first || config.primary_web_host
|
specific_hosts&.first || config.primary_web_host
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def roles
|
||||||
|
(specific_roles || config.roles).select do |role|
|
||||||
|
((specific_hosts || config.all_hosts) & role.hosts).any?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def hosts
|
def hosts
|
||||||
specific_hosts || config.all_hosts
|
(specific_hosts || config.all_hosts).select do |host|
|
||||||
|
(specific_roles || config.roles).flat_map(&:hosts).include?(host)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def roles_on(host)
|
||||||
|
roles.select { |role| role.hosts.include?(host.to_s) }.map(&:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def traefik_hosts
|
def traefik_hosts
|
||||||
@@ -52,16 +66,16 @@ class Mrsk::Commander
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def app
|
def app(role: nil)
|
||||||
@app ||= Mrsk::Commands::App.new(config)
|
Mrsk::Commands::App.new(config, role: role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def accessory(name)
|
def accessory(name)
|
||||||
Mrsk::Commands::Accessory.new(config, name: name)
|
Mrsk::Commands::Accessory.new(config, name: name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def auditor
|
def auditor(role: nil)
|
||||||
@auditor ||= Mrsk::Commands::Auditor.new(config)
|
Mrsk::Commands::Auditor.new(config, role: role)
|
||||||
end
|
end
|
||||||
|
|
||||||
def builder
|
def builder
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class Mrsk::Commands::Accessory < Mrsk::Commands::Base
|
class Mrsk::Commands::Accessory < Mrsk::Commands::Base
|
||||||
attr_reader :accessory_config
|
attr_reader :accessory_config
|
||||||
delegate :service_name, :image, :host, :port, :files, :directories, :publish_args, :env_args, :volume_args, :label_args, to: :accessory_config
|
delegate :service_name, :image, :host, :port, :files, :directories, :publish_args, :env_args, :volume_args,
|
||||||
|
:label_args, :option_args, to: :accessory_config
|
||||||
|
|
||||||
def initialize(config, name:)
|
def initialize(config, name:)
|
||||||
super(config)
|
super(config)
|
||||||
@@ -17,6 +18,7 @@ class Mrsk::Commands::Accessory < Mrsk::Commands::Base
|
|||||||
*env_args,
|
*env_args,
|
||||||
*volume_args,
|
*volume_args,
|
||||||
*label_args,
|
*label_args,
|
||||||
|
*option_args,
|
||||||
image
|
image
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
class Mrsk::Commands::App < Mrsk::Commands::Base
|
class Mrsk::Commands::App < Mrsk::Commands::Base
|
||||||
def run(role: :web)
|
attr_reader :role
|
||||||
role = config.role(role)
|
|
||||||
|
def initialize(config, role: nil)
|
||||||
|
super(config)
|
||||||
|
@role = role
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
role = config.role(self.role)
|
||||||
|
|
||||||
docker :run,
|
docker :run,
|
||||||
"--detach",
|
"--detach",
|
||||||
"--restart unless-stopped",
|
"--restart unless-stopped",
|
||||||
"--name", service_with_version_and_destination,
|
"--name", container_name,
|
||||||
"-e", "MRSK_CONTAINER_NAME=\"#{service_with_version_and_destination}\"",
|
"-e", "MRSK_CONTAINER_NAME=\"#{container_name}\"",
|
||||||
*role.env_args,
|
*role.env_args,
|
||||||
*config.logging_args,
|
*config.logging_args,
|
||||||
*config.volume_args,
|
*config.volume_args,
|
||||||
@@ -17,7 +24,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
docker :start, service_with_version_and_destination
|
docker :start, container_name
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop(version: nil)
|
def stop(version: nil)
|
||||||
@@ -52,7 +59,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
|
|||||||
def execute_in_existing_container(*command, interactive: false)
|
def execute_in_existing_container(*command, interactive: false)
|
||||||
docker :exec,
|
docker :exec,
|
||||||
("-it" if interactive),
|
("-it" if interactive),
|
||||||
service_with_version_and_destination,
|
container_name,
|
||||||
*command
|
*command
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -97,7 +104,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
|
|||||||
|
|
||||||
def remove_container(version:)
|
def remove_container(version:)
|
||||||
pipe \
|
pipe \
|
||||||
container_id_for(container_name: service_with_version_and_destination(version)),
|
container_id_for(container_name: container_name(version)),
|
||||||
xargs(docker(:container, :rm))
|
xargs(docker(:container, :rm))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -115,12 +122,12 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
|
|||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
def service_with_version_and_destination(version = nil)
|
def container_name(version = nil)
|
||||||
[ config.service, config.destination, version || config.version ].compact.join("-")
|
[ config.service, role, config.destination, version || config.version ].compact.join("-")
|
||||||
end
|
end
|
||||||
|
|
||||||
def container_id_for_version(version)
|
def container_id_for_version(version)
|
||||||
container_id_for(container_name: service_with_version_and_destination(version))
|
container_id_for(container_name: container_name(version))
|
||||||
end
|
end
|
||||||
|
|
||||||
def filter_args
|
def filter_args
|
||||||
@@ -130,6 +137,7 @@ class Mrsk::Commands::App < Mrsk::Commands::Base
|
|||||||
def filters
|
def filters
|
||||||
[ "label=service=#{config.service}" ].tap do |filters|
|
[ "label=service=#{config.service}" ].tap do |filters|
|
||||||
filters << "label=destination=#{config.destination}" if config.destination
|
filters << "label=destination=#{config.destination}" if config.destination
|
||||||
|
filters << "label=role=#{role}" if role
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
require "active_support/core_ext/time/conversions"
|
require "active_support/core_ext/time/conversions"
|
||||||
|
|
||||||
class Mrsk::Commands::Auditor < Mrsk::Commands::Base
|
class Mrsk::Commands::Auditor < Mrsk::Commands::Base
|
||||||
|
attr_reader :role
|
||||||
|
|
||||||
|
def initialize(config, role: nil)
|
||||||
|
super(config)
|
||||||
|
@role = role
|
||||||
|
end
|
||||||
|
|
||||||
# Runs remotely
|
# Runs remotely
|
||||||
def record(line)
|
def record(line)
|
||||||
append \
|
append \
|
||||||
@@ -25,18 +32,26 @@ class Mrsk::Commands::Auditor < Mrsk::Commands::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def tagged_record_line(line)
|
def tagged_record_line(line)
|
||||||
"'#{recorded_at_tag} #{performer_tag} #{line}'"
|
tagged_line recorded_at_tag, performer_tag, role_tag, line
|
||||||
end
|
end
|
||||||
|
|
||||||
def tagged_broadcast_line(line)
|
def tagged_broadcast_line(line)
|
||||||
"'#{performer_tag} #{line}'"
|
tagged_line performer_tag, role_tag, line
|
||||||
|
end
|
||||||
|
|
||||||
|
def tagged_line(*tags_and_line)
|
||||||
|
"'#{tags_and_line.compact.join(" ")}'"
|
||||||
|
end
|
||||||
|
|
||||||
|
def recorded_at_tag
|
||||||
|
"[#{Time.now.to_fs(:db)}]"
|
||||||
end
|
end
|
||||||
|
|
||||||
def performer_tag
|
def performer_tag
|
||||||
"[#{`whoami`.strip}]"
|
"[#{`whoami`.strip}]"
|
||||||
end
|
end
|
||||||
|
|
||||||
def recorded_at_tag
|
def role_tag
|
||||||
"[#{Time.now.to_fs(:db)}]"
|
"[#{role}]" if role
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class Mrsk::Configuration
|
|||||||
|
|
||||||
|
|
||||||
def all_hosts
|
def all_hosts
|
||||||
roles.flat_map(&:hosts)
|
roles.flat_map(&:hosts).uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
def primary_web_host
|
def primary_web_host
|
||||||
@@ -86,7 +86,7 @@ class Mrsk::Configuration
|
|||||||
end
|
end
|
||||||
|
|
||||||
def traefik_hosts
|
def traefik_hosts
|
||||||
roles.select(&:running_traefik?).flat_map(&:hosts)
|
roles.select(&:running_traefik?).flat_map(&:hosts).uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class Mrsk::Configuration::Accessory
|
class Mrsk::Configuration::Accessory
|
||||||
delegate :argumentize, :argumentize_env_with_secrets, to: Mrsk::Utils
|
delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Mrsk::Utils
|
||||||
|
|
||||||
attr_accessor :name, :specifics
|
attr_accessor :name, :specifics
|
||||||
|
|
||||||
@@ -67,6 +67,14 @@ class Mrsk::Configuration::Accessory
|
|||||||
argumentize "--volume", volumes
|
argumentize "--volume", volumes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def option_args
|
||||||
|
if args = specifics["options"]
|
||||||
|
optionize args
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
attr_accessor :config
|
attr_accessor :config
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,11 @@ require_relative "cli_test_case"
|
|||||||
class CliAppTest < CliTestCase
|
class CliAppTest < CliTestCase
|
||||||
test "boot" do
|
test "boot" do
|
||||||
# Stub current version fetch
|
# Stub current version fetch
|
||||||
SSHKit::Backend::Abstract.any_instance.stubs(:capture)
|
SSHKit::Backend::Abstract.any_instance.stubs(:capture).returns("123") # old version
|
||||||
.returns("999") # new version
|
|
||||||
.then
|
|
||||||
.returns("123") # old version
|
|
||||||
|
|
||||||
run_command("boot").tap do |output|
|
run_command("boot").tap do |output|
|
||||||
assert_match "docker run --detach --restart unless-stopped", output
|
assert_match "docker run --detach --restart unless-stopped", output
|
||||||
assert_match "docker container ls --all --filter name=app-123 --quiet | xargs docker stop", output
|
assert_match "docker container ls --all --filter name=app-web-123 --quiet | xargs docker stop", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -20,16 +17,14 @@ class CliAppTest < CliTestCase
|
|||||||
# Prevent expected failures from outputting to terminal
|
# Prevent expected failures from outputting to terminal
|
||||||
Thread.report_on_exception = false
|
Thread.report_on_exception = false
|
||||||
|
|
||||||
MRSK.app.stubs(:run)
|
Mrsk::Commands::App.any_instance.stubs(:run)
|
||||||
.raises(SSHKit::Command::Failed.new("already in use"))
|
|
||||||
.then
|
|
||||||
.raises(SSHKit::Command::Failed.new("already in use"))
|
.raises(SSHKit::Command::Failed.new("already in use"))
|
||||||
.then
|
.then
|
||||||
.returns([ :docker, :run ])
|
.returns([ :docker, :run ])
|
||||||
|
|
||||||
run_command("boot").tap do |output|
|
run_command("boot").tap do |output|
|
||||||
assert_match "Rebooting container with same version latest already deployed", output # Can't start what's already running
|
assert_match "Rebooting container with same version latest already deployed", output # Can't start what's already running
|
||||||
assert_match "docker container ls --all --filter name=app-latest --quiet | xargs docker container rm", output # Remove old container
|
assert_match "docker container ls --all --filter name=app-web-latest --quiet | xargs docker container rm", output # Remove old container
|
||||||
assert_match "docker run", output # Start new container
|
assert_match "docker run", output # Start new container
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
@@ -38,32 +33,58 @@ class CliAppTest < CliTestCase
|
|||||||
|
|
||||||
test "start" do
|
test "start" do
|
||||||
run_command("start").tap do |output|
|
run_command("start").tap do |output|
|
||||||
assert_match "docker start app-999", output
|
assert_match "docker start app-web-999", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "stop" do
|
test "stop" do
|
||||||
run_command("stop").tap do |output|
|
run_command("stop").tap do |output|
|
||||||
assert_match "docker ps --quiet --filter label=service=app | xargs docker stop", output
|
assert_match "docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker stop", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "details" do
|
test "details" do
|
||||||
run_command("details").tap do |output|
|
run_command("details").tap do |output|
|
||||||
assert_match "docker ps --filter label=service=app", output
|
assert_match "docker ps --filter label=service=app --filter label=role=web", output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "remove" do
|
||||||
|
run_command("remove").tap do |output|
|
||||||
|
assert_match /#{Regexp.escape("docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker stop")}/, output
|
||||||
|
assert_match /#{Regexp.escape("docker container prune --force --filter label=service=app")}/, output
|
||||||
|
assert_match /#{Regexp.escape("docker image prune --all --force --filter label=service=app")}/, output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "remove_container" do
|
||||||
|
run_command("remove_container", "1234567").tap do |output|
|
||||||
|
assert_match "docker container ls --all --filter name=app-web-1234567 --quiet | xargs docker container rm", output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "remove_containers" do
|
||||||
|
run_command("remove_containers").tap do |output|
|
||||||
|
assert_match "docker container prune --force --filter label=service=app", output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "remove_images" do
|
||||||
|
run_command("remove_images").tap do |output|
|
||||||
|
assert_match "docker image prune --all --force --filter label=service=app", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "exec" do
|
test "exec" do
|
||||||
run_command("exec", "ruby -v").tap do |output|
|
run_command("exec", "ruby -v").tap do |output|
|
||||||
assert_match "ruby -v", output
|
assert_match "docker run --rm dhh/app:latest ruby -v", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "exec with reuse" do
|
test "exec with reuse" do
|
||||||
run_command("exec", "--reuse", "ruby -v").tap do |output|
|
run_command("exec", "--reuse", "ruby -v").tap do |output|
|
||||||
assert_match "docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1", output # Get current version
|
assert_match "docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1", output # Get current version
|
||||||
assert_match "docker exec app-999 ruby -v", output
|
assert_match "docker exec app-web-999 ruby -v", output
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -93,32 +114,6 @@ class CliAppTest < CliTestCase
|
|||||||
assert_match "docker ps --quiet --filter label=service=app | xargs docker logs --timestamps --tail 10 --follow 2>&1", run_command("logs", "--follow")
|
assert_match "docker ps --quiet --filter label=service=app | xargs docker logs --timestamps --tail 10 --follow 2>&1", run_command("logs", "--follow")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "remove" do
|
|
||||||
Mrsk::Cli::App.any_instance.expects(:stop)
|
|
||||||
Mrsk::Cli::App.any_instance.expects(:remove_containers)
|
|
||||||
Mrsk::Cli::App.any_instance.expects(:remove_images)
|
|
||||||
|
|
||||||
run_command("remove")
|
|
||||||
end
|
|
||||||
|
|
||||||
test "remove_container" do
|
|
||||||
run_command("remove_container", "1234567").tap do |output|
|
|
||||||
assert_match "docker container ls --all --filter name=app-1234567 --quiet | xargs docker container rm", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "remove_containers" do
|
|
||||||
run_command("remove_containers").tap do |output|
|
|
||||||
assert_match "docker container prune --force --filter label=service=app", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "remove_images" do
|
|
||||||
run_command("remove_images").tap do |output|
|
|
||||||
assert_match "docker image prune --all --force --filter label=service=app", output
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
test "version" do
|
test "version" do
|
||||||
run_command("version").tap do |output|
|
run_command("version").tap do |output|
|
||||||
assert_match "docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1", output
|
assert_match "docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1", output
|
||||||
@@ -127,6 +122,6 @@ class CliAppTest < CliTestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def run_command(*command)
|
def run_command(*command)
|
||||||
stdouted { Mrsk::Cli::App.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) }
|
stdouted { Mrsk::Cli::App.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml", "--hosts", "1.1.1.1"]) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ class CliMainTest < CliTestCase
|
|||||||
|
|
||||||
test "rollback good version" do
|
test "rollback good version" do
|
||||||
Mrsk::Cli::Main.any_instance.stubs(:container_name_available?).returns(true)
|
Mrsk::Cli::Main.any_instance.stubs(:container_name_available?).returns(true)
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info).with(:docker, :ps, "--filter", "label=service=app", "--format", "\"{{.Names}}\"", "|", "sed 's/-/\\n/g'", "|", "tail -n 1").returns("version-to-rollback\n").times(2)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info).with(:docker, :ps, "--filter", "label=service=app", "--format", "\"{{.Names}}\"", "|", "sed 's/-/\\n/g'", "|", "tail -n 1").returns("version-to-rollback\n").at_least_once
|
||||||
|
|
||||||
run_command("rollback", "123").tap do |output|
|
run_command("rollback", "123").tap do |output|
|
||||||
assert_match "Start version 123", output
|
assert_match "Start version 123", output
|
||||||
@@ -99,7 +99,7 @@ class CliMainTest < CliTestCase
|
|||||||
|
|
||||||
test "rollback without old version" do
|
test "rollback without old version" do
|
||||||
Mrsk::Cli::Main.any_instance.stubs(:container_name_available?).returns(true)
|
Mrsk::Cli::Main.any_instance.stubs(:container_name_available?).returns(true)
|
||||||
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info).with(:docker, :ps, "--filter", "label=service=app", "--format", "\"{{.Names}}\"", "|", "sed 's/-/\\n/g'", "|", "tail -n 1").returns("").times(2)
|
SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info).with(:docker, :ps, "--filter", "label=service=app", "--format", "\"{{.Names}}\"", "|", "sed 's/-/\\n/g'", "|", "tail -n 1").returns("").at_least_once
|
||||||
|
|
||||||
run_command("rollback", "123").tap do |output|
|
run_command("rollback", "123").tap do |output|
|
||||||
assert_match "Start version 123", output
|
assert_match "Start version 123", output
|
||||||
@@ -120,8 +120,6 @@ class CliMainTest < CliTestCase
|
|||||||
run_command("audit").tap do |output|
|
run_command("audit").tap do |output|
|
||||||
assert_match /tail -n 50 mrsk-app-audit.log on 1.1.1.1/, output
|
assert_match /tail -n 50 mrsk-app-audit.log on 1.1.1.1/, output
|
||||||
assert_match /App Host: 1.1.1.1/, output
|
assert_match /App Host: 1.1.1.1/, output
|
||||||
assert_match /tail -n 50 mrsk-app-audit.log on 1.1.1.2/, output
|
|
||||||
assert_match /App Host: 1.1.1.2/, output
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,13 @@ class CliPruneTest < CliTestCase
|
|||||||
|
|
||||||
test "images" do
|
test "images" do
|
||||||
run_command("images").tap do |output|
|
run_command("images").tap do |output|
|
||||||
assert_match "docker image prune --all --force --filter label=service=app --filter until=168h on 1.1.1.1", output
|
assert_match /docker image prune --all --force --filter label=service=app --filter until=168h on 1.1.1.\d/, output
|
||||||
assert_match "docker image prune --all --force --filter label=service=app --filter until=168h on 1.1.1.2", output
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "containers" do
|
test "containers" do
|
||||||
run_command("containers").tap do |output|
|
run_command("containers").tap do |output|
|
||||||
assert_match "docker container prune --force --filter label=service=app --filter until=72h on 1.1.1.1", output
|
assert_match /docker container prune --force --filter label=service=app --filter until=72h on 1.1.1.\d/, output
|
||||||
assert_match "docker container prune --force --filter label=service=app --filter until=72h on 1.1.1.2", output
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,13 @@ class CliRegistryTest < CliTestCase
|
|||||||
test "login" do
|
test "login" do
|
||||||
run_command("login").tap do |output|
|
run_command("login").tap do |output|
|
||||||
assert_match /docker login -u \[REDACTED\] -p \[REDACTED\] as .*@localhost/, output
|
assert_match /docker login -u \[REDACTED\] -p \[REDACTED\] as .*@localhost/, output
|
||||||
assert_match "docker login -u [REDACTED] -p [REDACTED] on 1.1.1.1", output
|
assert_match /docker login -u \[REDACTED\] -p \[REDACTED\] on 1.1.1.\d/, output
|
||||||
assert_match "docker login -u [REDACTED] -p [REDACTED] on 1.1.1.2", output
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "logout" do
|
test "logout" do
|
||||||
run_command("logout").tap do |output|
|
run_command("logout").tap do |output|
|
||||||
assert_match "docker logout on 1.1.1.1", output
|
assert_match /docker logout on 1.1.1.\d/, output
|
||||||
assert_match "docker logout on 1.1.1.2", output
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -14,18 +14,29 @@ class CommanderTest < ActiveSupport::TestCase
|
|||||||
test "overwriting hosts" do
|
test "overwriting hosts" do
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
|
||||||
|
|
||||||
@mrsk.specific_hosts = [ "1.2.3.4", "1.2.3.5" ]
|
@mrsk.specific_hosts = [ "1.1.1.1", "1.1.1.2" ]
|
||||||
assert_equal [ "1.2.3.4", "1.2.3.5" ], @mrsk.hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2" ], @mrsk.hosts
|
||||||
end
|
end
|
||||||
|
|
||||||
test "overwriting hosts with roles" do
|
test "filtering hosts by filtering roles" do
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
|
||||||
|
|
||||||
@mrsk.specific_roles = [ "workers", "web" ]
|
@mrsk.specific_roles = [ "web" ]
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2" ], @mrsk.hosts
|
||||||
|
end
|
||||||
|
|
||||||
|
test "filtering roles" do
|
||||||
|
assert_equal [ "web", "workers" ], @mrsk.roles.map(&:name)
|
||||||
|
|
||||||
@mrsk.specific_roles = [ "workers" ]
|
@mrsk.specific_roles = [ "workers" ]
|
||||||
assert_equal [ "1.1.1.3", "1.1.1.4" ], @mrsk.hosts
|
assert_equal [ "workers" ], @mrsk.roles.map(&:name)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "filtering roles by filtering hosts" do
|
||||||
|
assert_equal [ "web", "workers" ], @mrsk.roles.map(&:name)
|
||||||
|
|
||||||
|
@mrsk.specific_hosts = [ "1.1.1.3" ]
|
||||||
|
assert_equal [ "workers" ], @mrsk.roles.map(&:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "overwriting hosts with primary" do
|
test "overwriting hosts with primary" do
|
||||||
@@ -39,4 +50,9 @@ class CommanderTest < ActiveSupport::TestCase
|
|||||||
@mrsk.specific_roles = "web"
|
@mrsk.specific_roles = "web"
|
||||||
assert_equal "1.1.1.1", @mrsk.primary_host
|
assert_equal "1.1.1.1", @mrsk.primary_host
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "roles_on" do
|
||||||
|
assert_equal [ "web" ], @mrsk.roles_on("1.1.1.1")
|
||||||
|
assert_equal [ "workers" ], @mrsk.roles_on("1.1.1.3")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "run" do
|
test "run" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker run --detach --restart unless-stopped --name app-999 -e MRSK_CONTAINER_NAME=\"app-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.routers.app.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.services.app.loadbalancer.healthcheck.path=\"/up\" --label traefik.http.services.app.loadbalancer.healthcheck.interval=\"1s\" --label traefik.http.middlewares.app-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app.middlewares=\"app-retry@docker\" dhh/app:999",
|
"docker run --detach --restart unless-stopped --log-opt max-size=10m --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.routers.app.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.services.app.loadbalancer.healthcheck.path=\"/up\" --label traefik.http.services.app.loadbalancer.healthcheck.interval=\"1s\" --label traefik.http.middlewares.app-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app.middlewares=\"app-retry@docker\" dhh/app:999",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
@config[:volumes] = ["/local/path:/container/path" ]
|
@config[:volumes] = ["/local/path:/container/path" ]
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker run --detach --restart unless-stopped --name app-999 -e MRSK_CONTAINER_NAME=\"app-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --volume /local/path:/container/path --label service=\"app\" --label role=\"web\" --label traefik.http.routers.app.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.services.app.loadbalancer.healthcheck.path=\"/up\" --label traefik.http.services.app.loadbalancer.healthcheck.interval=\"1s\" --label traefik.http.middlewares.app-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app.middlewares=\"app-retry@docker\" dhh/app:999",
|
"docker run --detach --restart unless-stopped --log-opt max-size=10m --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --volume /local/path:/container/path --label service=\"app\" --label role=\"web\" --label traefik.http.routers.app.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.services.app.loadbalancer.healthcheck.path=\"/up\" --label traefik.http.services.app.loadbalancer.healthcheck.interval=\"1s\" --label traefik.http.middlewares.app-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app.middlewares=\"app-retry@docker\" dhh/app:999",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -29,16 +29,15 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
@config[:healthcheck] = { "path" => "/healthz" }
|
@config[:healthcheck] = { "path" => "/healthz" }
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker run --detach --restart unless-stopped --name app-999 -e MRSK_CONTAINER_NAME=\"app-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.routers.app.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.services.app.loadbalancer.healthcheck.path=\"/healthz\" --label traefik.http.services.app.loadbalancer.healthcheck.interval=\"1s\" --label traefik.http.middlewares.app-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app.middlewares=\"app-retry@docker\" dhh/app:999",
|
"docker run --detach --restart unless-stopped --log-opt max-size=10m --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.routers.app.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.services.app.loadbalancer.healthcheck.path=\"/healthz\" --label traefik.http.services.app.loadbalancer.healthcheck.interval=\"1s\" --label traefik.http.middlewares.app-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app.middlewares=\"app-retry@docker\" dhh/app:999",
|
||||||
new_command.run.join(" ")
|
new_command.run.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "run with custom options" do
|
test "run with custom options" do
|
||||||
@config[:servers] = { "web" => [ "1.1.1.1" ], "jobs" => { "hosts" => [ "1.1.1.2" ], "cmd" => "bin/jobs", "options" => { "mount" => "somewhere", "cap-add" => true } } }
|
@config[:servers] = { "web" => [ "1.1.1.1" ], "jobs" => { "hosts" => [ "1.1.1.2" ], "cmd" => "bin/jobs", "options" => { "mount" => "somewhere", "cap-add" => true } } }
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker run --detach --restart unless-stopped --name app-999 -e MRSK_CONTAINER_NAME=\"app-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"jobs\" --mount \"somewhere\" --cap-add dhh/app:999 bin/jobs",
|
"docker run --detach --restart unless-stopped --log-opt max-size=10m --name app-jobs-999 -e MRSK_CONTAINER_NAME=\"app-jobs-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"jobs\" --mount \"somewhere\" --cap-add dhh/app:999 bin/jobs",
|
||||||
new_command.run(role: :jobs).join(" ")
|
new_command(role: "jobs").run.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "run with logging config" do
|
test "run with logging config" do
|
||||||
@@ -51,76 +50,76 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "start" do
|
test "start" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker start app-999",
|
"docker start app-web-999",
|
||||||
new_command.start.join(" ")
|
new_command.start.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "start with destination" do
|
test "start with destination" do
|
||||||
@destination = "staging"
|
@destination = "staging"
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker start app-staging-999",
|
"docker start app-web-staging-999",
|
||||||
new_command.start.join(" ")
|
new_command.start.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "stop" do
|
test "stop" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker stop",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker stop",
|
||||||
new_command.stop.join(" ")
|
new_command.stop.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "stop with version" do
|
test "stop with version" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container ls --all --filter name=app-123 --quiet | xargs docker stop",
|
"docker container ls --all --filter name=app-web-123 --quiet | xargs docker stop",
|
||||||
new_command.stop(version: "123").join(" ")
|
new_command.stop(version: "123").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "info" do
|
test "info" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --filter label=service=app",
|
"docker ps --filter label=service=app --filter label=role=web",
|
||||||
new_command.info.join(" ")
|
new_command.info.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "info with destination" do
|
test "info with destination" do
|
||||||
@destination = "staging"
|
@destination = "staging"
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --filter label=service=app --filter label=destination=staging",
|
"docker ps --filter label=service=app --filter label=destination=staging --filter label=role=web",
|
||||||
new_command.info.join(" ")
|
new_command.info.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
test "logs" do
|
test "logs" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs 2>&1",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs 2>&1",
|
||||||
new_command.logs.join(" ")
|
new_command.logs.join(" ")
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs --since 5m 2>&1",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs --since 5m 2>&1",
|
||||||
new_command.logs(since: "5m").join(" ")
|
new_command.logs(since: "5m").join(" ")
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs --tail 100 2>&1",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs --tail 100 2>&1",
|
||||||
new_command.logs(lines: "100").join(" ")
|
new_command.logs(lines: "100").join(" ")
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs --since 5m --tail 100 2>&1",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs --since 5m --tail 100 2>&1",
|
||||||
new_command.logs(since: "5m", lines: "100").join(" ")
|
new_command.logs(since: "5m", lines: "100").join(" ")
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs 2>&1 | grep 'my-id'",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs 2>&1 | grep 'my-id'",
|
||||||
new_command.logs(grep: "my-id").join(" ")
|
new_command.logs(grep: "my-id").join(" ")
|
||||||
|
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs --since 5m 2>&1 | grep 'my-id'",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs --since 5m 2>&1 | grep 'my-id'",
|
||||||
new_command.logs(since: "5m", grep: "my-id").join(" ")
|
new_command.logs(since: "5m", grep: "my-id").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "follow logs" do
|
test "follow logs" do
|
||||||
assert_match \
|
assert_match \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs --timestamps --tail 10 --follow 2>&1",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs --timestamps --tail 10 --follow 2>&1",
|
||||||
new_command.follow_logs(host: "app-1")
|
new_command.follow_logs(host: "app-1")
|
||||||
|
|
||||||
assert_match \
|
assert_match \
|
||||||
"docker ps --quiet --filter label=service=app | xargs docker logs --timestamps --tail 10 --follow 2>&1 | grep \"Completed\"",
|
"docker ps --quiet --filter label=service=app --filter label=role=web | xargs docker logs --timestamps --tail 10 --follow 2>&1 | grep \"Completed\"",
|
||||||
new_command.follow_logs(host: "app-1", grep: "Completed")
|
new_command.follow_logs(host: "app-1", grep: "Completed")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -133,7 +132,7 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "execute in existing container" do
|
test "execute in existing container" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker exec app-999 bin/rails db:setup",
|
"docker exec app-web-999 bin/rails db:setup",
|
||||||
new_command.execute_in_existing_container("bin/rails", "db:setup").join(" ")
|
new_command.execute_in_existing_container("bin/rails", "db:setup").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -143,7 +142,7 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
test "execute in existing container over ssh" do
|
test "execute in existing container over ssh" do
|
||||||
assert_match %r|docker exec -it app-999 bin/rails c|,
|
assert_match %r|docker exec -it app-web-999 bin/rails c|,
|
||||||
new_command.execute_in_existing_container_over_ssh("bin/rails", "c", host: "app-1")
|
new_command.execute_in_existing_container_over_ssh("bin/rails", "c", host: "app-1")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -174,14 +173,14 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "current_container_id" do
|
test "current_container_id" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app",
|
"docker ps --quiet --filter label=service=app --filter label=role=web",
|
||||||
new_command.current_container_id.join(" ")
|
new_command.current_container_id.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "current_container_id with destination" do
|
test "current_container_id with destination" do
|
||||||
@destination = "staging"
|
@destination = "staging"
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --quiet --filter label=service=app --filter label=destination=staging",
|
"docker ps --quiet --filter label=service=app --filter label=destination=staging --filter label=role=web",
|
||||||
new_command.current_container_id.join(" ")
|
new_command.current_container_id.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -193,52 +192,52 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "current_running_version" do
|
test "current_running_version" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker ps --filter label=service=app --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1",
|
"docker ps --filter label=service=app --filter label=role=web --format \"{{.Names}}\" | sed 's/-/\\n/g' | tail -n 1",
|
||||||
new_command.current_running_version.join(" ")
|
new_command.current_running_version.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "list_containers" do
|
test "list_containers" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container ls --all --filter label=service=app",
|
"docker container ls --all --filter label=service=app --filter label=role=web",
|
||||||
new_command.list_containers.join(" ")
|
new_command.list_containers.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "list_containers with destination" do
|
test "list_containers with destination" do
|
||||||
@destination = "staging"
|
@destination = "staging"
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container ls --all --filter label=service=app --filter label=destination=staging",
|
"docker container ls --all --filter label=service=app --filter label=destination=staging --filter label=role=web",
|
||||||
new_command.list_containers.join(" ")
|
new_command.list_containers.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "list_container_names" do
|
test "list_container_names" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container ls --all --filter label=service=app --format '{{ .Names }}'",
|
"docker container ls --all --filter label=service=app --filter label=role=web --format '{{ .Names }}'",
|
||||||
new_command.list_container_names.join(" ")
|
new_command.list_container_names.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "remove_container" do
|
test "remove_container" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container ls --all --filter name=app-999 --quiet | xargs docker container rm",
|
"docker container ls --all --filter name=app-web-999 --quiet | xargs docker container rm",
|
||||||
new_command.remove_container(version: "999").join(" ")
|
new_command.remove_container(version: "999").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "remove_container with destination" do
|
test "remove_container with destination" do
|
||||||
@destination = "staging"
|
@destination = "staging"
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container ls --all --filter name=app-staging-999 --quiet | xargs docker container rm",
|
"docker container ls --all --filter name=app-web-staging-999 --quiet | xargs docker container rm",
|
||||||
new_command.remove_container(version: "999").join(" ")
|
new_command.remove_container(version: "999").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "remove_containers" do
|
test "remove_containers" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container prune --force --filter label=service=app",
|
"docker container prune --force --filter label=service=app --filter label=role=web",
|
||||||
new_command.remove_containers.join(" ")
|
new_command.remove_containers.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "remove_containers with destination" do
|
test "remove_containers with destination" do
|
||||||
@destination = "staging"
|
@destination = "staging"
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker container prune --force --filter label=service=app --filter label=destination=staging",
|
"docker container prune --force --filter label=service=app --filter label=destination=staging --filter label=role=web",
|
||||||
new_command.remove_containers.join(" ")
|
new_command.remove_containers.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -250,19 +249,19 @@ class CommandsAppTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "remove_images" do
|
test "remove_images" do
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker image prune --all --force --filter label=service=app",
|
"docker image prune --all --force --filter label=service=app --filter label=role=web",
|
||||||
new_command.remove_images.join(" ")
|
new_command.remove_images.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
test "remove_images with destination" do
|
test "remove_images with destination" do
|
||||||
@destination = "staging"
|
@destination = "staging"
|
||||||
assert_equal \
|
assert_equal \
|
||||||
"docker image prune --all --force --filter label=service=app --filter label=destination=staging",
|
"docker image prune --all --force --filter label=service=app --filter label=destination=staging --filter label=role=web",
|
||||||
new_command.remove_images.join(" ")
|
new_command.remove_images.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def new_command
|
def new_command(role: "web")
|
||||||
Mrsk::Commands::App.new(Mrsk::Configuration.new(@config, destination: @destination, version: "999"))
|
Mrsk::Commands::App.new(Mrsk::Configuration.new(@config, destination: @destination, version: "999"), role: role)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ class CommandsAuditorTest < ActiveSupport::TestCase
|
|||||||
new_command.record("app removed container").join(" ")
|
new_command.record("app removed container").join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "record with role" do
|
||||||
|
@role = "web"
|
||||||
|
|
||||||
|
assert_match \
|
||||||
|
/echo '.* \[web\] app removed container' >> mrsk-app-audit.log/,
|
||||||
|
new_command.record("app removed container").join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
test "broadcast" do
|
test "broadcast" do
|
||||||
assert_match \
|
assert_match \
|
||||||
/bin\/audit_broadcast '\[.*\] app removed container'/,
|
/bin\/audit_broadcast '\[.*\] app removed container'/,
|
||||||
@@ -30,6 +38,6 @@ class CommandsAuditorTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
private
|
private
|
||||||
def new_command
|
def new_command
|
||||||
Mrsk::Commands::Auditor.new(Mrsk::Configuration.new(@config, destination: @destination, version: "123"))
|
Mrsk::Commands::Auditor.new(Mrsk::Configuration.new(@config, destination: @destination, version: "123"), role: @role)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -39,7 +39,11 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
|
|||||||
},
|
},
|
||||||
"volumes" => [
|
"volumes" => [
|
||||||
"/var/lib/redis:/data"
|
"/var/lib/redis:/data"
|
||||||
]
|
],
|
||||||
|
"options" => {
|
||||||
|
"cpus" => 4,
|
||||||
|
"memory" => "2GB"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,4 +108,8 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase
|
|||||||
test "directories" do
|
test "directories" do
|
||||||
assert_equal({"$PWD/app-mysql/data"=>"/var/lib/mysql"}, @config.accessory(:mysql).directories)
|
assert_equal({"$PWD/app-mysql/data"=>"/var/lib/mysql"}, @config.accessory(:mysql).directories)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "options" do
|
||||||
|
assert_equal ["--cpus", "\"4\"", "--memory", "\"2GB\""], @config.accessory(:redis).option_args
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
@config = Mrsk::Configuration.new(@deploy)
|
@config = Mrsk::Configuration.new(@deploy)
|
||||||
|
|
||||||
@deploy_with_roles = @deploy.dup.merge({
|
@deploy_with_roles = @deploy.dup.merge({
|
||||||
servers: { "web" => [ "1.1.1.1", "1.1.1.2" ], "workers" => { "hosts" => [ "1.1.1.3", "1.1.1.4" ] } } })
|
servers: { "web" => [ "1.1.1.1", "1.1.1.2" ], "workers" => { "hosts" => [ "1.1.1.1", "1.1.1.3" ] } } })
|
||||||
|
|
||||||
@config_with_roles = Mrsk::Configuration.new(@deploy_with_roles)
|
@config_with_roles = Mrsk::Configuration.new(@deploy_with_roles)
|
||||||
end
|
end
|
||||||
@@ -55,7 +55,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
|
|
||||||
test "all hosts" do
|
test "all hosts" do
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2"], @config.all_hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2"], @config.all_hosts
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @config_with_roles.all_hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3" ], @config_with_roles.all_hosts
|
||||||
end
|
end
|
||||||
|
|
||||||
test "primary web host" do
|
test "primary web host" do
|
||||||
@@ -69,7 +69,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
@deploy_with_roles[:servers]["workers"]["traefik"] = true
|
@deploy_with_roles[:servers]["workers"]["traefik"] = true
|
||||||
config = Mrsk::Configuration.new(@deploy_with_roles)
|
config = Mrsk::Configuration.new(@deploy_with_roles)
|
||||||
|
|
||||||
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], config.traefik_hosts
|
assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3" ], config.traefik_hosts
|
||||||
end
|
end
|
||||||
|
|
||||||
test "version" do
|
test "version" do
|
||||||
|
|||||||
2
test/fixtures/deploy_with_accessories.yml
vendored
2
test/fixtures/deploy_with_accessories.yml
vendored
@@ -28,4 +28,4 @@ accessories:
|
|||||||
directories:
|
directories:
|
||||||
- data:/data
|
- data:/data
|
||||||
|
|
||||||
readiness_delay: 0
|
readiness_delay: 0
|
||||||
|
|||||||
Reference in New Issue
Block a user