Merge pull request #1501 from basecamp/accessory-only
Allow accessory only configurations
This commit is contained in:
@@ -149,8 +149,12 @@ class Kamal::Configuration
|
|||||||
proxy_roles.flat_map(&:name)
|
proxy_roles.flat_map(&:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def proxy_accessories
|
||||||
|
accessories.select(&:running_proxy?)
|
||||||
|
end
|
||||||
|
|
||||||
def proxy_hosts
|
def proxy_hosts
|
||||||
proxy_roles.flat_map(&:hosts).uniq
|
(proxy_roles.flat_map(&:hosts) + proxy_accessories.flat_map(&:hosts)).uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
def repository
|
def repository
|
||||||
@@ -367,22 +371,26 @@ class Kamal::Configuration
|
|||||||
end
|
end
|
||||||
|
|
||||||
def ensure_required_keys_present
|
def ensure_required_keys_present
|
||||||
%i[ service image registry servers ].each do |key|
|
%i[ service image registry ].each do |key|
|
||||||
raise Kamal::ConfigurationError, "Missing required configuration for #{key}" unless raw_config[key].present?
|
raise Kamal::ConfigurationError, "Missing required configuration for #{key}" unless raw_config[key].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
unless role(primary_role_name).present?
|
if raw_config.servers.nil?
|
||||||
raise Kamal::ConfigurationError, "The primary_role #{primary_role_name} isn't defined"
|
raise Kamal::ConfigurationError, "No servers or accessories specified" unless raw_config.accessories.present?
|
||||||
end
|
else
|
||||||
|
unless role(primary_role_name).present?
|
||||||
|
raise Kamal::ConfigurationError, "The primary_role #{primary_role_name} isn't defined"
|
||||||
|
end
|
||||||
|
|
||||||
if primary_role.hosts.empty?
|
if primary_role.hosts.empty?
|
||||||
raise Kamal::ConfigurationError, "No servers specified for the #{primary_role.name} primary_role"
|
raise Kamal::ConfigurationError, "No servers specified for the #{primary_role.name} primary_role"
|
||||||
end
|
end
|
||||||
|
|
||||||
unless allow_empty_roles?
|
unless allow_empty_roles?
|
||||||
roles.each do |role|
|
roles.each do |role|
|
||||||
if role.hosts.empty?
|
if role.hosts.empty?
|
||||||
raise Kamal::ConfigurationError, "No servers specified for the #{role.name} role. You can ignore this with allow_empty_roles: true"
|
raise Kamal::ConfigurationError, "No servers specified for the #{role.name} role. You can ignore this with allow_empty_roles: true"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ class Kamal::Configuration::Servers
|
|||||||
|
|
||||||
private
|
private
|
||||||
def role_names
|
def role_names
|
||||||
servers_config.is_a?(Array) ? [ "web" ] : servers_config.keys.sort
|
case servers_config
|
||||||
|
when Array
|
||||||
|
[ "web" ]
|
||||||
|
when NilClass
|
||||||
|
[]
|
||||||
|
else
|
||||||
|
servers_config.keys.sort
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
class Kamal::Configuration::Validator::Servers < Kamal::Configuration::Validator
|
class Kamal::Configuration::Validator::Servers < Kamal::Configuration::Validator
|
||||||
def validate!
|
def validate!
|
||||||
validate_type! config, Array, Hash
|
validate_type! config, Array, Hash, NilClass
|
||||||
|
|
||||||
validate_servers! config if config.is_a?(Array)
|
validate_servers! config if config.is_a?(Array)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
%i[ service image registry ].each do |key|
|
%i[ service image registry ].each do |key|
|
||||||
test "#{key} config required" do
|
test "#{key} config required" do
|
||||||
assert_raise(Kamal::ConfigurationError) do
|
assert_raise(Kamal::ConfigurationError) do
|
||||||
Kamal::Configuration.new @deploy.tap { _1.delete key }
|
Kamal::Configuration.new @deploy.tap { |config| config.delete key }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -38,21 +38,36 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
%w[ username password ].each do |key|
|
%w[ username password ].each do |key|
|
||||||
test "registry #{key} required" do
|
test "registry #{key} required" do
|
||||||
assert_raise(Kamal::ConfigurationError) do
|
assert_raise(Kamal::ConfigurationError) do
|
||||||
Kamal::Configuration.new @deploy.tap { _1[:registry].delete key }
|
Kamal::Configuration.new @deploy.tap { |config| config[:registry].delete key }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "service name valid" do
|
test "service name valid" do
|
||||||
assert_nothing_raised do
|
assert_nothing_raised do
|
||||||
Kamal::Configuration.new(@deploy.tap { _1[:service] = "hey-app1_primary" })
|
Kamal::Configuration.new(@deploy.tap { |config| config[:service] = "hey-app1_primary" })
|
||||||
Kamal::Configuration.new(@deploy.tap { _1[:service] = "MyApp" })
|
Kamal::Configuration.new(@deploy.tap { |config| config[:service] = "MyApp" })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test "service name invalid" do
|
test "service name invalid" do
|
||||||
assert_raise(Kamal::ConfigurationError) do
|
assert_raise(Kamal::ConfigurationError) do
|
||||||
Kamal::Configuration.new @deploy.tap { _1[:service] = "app.com" }
|
Kamal::Configuration.new @deploy.tap { |config| config[:service] = "app.com" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "servers required" do
|
||||||
|
assert_raise(Kamal::ConfigurationError) do
|
||||||
|
Kamal::Configuration.new @deploy.tap { |config| config.delete(:servers) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
test "servers not required with accessories" do
|
||||||
|
assert_nothing_raised do
|
||||||
|
@deploy.delete(:servers)
|
||||||
|
@deploy[:accessories] = { "foo" => { "image" => "foo/bar", "host" => "1.1.1.1" } }
|
||||||
|
|
||||||
|
Kamal::Configuration.new(@deploy)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -250,7 +265,7 @@ class ConfigurationTest < ActiveSupport::TestCase
|
|||||||
test "destination required" do
|
test "destination required" do
|
||||||
dest_config_file = Pathname.new(File.expand_path("fixtures/deploy_for_required_dest.yml", __dir__))
|
dest_config_file = Pathname.new(File.expand_path("fixtures/deploy_for_required_dest.yml", __dir__))
|
||||||
|
|
||||||
assert_raises(Kamal::ConfigurationError) do
|
assert_raises(ArgumentError, "You must specify a destination") do
|
||||||
config = Kamal::Configuration.create_from config_file: dest_config_file
|
config = Kamal::Configuration.create_from config_file: dest_config_file
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,32 @@ class AccessoryTest < IntegrationTest
|
|||||||
assert_accessory_not_running :busybox
|
assert_accessory_not_running :busybox
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "proxied: boot, stop, start, restart, logs, remove" do
|
||||||
|
@app = "app_with_proxied_accessory"
|
||||||
|
|
||||||
|
kamal :proxy, :boot
|
||||||
|
|
||||||
|
kamal :accessory, :boot, :netcat
|
||||||
|
assert_accessory_running :netcat
|
||||||
|
assert_netcat_is_up
|
||||||
|
|
||||||
|
kamal :accessory, :stop, :netcat
|
||||||
|
assert_accessory_not_running :netcat
|
||||||
|
assert_netcat_not_found
|
||||||
|
|
||||||
|
kamal :accessory, :start, :netcat
|
||||||
|
assert_accessory_running :netcat
|
||||||
|
assert_netcat_is_up
|
||||||
|
|
||||||
|
kamal :accessory, :restart, :netcat
|
||||||
|
assert_accessory_running :netcat
|
||||||
|
assert_netcat_is_up
|
||||||
|
|
||||||
|
kamal :accessory, :remove, :netcat, "-y"
|
||||||
|
assert_accessory_not_running :netcat
|
||||||
|
assert_netcat_not_found
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def assert_accessory_running(name)
|
def assert_accessory_running(name)
|
||||||
assert_match /registry:4443\/busybox:1.36.0 "sh -c 'echo \\"Start/, accessory_details(name)
|
assert_match /registry:4443\/busybox:1.36.0 "sh -c 'echo \\"Start/, accessory_details(name)
|
||||||
@@ -33,4 +59,25 @@ class AccessoryTest < IntegrationTest
|
|||||||
def accessory_details(name)
|
def accessory_details(name)
|
||||||
kamal :accessory, :details, name, capture: true
|
kamal :accessory, :details, name, capture: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assert_netcat_is_up
|
||||||
|
response = netcat_response
|
||||||
|
debug_response_code(response, "200")
|
||||||
|
assert_equal "200", response.code
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_netcat_not_found
|
||||||
|
response = netcat_response
|
||||||
|
debug_response_code(response, "404")
|
||||||
|
assert_equal "404", response.code
|
||||||
|
end
|
||||||
|
|
||||||
|
def netcat_response
|
||||||
|
uri = URI.parse("http://127.0.0.1:12345/up")
|
||||||
|
http = Net::HTTP.new(uri.host, uri.port)
|
||||||
|
request = Net::HTTP::Get.new(uri)
|
||||||
|
request["Host"] = "netcat"
|
||||||
|
|
||||||
|
http.request(request)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
service: app_with_proxied_accessory
|
service: app_with_proxied_accessory
|
||||||
image: app_with_proxied_accessory
|
image: app_with_proxied_accessory
|
||||||
servers:
|
|
||||||
- vm1
|
|
||||||
env:
|
env:
|
||||||
clear:
|
clear:
|
||||||
CLEAR_TOKEN: 4321
|
CLEAR_TOKEN: 4321
|
||||||
@@ -24,15 +22,13 @@ accessories:
|
|||||||
service: custom-busybox
|
service: custom-busybox
|
||||||
image: registry:4443/busybox:1.36.0
|
image: registry:4443/busybox:1.36.0
|
||||||
cmd: sh -c 'echo "Starting busybox..."; trap exit term; while true; do sleep 1; done'
|
cmd: sh -c 'echo "Starting busybox..."; trap exit term; while true; do sleep 1; done'
|
||||||
roles:
|
host: vm1
|
||||||
- web
|
|
||||||
netcat:
|
netcat:
|
||||||
service: netcat
|
service: netcat
|
||||||
image: registry:4443/busybox:1.36.0
|
image: registry:4443/busybox:1.36.0
|
||||||
cmd: >
|
cmd: >
|
||||||
sh -c 'echo "Starting netcat..."; while true; do echo -e "HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nHello Ruby" | nc -l -p 80; done'
|
sh -c 'echo "Starting netcat..."; while true; do echo -e "HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nHello Ruby" | nc -l -p 80; done'
|
||||||
roles:
|
host: vm1
|
||||||
- web
|
|
||||||
port: 12345:80
|
port: 12345:80
|
||||||
proxy:
|
proxy:
|
||||||
host: netcat
|
host: netcat
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
require_relative "integration_test"
|
|
||||||
|
|
||||||
class ProxiedAccessoryTest < IntegrationTest
|
|
||||||
test "boot, stop, start, restart, logs, remove" do
|
|
||||||
@app = "app_with_proxied_accessory"
|
|
||||||
|
|
||||||
kamal :deploy
|
|
||||||
|
|
||||||
kamal :accessory, :boot, :netcat
|
|
||||||
assert_accessory_running :netcat
|
|
||||||
assert_netcat_is_up
|
|
||||||
|
|
||||||
kamal :accessory, :stop, :netcat
|
|
||||||
assert_accessory_not_running :netcat
|
|
||||||
assert_netcat_not_found
|
|
||||||
|
|
||||||
kamal :accessory, :start, :netcat
|
|
||||||
assert_accessory_running :netcat
|
|
||||||
assert_netcat_is_up
|
|
||||||
|
|
||||||
kamal :accessory, :restart, :netcat
|
|
||||||
assert_accessory_running :netcat
|
|
||||||
assert_netcat_is_up
|
|
||||||
|
|
||||||
kamal :accessory, :remove, :netcat, "-y"
|
|
||||||
assert_accessory_not_running :netcat
|
|
||||||
assert_netcat_not_found
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def assert_accessory_running(name)
|
|
||||||
assert_match /registry:4443\/busybox:1.36.0 "sh -c 'echo \\"Start/, accessory_details(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_accessory_not_running(name)
|
|
||||||
assert_no_match /registry:4443\/busybox:1.36.0 "sh -c 'echo \\"Start/, accessory_details(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def accessory_details(name)
|
|
||||||
kamal :accessory, :details, name, capture: true
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_netcat_is_up
|
|
||||||
response = netcat_response
|
|
||||||
debug_response_code(response, "200")
|
|
||||||
assert_equal "200", response.code
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_netcat_not_found
|
|
||||||
response = netcat_response
|
|
||||||
debug_response_code(response, "404")
|
|
||||||
assert_equal "404", response.code
|
|
||||||
end
|
|
||||||
|
|
||||||
def netcat_response
|
|
||||||
uri = URI.parse("http://127.0.0.1:12345/up")
|
|
||||||
http = Net::HTTP.new(uri.host, uri.port)
|
|
||||||
request = Net::HTTP::Get.new(uri)
|
|
||||||
request["Host"] = "netcat"
|
|
||||||
|
|
||||||
http.request(request)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
Reference in New Issue
Block a user