Rename roles

Allow roles to be renamed without having to manually stop the old
containers.

If you have config like:

```
servers:
  jobs:
    hosts:
      - vm3
```

And you want to rename `jobs` to `workers`, you can do:

```
servers:
  workers:
    previously:
      - jobs
    hosts:
      - vm3
```

And the deployment will take care of stopping the old "jobs" containers.

Once deployed you can remove the `previously` key.
This commit is contained in:
Donal McBreen
2024-03-26 13:48:04 +00:00
parent d475e88dbe
commit 9a5880208a
9 changed files with 137 additions and 28 deletions

View File

@@ -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?

View File

@@ -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)

View File

@@ -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?

View File

@@ -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