1
0
mirror of https://github.com/coreos/prometheus-operator.git synced 2026-02-05 06:45:27 +01:00

feat: allow UTF-8 characters in label names

Follow-up from #7637 to complete the UTF8 support for labels

Related-to: #7362

Assisted-by: Cursor
Signed-off-by: Jayapriya Pai <slashpai9@gmail.com>
This commit is contained in:
Jayapriya Pai
2025-10-07 00:05:35 +05:30
parent 1936e40708
commit a2e1f38665
26 changed files with 340 additions and 216 deletions

View File

@@ -321,6 +321,7 @@ func testAllNSPrometheus(t *testing.T) {
"PrometheusAgentSSetServiceName": testPrometheusAgentSSetServiceName,
"PrometheusReconciliationOnSecretChanges": testPrometheusReconciliationOnSecretChanges,
"PrometheusUTF8MetricsSupport": testPrometheusUTF8MetricsSupport,
"PrometheusUTF8LabelSupport": testPrometheusUTF8LabelSupport,
}
for name, f := range testFuncs {

View File

@@ -4930,22 +4930,15 @@ func testRelabelConfigCRDValidation(t *testing.T) {
expectedError: true,
},
{
scenario: "empty-source-lbl",
scenario: "accepts-utf-8-labels",
relabelConfigs: []monitoringv1.RelabelConfig{
{
SourceLabels: []monitoringv1.LabelName{""},
SourceLabels: []monitoringv1.LabelName{"app.info"},
Action: "replace",
TargetLabel: "app.info",
Replacement: ptr.To("test.app"),
},
},
expectedError: true,
},
{
scenario: "invalid-source-lbl",
relabelConfigs: []monitoringv1.RelabelConfig{
{
SourceLabels: []monitoringv1.LabelName{"metric%)"},
},
},
expectedError: true,
},
}
@@ -5501,6 +5494,7 @@ func testPrometheusUTF8MetricsSupport(t *testing.T) {
testCtx := framework.NewTestCtx(t)
defer testCtx.Cleanup(t)
ns := framework.CreateNamespace(context.Background(), t, testCtx)
// Disable admission webhook for rule since utf8 is not enabled by default and rule contain metric name with utf8 characters.
ruleNamespaceSelector := map[string]string{"excludeFromWebhook": "true"}
err := framework.AddLabelsToNamespace(context.Background(), ns, ruleNamespaceSelector)
@@ -5720,6 +5714,153 @@ func testPrometheusUTF8MetricsSupport(t *testing.T) {
require.NoError(t, err, "UTF-8 alert rule should be queryable")
}
func testPrometheusUTF8LabelSupport(t *testing.T) {
t.Parallel()
testCtx := framework.NewTestCtx(t)
defer testCtx.Cleanup(t)
ns := framework.CreateNamespace(context.Background(), t, testCtx)
framework.SetupPrometheusRBAC(context.Background(), t, testCtx, ns)
name := "prometheus-utf8-test"
// Create deployment for instrumented sample app
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "instrumented-sample-app",
Namespace: ns,
Labels: map[string]string{
"app": "instrumented-sample-app",
},
},
Spec: appsv1.DeploymentSpec{
Replicas: ptr.To(int32(1)),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app.name": "instrumented-sample-app"},
},
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app.name": "instrumented-sample-app",
},
},
Spec: v1.PodSpec{
Containers: []v1.Container{{
Name: "instrumented-sample-app",
Image: "quay.io/prometheus-operator/instrumented-sample-app:latest",
Ports: []v1.ContainerPort{{
Name: "web",
ContainerPort: 8080,
Protocol: v1.ProtocolTCP,
}},
}},
},
},
},
}
_, err := framework.KubeClient.AppsV1().Deployments(ns).Create(context.Background(), deployment, metav1.CreateOptions{})
require.NoError(t, err)
service := &v1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "utf8-test-service",
Namespace: ns,
Labels: map[string]string{
"app.name": "instrumented-sample-app",
"group": "test.app",
"cluster": "dev",
},
},
Spec: v1.ServiceSpec{
Ports: []v1.ServicePort{{Name: "web", Port: 8080, TargetPort: intstr.FromInt(8080)}},
Selector: map[string]string{"app.name": "instrumented-sample-app"},
},
}
_, err = framework.KubeClient.CoreV1().Services(ns).Create(context.Background(), service, metav1.CreateOptions{})
require.NoError(t, err)
sm := &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "utf8-servicemonitor",
Namespace: ns,
Labels: map[string]string{"group": "test.app", "app.name": "instrumented-sample-app"},
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{"app.name": "instrumented-sample-app"},
},
Endpoints: []monitoringv1.Endpoint{{
Port: "web",
Interval: "2s",
RelabelConfigs: []monitoringv1.RelabelConfig{{
SourceLabels: []monitoringv1.LabelName{"__meta_kubernetes_service_label_cluster"},
TargetLabel: "service_clustér_label",
Action: "replace",
}},
BasicAuth: &monitoringv1.BasicAuth{
Username: v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{Name: "basic-auth"},
Key: "username",
},
Password: v1.SecretKeySelector{
LocalObjectReference: v1.LocalObjectReference{Name: "basic-auth"},
Key: "password",
},
},
}},
},
}
secret := &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "basic-auth",
Namespace: ns,
},
Type: v1.SecretTypeOpaque,
StringData: map[string]string{
"username": "user",
"password": "pass",
},
}
_, err = framework.KubeClient.CoreV1().Secrets(ns).Create(context.Background(), secret, metav1.CreateOptions{})
require.NoError(t, err)
_, err = framework.MonClientV1.ServiceMonitors(ns).Create(context.Background(), sm, metav1.CreateOptions{})
require.NoError(t, err)
err = framework.WaitForDeploymentReady(context.Background(), ns, "instrumented-sample-app", 1)
require.NoError(t, err)
prom := framework.MakeBasicPrometheus(ns, name, "test.app", 1)
_, err = framework.CreatePrometheusAndWaitUntilReady(context.Background(), ns, prom)
require.NoError(t, err)
// Default Prometheus service name is "prometheus-operated".
promSvcName := "prometheus-operated"
// Wait for the instrumented-sample-app target to be discovered
err = framework.WaitForHealthyTargets(context.Background(), ns, promSvcName, 1)
require.NoError(t, err)
// Verify UTF8 labels work in queries.
err = wait.PollUntilContextTimeout(context.Background(), 5*time.Second, 2*time.Minute, false, func(ctx context.Context) (bool, error) {
results, err := framework.PrometheusQuery(ns, promSvcName, "http", `{"service_clustér_label"="dev"}`)
if err != nil {
t.Logf("UTF8 label query failed: %v", err)
return false, nil
}
if len(results) == 0 {
t.Logf("UTF8 label query returned no results")
return false, nil
}
return true, nil
})
require.NoError(t, err, "UTF-8 label queries should work in Prometheus 3.0+ queries")
}
func isAlertmanagerDiscoveryWorking(ns, promSVCName, alertmanagerName string) func(ctx context.Context) (bool, error) {
return func(ctx context.Context) (bool, error) {
pods, err := framework.KubeClient.CoreV1().Pods(ns).List(