diff --git a/autodoc/admin-api/data/admin-api.lua b/autodoc/admin-api/data/admin-api.lua index 70beee6f776..d28d63e57e0 100644 --- a/autodoc/admin-api/data/admin-api.lua +++ b/autodoc/admin-api/data/admin-api.lua @@ -1571,6 +1571,7 @@ return { ["healthchecks.active.http_path"] = { description = [[Path to use in GET HTTP request to run as a probe on active health checks.]] }, ["healthchecks.active.https_verify_certificate"] = { description = [[Whether to check the validity of the SSL certificate of the remote host when performing active health checks using HTTPS.]] }, ["healthchecks.active.https_sni"] = { description = [[The hostname to use as an SNI (Server Name Identification) when performing active health checks using HTTPS. This is particularly useful when Targets are configured using IPs, so that the target host's certificate can be verified with the proper SNI.]], example = "example.com", }, + ["healthchecks.active.headers"] = { description = [[One or more lists of values indexed by header name to use in GET HTTP request to run as a probe on active health checks. Values must be pre-formatted.]], example = { { ["x-my-header"] = {"foo", "bar"}, ["x-another-header"] = {"bla"} }, nil }, }, ["healthchecks.active.healthy.interval"] = { description = [[Interval between active health checks for healthy targets (in seconds). A value of zero indicates that active probes for healthy targets should not be performed.]] }, ["healthchecks.active.healthy.http_statuses"] = { description = [[An array of HTTP statuses to consider a success, indicating healthiness, when returned by a probe in active health checks.]] }, ["healthchecks.active.healthy.successes"] = { description = [[Number of successes in active probes (as defined by `healthchecks.active.healthy.http_statuses`) to consider a target healthy.]] }, diff --git a/kong/db/schema/entities/upstreams.lua b/kong/db/schema/entities/upstreams.lua index f7fda2cebd8..e10bc71353d 100644 --- a/kong/db/schema/entities/upstreams.lua +++ b/kong/db/schema/entities/upstreams.lua @@ -73,7 +73,6 @@ local check_verify_certificate = Schema.define { required = true, } - local health_threshold = Schema.define { type = "number", default = 0, @@ -92,6 +91,7 @@ local healthchecks_config = { http_path = "/", https_sni = NO_DEFAULT, https_verify_certificate = true, + headers = NO_DEFAULT, healthy = { interval = 0, -- 0 = probing disabled by default http_statuses = { 200, 302 }, @@ -136,6 +136,7 @@ local types = { http_statuses = http_statuses, https_sni = typedefs.sni, https_verify_certificate = check_verify_certificate, + headers = typedefs.headers, } diff --git a/spec/01-unit/01-db/01-schema/09-upstreams_spec.lua b/spec/01-unit/01-db/01-schema/09-upstreams_spec.lua index b745c74aff6..c6c4b5efed9 100644 --- a/spec/01-unit/01-db/01-schema/09-upstreams_spec.lua +++ b/spec/01-unit/01-db/01-schema/09-upstreams_spec.lua @@ -67,6 +67,12 @@ describe("load upstreams", function() assert.truthy(errs.healthchecks.active.concurrency) end) + it("invalid healthckecks.active.headers produces error", function() + local ok, errs = validate({ healthchecks = { active = { headers = { 114514 } } } } ) + assert.falsy(ok) + assert.truthy(errs.healthchecks.active.headers) + end) + it("invalid healthckecks.active.http_path produces error", function() local ok, errs = validate({ healthchecks = { active = { http_path = "potato" } } } ) assert.falsy(ok) @@ -273,6 +279,10 @@ describe("load upstreams", function() local integer = "expected an integer" local boolean = "expected a boolean" local number = "expected a number" + local array = "expected an array" + local string = "expected a string" + local map = "expected a map" + local len_min_default = "length must be at least 1" local invalid_host = "invalid value: " local invalid_host_port = "must not have a port" local invalid_ip = "must not be an IP" @@ -283,7 +293,7 @@ describe("load upstreams", function() {{ active = { concurrency = 0.5 }}, integer }, {{ active = { concurrency = 0 }}, pos_integer }, {{ active = { concurrency = -10 }}, pos_integer }, - {{ active = { http_path = "" }}, "length must be at least 1" }, + {{ active = { http_path = "" }}, len_min_default }, {{ active = { http_path = "ovo" }}, "should start with: /" }, {{ active = { https_sni = "127.0.0.1", }}, invalid_ip }, {{ active = { https_sni = "127.0.0.1:8080", }}, invalid_ip }, @@ -298,9 +308,13 @@ describe("load upstreams", function() {{ active = { https_sni = "hello-.example.com", }}, invalid_host }, {{ active = { https_sni = "example.com:1234", }}, invalid_host_port }, {{ active = { https_verify_certificate = "ovo", }}, boolean }, + {{ active = { headers = 0, }}, map }, + {{ active = { headers = { 0 }, }}, string }, + {{ active = { headers = { "" }, }}, string }, + {{ active = { headers = { ["x-header"] = 123 }, }}, array }, {{ active = { healthy = { interval = -1 }}}, seconds }, {{ active = { healthy = { interval = 1e+42 }}}, seconds }, - {{ active = { healthy = { http_statuses = 404 }}}, "expected an array" }, + {{ active = { healthy = { http_statuses = 404 }}}, array }, {{ active = { healthy = { http_statuses = { "ovo" }}}}, integer }, {{ active = { healthy = { http_statuses = { -1 }}}}, status_code }, {{ active = { healthy = { http_statuses = { 99 }}}}, status_code }, @@ -316,7 +330,7 @@ describe("load upstreams", function() {{ active = { healthy = { successes = 256 }}}, zero_integer }, {{ active = { unhealthy = { interval = -1 }}}, seconds }, {{ active = { unhealthy = { interval = 1e+42 }}}, seconds }, - {{ active = { unhealthy = { http_statuses = 404 }}}, "expected an array" }, + {{ active = { unhealthy = { http_statuses = 404 }}}, array }, {{ active = { unhealthy = { http_statuses = { "ovo" }}}}, integer }, {{ active = { unhealthy = { http_statuses = { -1 }}}}, status_code }, {{ active = { unhealthy = { http_statuses = { 99 }}}}, status_code }, @@ -332,7 +346,7 @@ describe("load upstreams", function() {{ active = { unhealthy = { http_failures = 0.5 }}}, integer}, {{ active = { unhealthy = { http_failures = -1 }}}, zero_integer }, {{ active = { unhealthy = { http_failures = 256 }}}, zero_integer }, - {{ passive = { healthy = { http_statuses = 404 }}}, "expected an array" }, + {{ passive = { healthy = { http_statuses = 404 }}}, array }, {{ passive = { healthy = { http_statuses = { "ovo" }}}}, integer }, {{ passive = { healthy = { http_statuses = { -1 }}}}, status_code }, {{ passive = { healthy = { http_statuses = { 99 }}}}, status_code }, @@ -340,7 +354,7 @@ describe("load upstreams", function() {{ passive = { healthy = { successes = 0.5 }}}, integer }, --{{ passive = { healthy = { successes = 0 }}}, integer }, {{ passive = { healthy = { successes = -1 }}}, zero_integer }, - {{ passive = { unhealthy = { http_statuses = 404 }}}, "expected an array" }, + {{ passive = { unhealthy = { http_statuses = 404 }}}, array }, {{ passive = { unhealthy = { http_statuses = { "ovo" }}}}, integer }, {{ passive = { unhealthy = { http_statuses = { -1 }}}}, status_code }, {{ passive = { unhealthy = { http_statuses = { 99 }}}}, status_code }, diff --git a/spec/01-unit/01-db/01-schema/11-declarative_config/03-flatten_spec.lua b/spec/01-unit/01-db/01-schema/11-declarative_config/03-flatten_spec.lua index 5de27ea70c3..be5a84ece2c 100644 --- a/spec/01-unit/01-db/01-schema/11-declarative_config/03-flatten_spec.lua +++ b/spec/01-unit/01-db/01-schema/11-declarative_config/03-flatten_spec.lua @@ -1781,6 +1781,7 @@ describe("declarative config: flatten", function() http_path = "/", https_sni = null, https_verify_certificate = true, + headers = null, timeout = 1, type = "http", unhealthy = { @@ -1832,6 +1833,7 @@ describe("declarative config: flatten", function() http_path = "/", https_sni = null, https_verify_certificate = true, + headers = null, timeout = 1, type = "http", unhealthy = { diff --git a/spec/02-integration/05-proxy/10-balancer/01-healthchecks_spec.lua b/spec/02-integration/05-proxy/10-balancer/01-healthchecks_spec.lua index 6f6e6cfd203..89f74cf0c46 100644 --- a/spec/02-integration/05-proxy/10-balancer/01-healthchecks_spec.lua +++ b/spec/02-integration/05-proxy/10-balancer/01-healthchecks_spec.lua @@ -729,6 +729,7 @@ for _, strategy in helpers.each_strategy() do http_path = "/status", https_sni = cjson.null, https_verify_certificate = true, + headers = cjson.null, timeout = 1, unhealthy = { http_failures = 1,