Skip to content

Commit 150c086

Browse files
committed
feat: Configure Prometheus endpoint via Helm chart (#4562)
Add PrometheusEndpoint to backend config and API - Update frontend to use configured endpoint for Prometheus plugin - Add config.prometheus.endpoint to Helm chart values - Use safe quoting for Helm value injection - Add backend validation for Prometheus URL Signed-off-by: zyzzmohit <mohitray949@gmail.com>
1 parent 51c2b8b commit 150c086

File tree

11 files changed

+163
-24
lines changed

11 files changed

+163
-24
lines changed

backend/cmd/headlamp.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ const (
9797
type clientConfig struct {
9898
Clusters []Cluster `json:"clusters"`
9999
IsDynamicClusterEnabled bool `json:"isDynamicClusterEnabled"`
100+
PrometheusEndpoint string `json:"prometheusEndpoint"`
100101
}
101102

102103
type OauthConfig struct {
@@ -1750,7 +1751,7 @@ func parseClusterFromKubeConfig(kubeConfigs []string) ([]Cluster, []error) {
17501751
func (c *HeadlampConfig) getConfig(w http.ResponseWriter, r *http.Request) {
17511752
w.Header().Set("Content-Type", "application/json")
17521753

1753-
clientConfig := clientConfig{c.getClusters(), c.EnableDynamicClusters}
1754+
clientConfig := clientConfig{c.getClusters(), c.EnableDynamicClusters, c.PrometheusEndpoint}
17541755

17551756
if err := json.NewEncoder(w).Encode(&clientConfig); err != nil {
17561757
logger.Log(logger.LevelError, nil, err, "encoding config")

backend/cmd/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ func buildHeadlampCFG(conf *config.Config, kubeConfigStore kubeconfig.ContextSto
101101
TLSCertPath: conf.TLSCertPath,
102102
TLSKeyPath: conf.TLSKeyPath,
103103
SessionTTL: conf.SessionTTL,
104+
PrometheusEndpoint: *conf.PrometheusEndpoint,
104105
}
105106
}
106107

backend/cmd/stateless.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func (c *HeadlampConfig) parseKubeConfig(w http.ResponseWriter, r *http.Request)
178178
return
179179
}
180180

181-
clientConfig := clientConfig{contexts, c.EnableDynamicClusters}
181+
clientConfig := clientConfig{contexts, c.EnableDynamicClusters, c.PrometheusEndpoint}
182182

183183
if err := json.NewEncoder(w).Encode(&clientConfig); err != nil {
184184
logger.Log(logger.LevelError, nil, err, "encoding config")

backend/pkg/config/config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type Config struct {
8585
// TLS config
8686
TLSCertPath string `koanf:"tls-cert-path"`
8787
TLSKeyPath string `koanf:"tls-key-path"`
88+
PrometheusEndpoint *string `koanf:"prometheus-endpoint"`
8889
}
8990

9091
func (c *Config) Validate() error {
@@ -144,6 +145,12 @@ func (c *Config) Validate() error {
144145
}
145146
}
146147

148+
if c.PrometheusEndpoint != nil && *c.PrometheusEndpoint != "" {
149+
if !strings.HasPrefix(*c.PrometheusEndpoint, "http://") && !strings.HasPrefix(*c.PrometheusEndpoint, "https://") {
150+
return errors.New("prometheus-endpoint must start with http:// or https://")
151+
}
152+
}
153+
147154
return nil
148155
}
149156

@@ -448,6 +455,7 @@ func addGeneralFlags(f *flag.FlagSet) {
448455
f.Uint("port", defaultPort, "Port to listen from")
449456
f.String("proxy-urls", "", "Allow proxy requests to specified URLs")
450457
f.Bool("enable-helm", false, "Enable Helm operations")
458+
f.String("prometheus-endpoint", "", "Prometheus endpoint for the cluster")
451459
}
452460

453461
func addOIDCFlags(f *flag.FlagSet) {

backend/pkg/headlampconfig/headlampConfig.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,5 @@ type HeadlampCFG struct {
6363
TLSCertPath string
6464
TLSKeyPath string
6565
SessionTTL int
66+
PrometheusEndpoint string
6667
}

backend/pkg/kubeconfig/kubeconfig_test.go

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"path/filepath"
1111
"testing"
1212

13-
"github.com/kubernetes-sigs/headlamp/backend/pkg/config"
1413
"github.com/kubernetes-sigs/headlamp/backend/pkg/kubeconfig"
1514
"github.com/pkg/errors"
1615
"github.com/stretchr/testify/assert"
@@ -315,11 +314,44 @@ func createTempKubeconfig(t *testing.T, content string) string {
315314
}
316315

317316
func TestContext(t *testing.T) {
318-
kubeConfigFile := config.GetDefaultKubeConfigPath()
317+
// Start a mock server
318+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
319+
if r.URL.Path == "/version" {
320+
w.Header().Set("Content-Type", "application/json")
321+
_, _ = w.Write([]byte(`{"major": "1", "minor": "20"}`))
322+
return
323+
}
324+
w.WriteHeader(http.StatusNotFound)
325+
}))
326+
defer server.Close()
327+
328+
// Create a temp kubeconfig pointing to the mock server
329+
kubeConfigContent := fmt.Sprintf(`apiVersion: v1
330+
clusters:
331+
- cluster:
332+
server: %s
333+
insecure-skip-tls-verify: true
334+
name: minikube
335+
contexts:
336+
- context:
337+
cluster: minikube
338+
namespace: default
339+
user: minikube
340+
name: minikube
341+
current-context: minikube
342+
kind: Config
343+
users:
344+
- name: minikube
345+
user:
346+
token: test-token
347+
`, server.URL)
348+
349+
tempFile := createTempKubeconfig(t, kubeConfigContent)
350+
defer os.Remove(tempFile)
319351

320352
configStore := kubeconfig.NewContextStore()
321353

322-
err := kubeconfig.LoadAndStoreKubeConfigs(configStore, kubeConfigFile, kubeconfig.KubeConfig, nil)
354+
err := kubeconfig.LoadAndStoreKubeConfigs(configStore, tempFile, kubeconfig.KubeConfig, nil)
323355
require.NoError(t, err)
324356

325357
testContext, err := configStore.GetContext("minikube")
@@ -342,6 +374,11 @@ func TestContext(t *testing.T) {
342374

343375
err = testContext.ProxyRequest(rr, request)
344376
require.NoError(t, err)
377+
// We need to flush the proxy response to the recorder
378+
if f, ok := rr.Result().Body.(http.Flusher); ok {
379+
f.Flush()
380+
}
381+
345382
assert.Equal(t, http.StatusOK, rr.Code)
346383

347384
t.Logf("Proxy request Response: %s", rr.Body.String())

charts/headlamp/templates/deployment.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ spec:
319319
{{- with .Values.config.baseURL }}
320320
- "-base-url={{ . }}"
321321
{{- end }}
322+
{{- with .Values.config.prometheus.endpoint }}
323+
- "-prometheus-endpoint={{ . | quote }}"
324+
{{- end }}
322325
{{- with .Values.config.tlsCertPath }}
323326
- "-tls-cert-path={{ . }}"
324327
{{- end }}

charts/headlamp/values.yaml

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ config:
3838
baseURL: ""
3939
# -- session token TTL in seconds (default is 24 hours)
4040
sessionTTL: 86400
41+
prometheus:
42+
# -- Prometheus endpoint for the cluster
43+
endpoint: ""
4144
oidc:
4245
# Option 1:
4346
# @param config.oidc.secret - OIDC secret configuration
@@ -161,8 +164,7 @@ podLabels: {}
161164
hostUsers: true
162165

163166
# -- Headlamp pod's Security Context
164-
podSecurityContext:
165-
{}
167+
podSecurityContext: {}
166168
# fsGroup: 2000
167169

168170
# -- Headlamp containers Security Context
@@ -184,7 +186,6 @@ securityContext:
184186
# drop:
185187
# - ALL
186188

187-
188189
service:
189190
# -- Annotations to add to the service
190191
annotations: {}
@@ -211,8 +212,7 @@ persistentVolumeClaim:
211212
# -- Enable Persistent Volume Claim
212213
enabled: false
213214
# -- Annotations to add to the persistent volume claim (if enabled)
214-
annotations:
215-
{}
215+
annotations: {}
216216
# -- accessModes for the persistent volume claim, eg: ReadWriteOnce, ReadOnlyMany, ReadWriteMany etc.
217217
accessModes: []
218218
# -- size of the persistent volume claim, eg: 10Gi. Required if enabled is true.
@@ -228,8 +228,7 @@ ingress:
228228
# -- Enable ingress controller resource
229229
enabled: false
230230
# -- Annotations for Ingress resource
231-
annotations:
232-
{}
231+
annotations: {}
233232
# kubernetes.io/tls-acme: "true"
234233

235234
# -- Additional labels to add to the Ingress resource
@@ -242,8 +241,7 @@ ingress:
242241

243242
# -- Hostname(s) for the Ingress resource
244243
# Please refer to https://kubernetes.io/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec for more information.
245-
hosts:
246-
[]
244+
hosts: []
247245
# - host: chart-example.local
248246
# paths:
249247
# - path: /
@@ -288,8 +286,7 @@ httpRoute:
288286
# port: 80
289287

290288
# -- CPU/Memory resource requests/limits
291-
resources:
292-
{}
289+
resources: {}
293290
# We usually recommend not to specify default resources and to leave this as a conscious
294291
# choice for the user. This also increases chances charts run on environments with little
295292
# resources, such as Minikube. If you do want to specify resources, uncomment the following
@@ -353,8 +350,7 @@ pluginsManager:
353350
# cpu: "1000m"
354351
# memory: "4096Mi"
355352
# If omitted, the plugin manager will inherit the global securityContext
356-
securityContext:
357-
{}
353+
securityContext: {}
358354
# runAsUser: 1001
359355
# runAsNonRoot: true
360356
# allowPrivilegeEscalation: false

0 commit comments

Comments
 (0)