mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(helm/ai-gateway): render service nodePort with an explicit if guard (#27682)
> Coder Agents generated this commit Replace the with block around the Service nodePort field with an if guard that references .Values.service.nodePort directly. The with form rebinds the dot inside the block, so a later addition that needs .Values or .Release there would break. Extend the default_values fixture to enable ingress and httproute with only the values each one requires, so the golden file covers every template with the minimum viable configuration. Add a mustNotContain list to the render test cases. Golden files are rewritten wholesale by TestUpdateGoldenFiles, so these assertions pin optional fields and resources that each fixture leaves unset, including the Service nodePort.
This commit is contained in:
@@ -29,7 +29,7 @@ spec:
|
||||
port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
{{- with .Values.service.nodePort }}
|
||||
nodePort: {{ . }}
|
||||
{{- if .Values.service.nodePort }}
|
||||
nodePort: {{ .Values.service.nodePort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
@@ -22,21 +22,85 @@ var testCases = []testCase{
|
||||
{
|
||||
name: "default_values",
|
||||
fixture: "default_values",
|
||||
// The fixture enables every optional resource, so this case covers
|
||||
// rendering of all templates with the minimum required values.
|
||||
apiVersions: []string{"gateway.networking.k8s.io/v1/HTTPRoute"},
|
||||
mustNotContain: []string{
|
||||
// Service fields that only render when their value is set.
|
||||
"nodePort:",
|
||||
"loadBalancerClass:",
|
||||
"loadBalancerIP:",
|
||||
// externalTrafficPolicy only applies to NodePort and LoadBalancer.
|
||||
"externalTrafficPolicy:",
|
||||
// Ingress and HTTPRoute render with required fields only.
|
||||
"ingressClassName:",
|
||||
"hostnames:",
|
||||
// No secret is configured, so nothing mounts a Secret or switches
|
||||
// the probes and listener to TLS.
|
||||
"secretName:",
|
||||
"CODER_AI_GATEWAY_KEY_FILE",
|
||||
"CODER_AI_GATEWAY_TLS_CERT_FILE",
|
||||
"CODER_CLIENT_TLS_CA_FILE",
|
||||
"CODER_CLIENT_TLS_CERT_FILE",
|
||||
"scheme: HTTPS",
|
||||
// Opt-in workload settings.
|
||||
"startupProbe:",
|
||||
"envFrom:",
|
||||
"imagePullSecrets:",
|
||||
"priorityClassName:",
|
||||
"kind: ConfigMap",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "networking",
|
||||
fixture: "networking",
|
||||
namespace: "ai-gateway-test",
|
||||
apiVersions: []string{"gateway.networking.k8s.io/v1/HTTPRoute"},
|
||||
mustNotContain: []string{
|
||||
// The Service is a LoadBalancer without an explicit nodePort, so
|
||||
// Kubernetes allocates the port.
|
||||
"nodePort:",
|
||||
"loadBalancerIP:",
|
||||
// Only the Gateway key Secret is configured.
|
||||
"ai-gateway-listener",
|
||||
"coder-client-ca",
|
||||
"coder-client-tls",
|
||||
"scheme: HTTPS",
|
||||
"startupProbe:",
|
||||
"envFrom:",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "custom",
|
||||
fixture: "custom",
|
||||
namespace: "ai-gateway-test",
|
||||
mustNotContain: []string{
|
||||
// coder.serviceAccount.disableCreate is true, so the chart uses the
|
||||
// existing account instead of creating one.
|
||||
"kind: ServiceAccount",
|
||||
// Only the default ClusterIP Service renders.
|
||||
"kind: Ingress",
|
||||
"kind: HTTPRoute",
|
||||
"nodePort:",
|
||||
"loadBalancerClass:",
|
||||
"loadBalancerIP:",
|
||||
"externalTrafficPolicy:",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "nodeport",
|
||||
fixture: "nodeport",
|
||||
mustNotContain: []string{
|
||||
// LoadBalancer-only fields stay absent for a NodePort Service.
|
||||
"loadBalancerClass:",
|
||||
"loadBalancerIP:",
|
||||
"kind: Ingress",
|
||||
"kind: HTTPRoute",
|
||||
"ai-gateway-listener",
|
||||
"coder-client-ca",
|
||||
"coder-client-tls",
|
||||
"scheme: HTTPS",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing_key_field",
|
||||
@@ -54,6 +118,20 @@ var testCases = []testCase{
|
||||
{
|
||||
name: "listener_tls_with_ingress",
|
||||
fixture: "listener_tls_with_ingress",
|
||||
mustNotContain: []string{
|
||||
// Listener TLS does not imply client TLS to coderd.
|
||||
"coder-client-ca",
|
||||
"coder-client-tls",
|
||||
"CODER_CLIENT_TLS_CA_FILE",
|
||||
"CODER_CLIENT_TLS_CERT_FILE",
|
||||
// The Ingress renders with required fields only.
|
||||
"ingressClassName:",
|
||||
"kind: HTTPRoute",
|
||||
"nodePort:",
|
||||
"loadBalancerClass:",
|
||||
"loadBalancerIP:",
|
||||
"externalTrafficPolicy:",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "partial_client_tls",
|
||||
@@ -104,6 +182,12 @@ type testCase struct {
|
||||
namespace string
|
||||
expectedError string
|
||||
apiVersions []string
|
||||
// mustNotContain holds substrings that must be absent from the rendered
|
||||
// output. Golden files are rewritten wholesale by TestUpdateGoldenFiles,
|
||||
// so absence assertions live here to keep an unintended field from being
|
||||
// baked into the golden file. Each entry names an optional field or
|
||||
// resource that the fixture leaves unset.
|
||||
mustNotContain []string
|
||||
}
|
||||
|
||||
func (tc testCase) valuesFilePath() string {
|
||||
@@ -143,6 +227,9 @@ func TestRenderChart(t *testing.T) {
|
||||
return
|
||||
}
|
||||
require.NoError(t, err, output)
|
||||
for _, absent := range tc.mustNotContain {
|
||||
require.NotContains(t, output, absent)
|
||||
}
|
||||
golden, err := os.ReadFile(tc.goldenFilePath())
|
||||
require.NoError(t, err)
|
||||
golden = bytes.ReplaceAll(golden, []byte("\r"), nil)
|
||||
|
||||
@@ -137,3 +137,54 @@ spec:
|
||||
serviceAccountName: coder-ai-gateway
|
||||
terminationGracePeriodSeconds: 330
|
||||
volumes: []
|
||||
---
|
||||
# Source: coder-ai-gateway/templates/ingress.yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: coder-ai-gateway
|
||||
namespace: default
|
||||
labels:
|
||||
helm.sh/chart: coder-ai-gateway-0.1.0
|
||||
app.kubernetes.io/name: coder-ai-gateway
|
||||
app.kubernetes.io/instance: ai-gateway
|
||||
app.kubernetes.io/part-of: coder-ai-gateway
|
||||
app.kubernetes.io/version: "0.1.0"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
spec:
|
||||
rules:
|
||||
- host: "ai.example.com"
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: coder-ai-gateway
|
||||
port:
|
||||
number: 80
|
||||
---
|
||||
# Source: coder-ai-gateway/templates/httproute.yaml
|
||||
apiVersion: gateway.networking.k8s.io/v1
|
||||
kind: HTTPRoute
|
||||
metadata:
|
||||
name: coder-ai-gateway
|
||||
namespace: default
|
||||
labels:
|
||||
helm.sh/chart: coder-ai-gateway-0.1.0
|
||||
app.kubernetes.io/name: coder-ai-gateway
|
||||
app.kubernetes.io/instance: ai-gateway
|
||||
app.kubernetes.io/part-of: coder-ai-gateway
|
||||
app.kubernetes.io/version: "0.1.0"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
spec:
|
||||
parentRefs:
|
||||
- name: shared-gateway
|
||||
rules:
|
||||
- matches:
|
||||
- path:
|
||||
type: PathPrefix
|
||||
value: /
|
||||
backendRefs:
|
||||
- name: coder-ai-gateway
|
||||
port: 80
|
||||
|
||||
@@ -11,3 +11,13 @@ coder:
|
||||
name: ai-gateway-key
|
||||
key: key
|
||||
aigateway: {}
|
||||
# Enable every optional resource with only the values each one requires, so
|
||||
# the golden file covers rendering of all templates without opting into
|
||||
# non-default settings such as service.nodePort.
|
||||
ingress:
|
||||
enable: true
|
||||
host: ai.example.com
|
||||
httproute:
|
||||
enable: true
|
||||
parentRefs:
|
||||
- name: shared-gateway
|
||||
|
||||
Reference in New Issue
Block a user