Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
- Fix: turning off the health check on a k8s, azure or azure-aro scope now removes the liveness, readiness and startup probes from every container of the pod
- Fix: k8s scopes that have both a custom domain and additional ports now deploy, instead of failing with "Failed to build ingress template"

## [1.16.3] - 2026-09-08
Expand Down
9 changes: 9 additions & 0 deletions k8s/deployment/templates/deployment.yaml.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
initialDelaySeconds: {{ .healthCheck.initial_delay_seconds }}
successThreshold: 1
{{- end }}
{{- $healthCheckEnabled := or (not (has .scope.capabilities.health_check "enabled")) .scope.capabilities.health_check.enabled }}

apiVersion: apps/v1
kind: Deployment
Expand Down Expand Up @@ -147,6 +148,7 @@ spec:
memory: {{ .container_memory_in_memory }}Mi
requests:
cpu: 31m
{{- if $healthCheckEnabled }}
livenessProbe:
{{- if and (has .scope.capabilities.health_check "type") (eq .scope.capabilities.health_check.type "TCP") }}
{{- template "probe.tcp" dict "healthCheck" .scope.capabilities.health_check "traffic_port" .main_traffic_manager_port "app_port" .main_http_port }}
Expand All @@ -171,6 +173,7 @@ spec:
{{- end }}
{{- template "probe.base" dict "healthCheck" .scope.capabilities.health_check }}
failureThreshold: 90
{{- end }}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: Always
Expand Down Expand Up @@ -202,6 +205,7 @@ spec:
memory: {{ $.container_memory_in_memory }}Mi
requests:
cpu: 31m
{{- if $healthCheckEnabled }}
livenessProbe:
grpc:
port: {{ .traffic_manager_port }}
Expand All @@ -226,6 +230,7 @@ spec:
initialDelaySeconds: {{ $.scope.capabilities.health_check.initial_delay_seconds }}
successThreshold: 1
failureThreshold: 90
{{- end }}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: Always
Expand Down Expand Up @@ -256,6 +261,7 @@ spec:
memory: {{ $.container_memory_in_memory }}Mi
requests:
cpu: 31m
{{- if $healthCheckEnabled }}
livenessProbe:
httpGet:
path: {{ $.scope.capabilities.health_check.path }}
Expand Down Expand Up @@ -283,6 +289,7 @@ spec:
initialDelaySeconds: {{ $.scope.capabilities.health_check.initial_delay_seconds }}
successThreshold: 1
failureThreshold: 90
{{- end }}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: Always
Expand Down Expand Up @@ -323,6 +330,7 @@ spec:
requests:
cpu: {{ .scope.capabilities.cpu_millicores }}m
memory: {{ .scope.capabilities.ram_memory }}Mi
{{- if $healthCheckEnabled }}
livenessProbe:
{{- if and (has .scope.capabilities.health_check "type") (eq .scope.capabilities.health_check.type "TCP") }}
{{- template "probe.app_tcp" dict "port" .main_http_port }}
Expand All @@ -347,6 +355,7 @@ spec:
{{- end }}
{{- template "probe.base" dict "healthCheck" .scope.capabilities.health_check }}
failureThreshold: 90
{{- end }}
lifecycle:
preStop:
exec:
Expand Down
130 changes: 130 additions & 0 deletions k8s/deployment/tests/health_check_disabled.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env bats

setup() {
export PROJECT_ROOT="$(cd "$BATS_TEST_DIRNAME/../../.." && pwd)"
source "$PROJECT_ROOT/testing/assertions.sh"
export DEPLOYMENT="$PROJECT_ROOT/k8s/deployment/templates/deployment.yaml.tpl"
}

_context() {
local health_check="$1"
cat <<JSON
{
"account": {"id": "acc1", "slug": "acct"},
"namespace": {"id": "ns1", "slug": "nsps"},
"application": {"id": "app1", "slug": "appslug"},
"scope": {
"id": "scope-123",
"slug": "scopeslug",
"domain": "platform.example.com",
"domains": [],
"dimensions": {"env": "dev"},
"capabilities": {
"cpu_millicores": 100,
"ram_memory": 128,
"cpu_millicores_limit": 200,
"ram_memory_limit": 256,
"main_http_port": 8080,
"additional_ports": [
{"port": 8081, "type": "HTTP", "traffic_manager_port": 18081},
{"port": 9012, "type": "GRPC", "traffic_manager_port": 19012}
],
"scaling_type": "fixed",
"autoscaling": {
"min_replicas": 1,
"max_replicas": 3,
"target_cpu_utilization": 80,
"target_memory_enabled": false,
"target_memory_utilization": 80
},
"health_check": $health_check
}
},
"deployment": {"id": "deploy-456"},
"k8s_namespace": "ns-test",
"k8s_modifiers": {},
"asset": {"url": "example.com/app:latest"},
"main_http_port": 8080,
"main_traffic_manager_port": 80,
"traffic_image": "example.com/traffic:latest",
"container_cpu_in_millicores": 50,
"container_memory_in_memory": 64,
"pull_secrets": {"ENABLED": false, "SECRETS": []},
"region": "us-east-1",
"component": "app",
"service_account_name": "",
"traffic_manager_config_map": "",
"replicas": 1,
"parameters": {"results": []}
}
JSON
}

_health_check() {
echo "{\"enabled\": $1, \"type\": \"$2\", \"path\": \"/health\", \"timeout_seconds\": 1, \"period_seconds\": 5, \"initial_delay_seconds\": 5}"
}

_render() {
local ctx="$BATS_TEST_TMPDIR/ctx.json"
_context "$1" > "$ctx"
gomplate -c .="$ctx" -f "$DEPLOYMENT"
}

_probe_count() {
local rendered="$1" container="$2"
echo "$rendered" | yq -N ".spec.template.spec.containers[] | select(.name == \"$container\") | [.livenessProbe, .readinessProbe, .startupProbe] | map(select(. != null)) | length"
}

_assert_probes_on_every_container() {
local rendered="$1" expected="$2"
local container actual
for container in http application http-8081 grpc-9012; do
actual=$(_probe_count "$rendered" "$container")
if [ "$actual" != "$expected" ]; then
echo "container '$container': expected $expected probes, got $actual"
return 1
fi
done
}

@test "health check disabled: no container gets liveness, readiness or startup probes" {
rendered=$(_render "$(_health_check false HTTP)")

_assert_probes_on_every_container "$rendered" 0
}

@test "health check disabled with TCP type: no container gets probes either" {
rendered=$(_render "$(_health_check false TCP)")

_assert_probes_on_every_container "$rendered" 0
}

@test "health check enabled: every container keeps its three probes" {
rendered=$(_render "$(_health_check true HTTP)")

_assert_probes_on_every_container "$rendered" 3
}

@test "scope predating the enabled flag: every container keeps its three probes" {
rendered=$(_render '{"type": "HTTP", "path": "/health", "timeout_seconds": 1, "period_seconds": 5, "initial_delay_seconds": 5}')

_assert_probes_on_every_container "$rendered" 3
}

@test "health check disabled: containers and their ports survive" {
rendered=$(_render "$(_health_check false HTTP)")

assert_equal "$(echo "$rendered" | yq -N '[.spec.template.spec.containers[].name] | join(",")')" \
"http,http-8081,grpc-9012,application"
assert_equal "$(echo "$rendered" | yq -N '[.spec.template.spec.containers[] | select(.name == "application") | .ports[].containerPort] | join(",")')" \
"8080,8081,9012"
assert_equal "$(echo "$rendered" | yq -N '.spec.template.spec.containers[] | select(.name == "http") | .ports[0].containerPort')" \
"80"
}

@test "health check disabled: the application keeps its graceful shutdown hook" {
rendered=$(_render "$(_health_check false HTTP)")

assert_equal "$(echo "$rendered" | yq -N '.spec.template.spec.containers[] | select(.name == "application") | .lifecycle.preStop.exec.command | join(" ")')" \
"/bin/sleep 16"
}
Loading