Compare commits
1 Commits
proxy-0.5.
...
rename-rol
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a5880208a |
@@ -11,12 +11,12 @@ class Kamal::Cli::App::Boot
|
||||
end
|
||||
|
||||
def run
|
||||
old_version = old_version_renamed_if_clashing
|
||||
old_version, old_app = old_version_renamed_if_clashing
|
||||
|
||||
start_new_version
|
||||
|
||||
if old_version
|
||||
stop_old_version(old_version)
|
||||
stop_old_version(old_version, old_app)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,7 +41,13 @@ class Kamal::Cli::App::Boot
|
||||
execute *app.rename_container(version: version, new_version: renamed_version)
|
||||
end
|
||||
|
||||
capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip.presence
|
||||
[ role, *role.previous_roles ].each do |old_role|
|
||||
old_app = KAMAL.app(role: old_role)
|
||||
old_version = capture_with_info(*old_app.current_running_version, raise_on_non_zero_exit: false).strip.presence
|
||||
return [ old_version, old_app ] if old_version
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def start_new_version
|
||||
@@ -51,7 +57,7 @@ class Kamal::Cli::App::Boot
|
||||
Kamal::Cli::Healthcheck::Poller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) }
|
||||
end
|
||||
|
||||
def stop_old_version(version)
|
||||
def stop_old_version(version, app)
|
||||
if uses_cord?
|
||||
cord = capture_with_info(*app.cord(version: version), raise_on_non_zero_exit: false).strip
|
||||
if cord.present?
|
||||
|
||||
@@ -3,7 +3,7 @@ class Kamal::Commands::App < Kamal::Commands::Base
|
||||
|
||||
ACTIVE_DOCKER_STATUSES = [ :running, :restarting ]
|
||||
|
||||
attr_reader :role, :role
|
||||
attr_reader :role
|
||||
|
||||
def initialize(config, role: nil)
|
||||
super(config)
|
||||
|
||||
@@ -71,7 +71,9 @@ class Kamal::Configuration
|
||||
|
||||
|
||||
def roles
|
||||
@roles ||= role_names.collect { |role_name| Role.new(role_name, config: self) }
|
||||
@roles ||= role_names.collect do |role_name|
|
||||
Role.new(role_name, config: self, specializations: role_specializations(role_name), primary: role_name == primary_role_name)
|
||||
end
|
||||
end
|
||||
|
||||
def role(name)
|
||||
@@ -325,6 +327,14 @@ class Kamal::Configuration
|
||||
raw_config.servers.is_a?(Array) ? [ "web" ] : raw_config.servers.keys.sort
|
||||
end
|
||||
|
||||
def role_specializations(name)
|
||||
if servers.is_a?(Array) || servers[name].is_a?(Array)
|
||||
{}
|
||||
else
|
||||
servers[name].except("hosts")
|
||||
end
|
||||
end
|
||||
|
||||
def git_version
|
||||
@git_version ||=
|
||||
if Kamal::Git.used?
|
||||
|
||||
@@ -2,11 +2,11 @@ class Kamal::Configuration::Role
|
||||
CORD_FILE = "cord"
|
||||
delegate :argumentize, :optionize, to: Kamal::Utils
|
||||
|
||||
attr_accessor :name
|
||||
attr_reader :name
|
||||
alias to_s name
|
||||
|
||||
def initialize(name, config:)
|
||||
@name, @config = name.inquiry, config
|
||||
def initialize(name, config:, specializations:, primary:)
|
||||
@name, @config, @specializations, @primary = name.inquiry, config, specializations, primary
|
||||
end
|
||||
|
||||
def primary_host
|
||||
@@ -98,7 +98,7 @@ class Kamal::Configuration::Role
|
||||
end
|
||||
|
||||
def primary?
|
||||
self == @config.primary_role
|
||||
@primary
|
||||
end
|
||||
|
||||
|
||||
@@ -163,8 +163,14 @@ class Kamal::Configuration::Role
|
||||
File.join config.run_directory, "assets", "volumes", container_name(version)
|
||||
end
|
||||
|
||||
def previous_roles
|
||||
previous_role_names.map do |role_name|
|
||||
Kamal::Configuration::Role.new(role_name, config: config, specializations: specializations, primary: primary?)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
attr_accessor :config
|
||||
attr_reader :config, :specializations
|
||||
|
||||
def extract_hosts_from_config
|
||||
if config.servers.is_a?(Array)
|
||||
@@ -207,14 +213,6 @@ class Kamal::Configuration::Role
|
||||
end
|
||||
end
|
||||
|
||||
def specializations
|
||||
if config.servers.is_a?(Array) || config.servers[name].is_a?(Array)
|
||||
{}
|
||||
else
|
||||
config.servers[name].except("hosts")
|
||||
end
|
||||
end
|
||||
|
||||
def specialized_env
|
||||
Kamal::Configuration::Env.from_config config: specializations.fetch("env", {})
|
||||
end
|
||||
@@ -237,4 +235,8 @@ class Kamal::Configuration::Role
|
||||
options
|
||||
end
|
||||
end
|
||||
|
||||
def previous_role_names
|
||||
specializations.fetch("previously", [])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -53,7 +53,8 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
||||
test "custom labels via role specialization" do
|
||||
@deploy_with_roles[:labels] = { "my.custom.label" => "50" }
|
||||
@deploy_with_roles[:servers]["workers"]["labels"] = { "my.custom.label" => "70" }
|
||||
assert_equal "70", @config_with_roles.role(:workers).labels["my.custom.label"]
|
||||
config_with_roles = Kamal::Configuration.new(@deploy_with_roles)
|
||||
assert_equal "70", config_with_roles.role(:workers).labels["my.custom.label"]
|
||||
end
|
||||
|
||||
test "overwriting default traefik label" do
|
||||
@@ -109,6 +110,8 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
||||
]
|
||||
}
|
||||
|
||||
config_with_roles = Kamal::Configuration.new(@deploy_with_roles)
|
||||
|
||||
ENV["REDIS_PASSWORD"] = "secret456"
|
||||
ENV["DB_PASSWORD"] = "secret&\"123"
|
||||
|
||||
@@ -117,8 +120,8 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
||||
DB_PASSWORD=secret&\"123
|
||||
ENV
|
||||
|
||||
assert_equal expected_secrets_file, @config_with_roles.role(:workers).env.secrets_io.string
|
||||
assert_equal [ "--env-file", ".kamal/env/roles/app-workers.env", "--env", "REDIS_URL=\"redis://a/b\"", "--env", "WEB_CONCURRENCY=\"4\"" ], @config_with_roles.role(:workers).env_args
|
||||
assert_equal expected_secrets_file, config_with_roles.role(:workers).env.secrets_io.string
|
||||
assert_equal [ "--env-file", ".kamal/env/roles/app-workers.env", "--env", "REDIS_URL=\"redis://a/b\"", "--env", "WEB_CONCURRENCY=\"4\"" ], config_with_roles.role(:workers).env_args
|
||||
ensure
|
||||
ENV["REDIS_PASSWORD"] = nil
|
||||
ENV["DB_PASSWORD"] = nil
|
||||
@@ -135,14 +138,16 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
||||
]
|
||||
}
|
||||
|
||||
config_with_roles = Kamal::Configuration.new(@deploy_with_roles)
|
||||
|
||||
ENV["DB_PASSWORD"] = "secret123"
|
||||
|
||||
expected_secrets_file = <<~ENV
|
||||
DB_PASSWORD=secret123
|
||||
ENV
|
||||
|
||||
assert_equal expected_secrets_file, @config_with_roles.role(:workers).env.secrets_io.string
|
||||
assert_equal [ "--env-file", ".kamal/env/roles/app-workers.env", "--env", "REDIS_URL=\"redis://a/b\"", "--env", "WEB_CONCURRENCY=\"4\"" ], @config_with_roles.role(:workers).env_args
|
||||
assert_equal expected_secrets_file, config_with_roles.role(:workers).env.secrets_io.string
|
||||
assert_equal [ "--env-file", ".kamal/env/roles/app-workers.env", "--env", "REDIS_URL=\"redis://a/b\"", "--env", "WEB_CONCURRENCY=\"4\"" ], config_with_roles.role(:workers).env_args
|
||||
ensure
|
||||
ENV["DB_PASSWORD"] = nil
|
||||
end
|
||||
@@ -185,14 +190,16 @@ class ConfigurationRoleTest < ActiveSupport::TestCase
|
||||
}
|
||||
}
|
||||
|
||||
config_with_roles = Kamal::Configuration.new(@deploy_with_roles)
|
||||
|
||||
ENV["REDIS_PASSWORD"] = "secret456"
|
||||
|
||||
expected_secrets_file = <<~ENV
|
||||
REDIS_PASSWORD=secret456
|
||||
ENV
|
||||
|
||||
assert_equal expected_secrets_file, @config_with_roles.role(:workers).env.secrets_io.string
|
||||
assert_equal [ "--env-file", ".kamal/env/roles/app-workers.env", "--env", "REDIS_URL=\"redis://c/d\"" ], @config_with_roles.role(:workers).env_args
|
||||
assert_equal expected_secrets_file, config_with_roles.role(:workers).env.secrets_io.string
|
||||
assert_equal [ "--env-file", ".kamal/env/roles/app-workers.env", "--env", "REDIS_URL=\"redis://c/d\"" ], config_with_roles.role(:workers).env_args
|
||||
ensure
|
||||
ENV["REDIS_PASSWORD"] = nil
|
||||
end
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
service: app
|
||||
image: app
|
||||
primary_role: app
|
||||
servers:
|
||||
app:
|
||||
previously:
|
||||
- web
|
||||
hosts:
|
||||
- vm1
|
||||
- vm2
|
||||
jobs:
|
||||
previously:
|
||||
- workers
|
||||
hosts:
|
||||
- vm3
|
||||
cmd: sleep infinity
|
||||
|
||||
asset_path: /usr/share/nginx/html/versions
|
||||
|
||||
registry:
|
||||
server: registry:4443
|
||||
username: root
|
||||
password: root
|
||||
builder:
|
||||
multiarch: false
|
||||
args:
|
||||
COMMIT_SHA: <%= `git rev-parse HEAD` %>
|
||||
healthcheck:
|
||||
cmd: wget -qO- http://localhost > /dev/null || exit 1
|
||||
traefik:
|
||||
args:
|
||||
accesslog: true
|
||||
accesslog.format: json
|
||||
image: registry:4443/traefik:v2.10
|
||||
accessories:
|
||||
busybox:
|
||||
service: custom-busybox
|
||||
image: registry:4443/busybox:1.36.0
|
||||
cmd: sh -c 'echo "Starting busybox..."; trap exit term; while true; do sleep 1; done'
|
||||
roles:
|
||||
- app
|
||||
stop_wait_time: 1
|
||||
3
test/integration/docker/deployer/rename_roles.sh
Executable file
3
test/integration/docker/deployer/rename_roles.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $1 && cp -f config/deploy_renamed_roles.yml config/deploy.yml && git commit -am 'Rename roles'
|
||||
@@ -131,4 +131,16 @@ class IntegrationTest < ActiveSupport::TestCase
|
||||
puts "Tried to get the response code again and got #{app_response.code}"
|
||||
end
|
||||
end
|
||||
|
||||
def assert_container_running(host:, name:)
|
||||
assert container_running?(host: host, name: name)
|
||||
end
|
||||
|
||||
def assert_container_not_running(host:, name:)
|
||||
assert_not container_running?(host: host, name: name)
|
||||
end
|
||||
|
||||
def container_running?(host:, name:)
|
||||
docker_compose("exec #{host} docker ps --filter=name=#{name} | tail -n+2", capture: true).strip.present?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -92,6 +92,33 @@ class MainTest < IntegrationTest
|
||||
assert_no_images_or_containers
|
||||
end
|
||||
|
||||
test "rename roles" do
|
||||
@app = "app_with_roles"
|
||||
|
||||
kamal :envify
|
||||
kamal :deploy
|
||||
|
||||
first_version = latest_app_version
|
||||
|
||||
assert_container_running host: :vm1, name: "app-web-#{first_version}"
|
||||
assert_container_running host: :vm2, name: "app-web-#{first_version}"
|
||||
assert_container_running host: :vm3, name: "app-workers-#{first_version}"
|
||||
|
||||
rename_roles
|
||||
|
||||
kamal :envify
|
||||
kamal :deploy
|
||||
|
||||
second_version = latest_app_version
|
||||
|
||||
assert_container_running host: :vm1, name: "app-app-#{second_version}"
|
||||
assert_container_running host: :vm2, name: "app-app-#{second_version}"
|
||||
assert_container_running host: :vm3, name: "app-jobs-#{second_version}"
|
||||
assert_container_not_running host: :vm1, name: "app-web-#{first_version}"
|
||||
assert_container_not_running host: :vm2, name: "app-web-#{first_version}"
|
||||
assert_container_not_running host: :vm3, name: "app-workers-#{first_version}"
|
||||
end
|
||||
|
||||
private
|
||||
def assert_local_env_file(contents)
|
||||
assert_equal contents, deployer_exec("cat .env", capture: true)
|
||||
@@ -139,7 +166,7 @@ class MainTest < IntegrationTest
|
||||
assert vm1_container_ids.any?
|
||||
end
|
||||
|
||||
def assert_container_running(host:, name:)
|
||||
assert docker_compose("exec #{host} docker ps --filter=name=#{name} -q", capture: true).strip.present?
|
||||
def rename_roles
|
||||
deployer_exec "./rename_roles.sh #{@app}", workdir: "/"
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user