Skip to content
Draft
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
32 changes: 24 additions & 8 deletions lib/steps/helm_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,29 @@ func awsHelmLoki(ctx *pulumi.Context, k8sOpt pulumi.ResourceOption, compoundName
withAlias("kubernetes:helm.cattle.io/v1:HelmChart", resourceName))
}

// grafanaIngressValues builds the Grafana Helm ingress values.
//
// Grafana is routed through traefik-forward-auth only when the main site opts into it.
// The forward-auth middlewares (kube-system-traefik-forward-auth-main and
// -add-forwarded-headers) are created by the clusters step only when a site sets
// use_traefik_forward_auth: true. Adding the annotation unconditionally leaves the
// Grafana ingress referencing a non-existent middleware on workloads that don't enable
// forward-auth, which makes Traefik invalidate the router (HTTP 404). Otherwise Grafana
// authenticates with local accounts and the ingress should route straight through.
func grafanaIngressValues(domain string, sites map[string]types.SiteConfig) map[string]interface{} {
ingress := map[string]interface{}{
"enabled": true,
"hosts": []interface{}{fmt.Sprintf("grafana.%s", domain)},
"path": "/",
}
if mainSite, ok := sites["main"]; ok && mainSite.Spec.UseTraefikForwardAuth {
ingress["annotations"] = map[string]interface{}{
"traefik.ingress.kubernetes.io/router.middlewares": "kube-system-traefik-forward-auth-add-forwarded-headers@kubernetescrd,kube-system-traefik-forward-auth-main@kubernetescrd",
}
}
return ingress
}

func awsHelmGrafana(ctx *pulumi.Context, k8sOpt pulumi.ResourceOption, compoundName, release string,
params awsHelmParams, version string,
withAlias func(string, string) pulumi.ResourceOption) error {
Expand Down Expand Up @@ -936,14 +959,7 @@ func awsHelmGrafana(ctx *pulumi.Context, k8sOpt pulumi.ResourceOption, compoundN
values := map[string]interface{}{
"envFromSecret": "grafana-db-url",
"grafana.ini": iniCfg,
"ingress": map[string]interface{}{
"enabled": true,
"annotations": map[string]interface{}{
"traefik.ingress.kubernetes.io/router.middlewares": "kube-system-traefik-forward-auth-add-forwarded-headers@kubernetescrd,kube-system-traefik-forward-auth-main@kubernetescrd",
},
"hosts": []interface{}{fmt.Sprintf("grafana.%s", domain)},
"path": "/",
},
"ingress": grafanaIngressValues(domain, params.cfg.Sites),
"datasources": map[string]interface{}{
"datasources.yaml": map[string]interface{}{
"apiVersion": 1,
Expand Down
62 changes: 62 additions & 0 deletions lib/steps/helm_aws_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package steps

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/posit-dev/ptd/lib/types"
)

const grafanaForwardAuthMiddlewares = "kube-system-traefik-forward-auth-add-forwarded-headers@kubernetescrd,kube-system-traefik-forward-auth-main@kubernetescrd"

func TestGrafanaIngressValues(t *testing.T) {
t.Run("main site opts into forward-auth adds annotation", func(t *testing.T) {
sites := map[string]types.SiteConfig{
"main": {Spec: types.SiteConfigSpec{UseTraefikForwardAuth: true}},
}

ingress := grafanaIngressValues("example.com", sites)

annotations, ok := ingress["annotations"].(map[string]interface{})
assert.True(t, ok, "expected annotations to be present")
assert.Equal(t, grafanaForwardAuthMiddlewares, annotations["traefik.ingress.kubernetes.io/router.middlewares"])
})

t.Run("main site with forward-auth disabled has no annotation", func(t *testing.T) {
sites := map[string]types.SiteConfig{
"main": {Spec: types.SiteConfigSpec{UseTraefikForwardAuth: false}},
}

ingress := grafanaIngressValues("example.com", sites)

_, hasAnnotations := ingress["annotations"]
assert.False(t, hasAnnotations, "expected no annotations when forward-auth disabled")
})

t.Run("no main site has no annotation", func(t *testing.T) {
sites := map[string]types.SiteConfig{
"other": {Spec: types.SiteConfigSpec{UseTraefikForwardAuth: true}},
}

ingress := grafanaIngressValues("example.com", sites)

_, hasAnnotations := ingress["annotations"]
assert.False(t, hasAnnotations, "expected no annotations when no main site is present")
})

t.Run("nil sites map has no annotation", func(t *testing.T) {
ingress := grafanaIngressValues("example.com", nil)

_, hasAnnotations := ingress["annotations"]
assert.False(t, hasAnnotations, "expected no annotations when sites map is nil")
})

t.Run("basic ingress values", func(t *testing.T) {
ingress := grafanaIngressValues("example.com", nil)

assert.Equal(t, true, ingress["enabled"])
assert.Equal(t, []interface{}{"grafana.example.com"}, ingress["hosts"])
assert.Equal(t, "/", ingress["path"])
})
}
Loading