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
11 changes: 11 additions & 0 deletions build/templates/applications/helm-chart/kubernetes/README.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ A Helm chart for Kubernetes
| image.repository | string | `"{{.Name}}"` | |
| image.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
| imagePullSecrets[0].name | string | `"regcred"` | |
{{- if eq .IngressController "envoy" }}
| httproute.annotations | object | `{}` | |
| httproute.dnsWildcard | string | `"{{.DnsWildcard}}"` | |
| httproute.enabled | bool | `false` | |
| httproute.gateway.name | string | `"{{.GatewayName}}"` | |
| httproute.gateway.namespace | string | `"{{.GatewayNamespace}}"` | |
| httproute.hosts[0].host | string | `"edpDefault"` | |
| httproute.hosts[0].paths[0].path | string | `"/"` | |
| httproute.hosts[0].paths[0].pathType | string | `"PathPrefix"` | |
{{- else }}
| ingress.annotations | object | `{}` | |
| ingress.className | string | `""` | |
| ingress.dnsWildcard | string | `"{{.DnsWildcard}}"` | |
Expand All @@ -39,6 +49,7 @@ A Helm chart for Kubernetes
| ingress.hosts[0].paths[0].path | string | `"/"` | |
| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | |
| ingress.tls | list | `[]` | |
{{- end }}
| livenessProbe.tcpSocket.port | string | `"http"` | |
| nameOverride | string | `""` | |
| nodeSelector | object | `{}` | https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{{- if and (hasKey .Values "httproute") .Values.httproute.enabled -}}
{{- $fullName := include "REPLACE_IT.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- $top := . -}}
{{- range $i, $host := .Values.httproute.hosts }}
{{- if $i }}
---
{{- end }}
# Gateway API rules cannot carry a hostname, so each host gets its own HTTPRoute
# to keep path matches scoped to that host (mirrors the per-host rules of an Ingress).
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ $fullName }}{{ if $i }}-{{ $i }}{{ end }}
labels:
{{- include "REPLACE_IT.labels" $top | nindent 4 }}
{{- with $top.Values.httproute.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
parentRefs:
- name: {{ $top.Values.httproute.gateway.name }}
namespace: {{ $top.Values.httproute.gateway.namespace }}
{{- with $top.Values.httproute.gateway.sectionName }}
sectionName: {{ . }}
{{- end }}
hostnames:
{{- if eq $host.host "edpDefault" }}
- {{ $fullName }}-{{ $top.Release.Namespace }}.{{ $top.Values.httproute.dnsWildcard }}
{{- else }}
- {{ $host.host | quote }}
{{- end }}
rules:
- matches:
{{- range $host.paths }}
- path:
type: {{ .pathType | default "PathPrefix" }}
value: {{ .path }}
{{- end }}
backendRefs:
- name: {{ $fullName }}
port: {{ $svcPort }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
{{- if .Values.ingress.enabled -}}
{{- if and (hasKey .Values "ingress") .Values.ingress.enabled -}}
{{- $fullName := include "REPLACE_IT.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
{{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
{{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
{{- end }}
{{- end }}
{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}
Expand All @@ -23,8 +12,8 @@ metadata:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
ingressClassName: {{ .Values.ingress.className }}
{{- with .Values.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
Expand All @@ -38,9 +27,6 @@ spec:
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
# if .host = edpDefault then we need to use
# {{ $fullName }}-{{ $.Release.Namespace }}.{{ $.Values.ingress.dnsWildcard }}
# otherwise we need to use {{ .host }}
{{- if eq .host "edpDefault" }}
- host: {{ $fullName }}-{{ $.Release.Namespace }}.{{ $.Values.ingress.dnsWildcard }}
{{- else }}
Expand All @@ -50,19 +36,12 @@ spec:
paths:
{{- range .paths }}
- path: {{ .path }}
{{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
pathType: {{ .pathType }}
{{- end }}
backend:
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
service:
name: {{ $fullName }}
port:
number: {{ $svcPort }}
{{- else }}
serviceName: {{ $fullName }}
servicePort: {{ $svcPort }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
33 changes: 33 additions & 0 deletions build/templates/applications/helm-chart/kubernetes/values.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,38 @@ service:
type: ClusterIP
port: 8080

{{- if eq .IngressController "envoy" }}
# Expose the application via a Gateway API HTTPRoute on the shared Envoy Gateway.
httproute:
enabled: false
dnsWildcard: {{.DnsWildcard}}
# -- Parent Gateway the HTTPRoute attaches to. Defaults to the platform gateway.
gateway:
name: {{.GatewayName}}
namespace: {{.GatewayNamespace}}
# -- Optional Gateway listener to bind to (e.g. an HTTPS listener that terminates TLS).
# sectionName: ""
# Each entry below is rendered as its own HTTPRoute, so paths stay scoped to their host.
# 'edpDefault' expands to <CODEBASE_NAME>-<CODEBASE_NAMESPACE>.<CLUSTER_DNS_WILDCARD>; set a literal host to override.
hosts:
- host: edpDefault
paths:
- path: /
pathType: PathPrefix
# Example — expose two custom hosts, each with its own paths (renders two HTTPRoutes):
# hosts:
# - host: api.example.com
# paths:
# - path: /v1
# pathType: PathPrefix
# - path: /v2
# pathType: PathPrefix
# - host: web.example.com
# paths:
# - path: /
# pathType: PathPrefix
annotations: {}
{{- else }}
ingress:
enabled: false
dnsWildcard: {{.DnsWildcard}}
Expand All @@ -63,6 +95,7 @@ ingress:
# - secretName: chart-example-tls
# hosts:
# - chart-example.local
{{- end }}

resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
Expand Down
13 changes: 8 additions & 5 deletions controllers/codebase/service/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,14 @@ func buildTemplateConfig(
}

cf := model.ConfigGoTemplating{
Name: cb.Name,
PlatformType: platform.GetPlatformType(),
Lang: cb.Spec.Lang,
DnsWildcard: conf.DnsWildcard,
Framework: cb.Spec.Framework,
Name: cb.Name,
PlatformType: platform.GetPlatformType(),
Lang: cb.Spec.Lang,
DnsWildcard: conf.DnsWildcard,
Framework: cb.Spec.Framework,
IngressController: platform.GetIngressControllerType(),
GatewayName: platform.GatewayName(),
GatewayNamespace: platform.GatewayNamespace(),
}

cf.GitURL, err = getProjectUrl(c, &cb.Spec, cb.Namespace)
Expand Down
5 changes: 5 additions & 0 deletions pkg/model/gerrit_config_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ type ConfigGoTemplating struct {
DnsWildcard string
Framework string
GitURL string
// IngressController selects the scaffolded exposure: "nginx" -> Ingress, "envoy" -> HTTPRoute.
IngressController string
// GatewayName/GatewayNamespace target the parent Gateway; used only when IngressController is "envoy".
GatewayName string
GatewayNamespace string
}
9 changes: 9 additions & 0 deletions pkg/platform/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ func IsEnvoy() bool {
return os.Getenv(IngressControllerEnv) == IngressControllerEnvoy
}

// GetIngressControllerType returns the ingress controller type, defaulting to nginx for backward compatibility.
func GetIngressControllerType() string {
if IsEnvoy() {
return IngressControllerEnvoy
}

return IngressControllerNginx
}

// GatewayName returns the name of the parent Gateway API Gateway resource.
func GatewayName() string {
return os.Getenv(GatewayNameEnv)
Expand Down
14 changes: 14 additions & 0 deletions pkg/platform/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ func TestIsEnvoy_DefaultFalse(t *testing.T) {
}
}

func TestGetIngressControllerType_Envoy(t *testing.T) {
t.Setenv(IngressControllerEnv, IngressControllerEnvoy)

if GetIngressControllerType() != IngressControllerEnvoy {
t.Error("envoy should be reported when INGRESS_CONTROLLER_TYPE is envoy")
}
}

func TestGetIngressControllerType_DefaultNginx(t *testing.T) {
if GetIngressControllerType() != IngressControllerNginx {
t.Error("nginx should be the default ingress controller when INGRESS_CONTROLLER_TYPE is unset")
}
}

func TestGatewayName(t *testing.T) {
t.Setenv(GatewayNameEnv, "main-gateway")

Expand Down
82 changes: 82 additions & 0 deletions pkg/util/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,88 @@ func TestCopyTemplate_HelmTemplates_ShouldPass(t *testing.T) {
assert.Contains(t, string(b), "home: https://example.com")
}

// TestCopyTemplate_HelmTemplates_ExposureByController checks that the gateway selection
// configures the matching exposure in values.yaml, while both exposure templates are always
// shipped (each gated by its own values block, so the unselected one stays inert).
func TestCopyTemplate_HelmTemplates_ExposureByController(t *testing.T) {
t.Parallel()

tests := []struct {
name string
cf *model.ConfigGoTemplating
wantValues []string
absentValues []string
}{
{
name: "nginx renders ingress block",
cf: &model.ConfigGoTemplating{
Name: "c-name",
PlatformType: "kubernetes",
Lang: "go",
DnsWildcard: "mydomain.example.com",
GitURL: "https://example.com",
IngressController: "nginx",
},
wantValues: []string{"ingress:", "dnsWildcard: mydomain.example.com"},
absentValues: []string{"httproute:"},
},
{
name: "envoy renders httproute block wired to the gateway",
cf: &model.ConfigGoTemplating{
Name: "c-name",
PlatformType: "kubernetes",
Lang: "go",
DnsWildcard: "mydomain.example.com",
GitURL: "https://example.com",
IngressController: "envoy",
GatewayName: "main-gateway",
GatewayNamespace: "envoy-gateway-system",
},
wantValues: []string{
"httproute:",
"name: main-gateway",
"namespace: envoy-gateway-system",
"dnsWildcard: mydomain.example.com",
},
absentValues: []string{"\ningress:"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

testDir := t.TempDir()

err := CopyTemplate(
ctrl.LoggerInto(context.Background(), logr.Discard()),
HelmChartDeploymentScriptType,
testDir,
"../../build",
tt.cf,
)
require.NoError(t, err)

values, err := os.ReadFile(fmt.Sprintf("%v/deploy-templates/values.yaml", testDir))
require.NoError(t, err)

for _, want := range tt.wantValues {
assert.Contains(t, string(values), want)
}

for _, absent := range tt.absentValues {
assert.NotContains(t, string(values), absent)
}

// Both exposure templates always ship; each is gated by its own values block.
for _, f := range []string{"ingress.yaml", "httproute.yaml"} {
_, err = os.Stat(fmt.Sprintf("%v/deploy-templates/templates/%s", testDir, f))
require.NoError(t, err, "%s should always be shipped", f)
}
})
}
}

func TestCopyTemplate_HelmTemplates_DirectoryExists(t *testing.T) {
t.Parallel()

Expand Down
Loading