From 1d88281fee8bebcd522dc1d8600dd76348755c1c Mon Sep 17 00:00:00 2001 From: Nick Hammond Date: Mon, 9 Jun 2025 19:08:20 -0700 Subject: [PATCH] Validate that destination, role, and service are not set as labels on roles and accessories --- lib/kamal/configuration/validator.rb | 10 ++++++++++ lib/kamal/configuration/validator/accessory.rb | 2 ++ lib/kamal/configuration/validator/role.rb | 2 ++ test/configuration/validation_test.rb | 2 ++ 4 files changed, 16 insertions(+) diff --git a/lib/kamal/configuration/validator.rb b/lib/kamal/configuration/validator.rb index e67a4579..6fe9c604 100644 --- a/lib/kamal/configuration/validator.rb +++ b/lib/kamal/configuration/validator.rb @@ -169,6 +169,16 @@ class Kamal::Configuration::Validator unknown_keys_error unknown_keys if unknown_keys.present? end + def validate_labels!(labels) + with_context("labels") do + labels.each do |key, _| + with_context(key) do + error "invalid label. destination, role, and service are reserved labels" if %w[destination role service].include?(key) + end + end + end + end + def validate_docker_options!(options) if options error "Cannot set restart policy in docker options, unless-stopped is required" if options["restart"] diff --git a/lib/kamal/configuration/validator/accessory.rb b/lib/kamal/configuration/validator/accessory.rb index 564cfc7e..df18f196 100644 --- a/lib/kamal/configuration/validator/accessory.rb +++ b/lib/kamal/configuration/validator/accessory.rb @@ -6,6 +6,8 @@ class Kamal::Configuration::Validator::Accessory < Kamal::Configuration::Validat error "specify one of `host`, `hosts`, `role`, `roles`, `tag` or `tags`" end + validate_labels!(config["labels"]) if config.key?("labels") + validate_docker_options!(config["options"]) end end diff --git a/lib/kamal/configuration/validator/role.rb b/lib/kamal/configuration/validator/role.rb index e631746a..e5479217 100644 --- a/lib/kamal/configuration/validator/role.rb +++ b/lib/kamal/configuration/validator/role.rb @@ -2,6 +2,8 @@ class Kamal::Configuration::Validator::Role < Kamal::Configuration::Validator def validate! validate_type! config, Array, Hash + validate_labels!(config["labels"]) if config.key?("labels") + if config.is_a?(Array) validate_servers!(config) else diff --git a/test/configuration/validation_test.rb b/test/configuration/validation_test.rb index 179aacfe..ad3625d1 100644 --- a/test/configuration/validation_test.rb +++ b/test/configuration/validation_test.rb @@ -42,6 +42,7 @@ class ConfigurationValidationTest < ActiveSupport::TestCase assert_error "servers/web/options: should be a hash", servers: { "web" => { "options" => "" } } assert_error "servers/web/logging/options: should be a hash", servers: { "web" => { "logging" => { "options" => "" } } } assert_error "servers/web/logging/driver: should be a string", servers: { "web" => { "logging" => { "driver" => [] } } } + assert_error "servers/web/labels/service: invalid label. destination, role, and service are reserved labels", servers: { "web" => { "labels" => { "service" => "foo" } } } assert_error "servers/web/labels: should be a hash", servers: { "web" => { "labels" => [] } } assert_error "servers/web/env: should be a hash", servers: { "web" => { "env" => [] } } assert_error "servers/web/env: tags are only allowed in the root env", servers: { "web" => { "hosts" => [ "1.1.1.1" ], "env" => { "tags" => {} } } } @@ -58,6 +59,7 @@ class ConfigurationValidationTest < ActiveSupport::TestCase assert_error "accessories/accessory1: should be a hash", accessories: { "accessory1" => [] } assert_error "accessories/accessory1: unknown key: unknown", accessories: { "accessory1" => { "unknown" => "baz" } } assert_error "accessories/accessory1/options: should be a hash", accessories: { "accessory1" => { "options" => [] } } + assert_error "accessories/accessory1/labels/destination: invalid label. destination, role, and service are reserved labels", accessories: { "accessory1" => { "host" => "host", "labels" => { "destination" => "foo" } } } assert_error "accessories/accessory1/host: should be a string", accessories: { "accessory1" => { "host" => [] } } assert_error "accessories/accessory1/env: should be a hash", accessories: { "accessory1" => { "env" => [] } } assert_error "accessories/accessory1/env: tags are only allowed in the root env", accessories: { "accessory1" => { "host" => "host", "env" => { "tags" => {} } } }