Files
kamaji/controllers/certificate_lifecycle_controller_metrics_test.go
Patryk Rostkowski 489c191c0b feat: add custom Kamaji metrics and dashboard (#1108)
Signed-off-by: Patryk Rostkowski <patrostkowski@gmail.com>
2026-04-07 18:57:50 +02:00

138 lines
4.7 KiB
Go

// Copyright 2022 Clastix Labs
// SPDX-License-Identifier: Apache-2.0
package controllers
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"testing"
"time"
"github.com/prometheus/client_golang/prometheus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
"github.com/clastix/kamaji/internal/constants"
"github.com/clastix/kamaji/internal/metrics"
"github.com/clastix/kamaji/internal/utilities"
)
func TestCertificateRefreshMetrics(t *testing.T) {
t.Parallel()
scheme := runtime.NewScheme()
if err := kamajiv1alpha1.AddToScheme(scheme); err != nil {
t.Fatalf("failed adding kamaji scheme: %v", err)
}
if err := corev1.AddToScheme(scheme); err != nil {
t.Fatalf("failed adding corev1 scheme: %v", err)
}
validCertPEM, err := testCertificatePEM(time.Now().Add(48 * time.Hour))
if err != nil {
t.Fatalf("failed generating valid cert: %v", err)
}
expiringCertPEM, err := testCertificatePEM(time.Now().Add(30 * time.Minute))
if err != nil {
t.Fatalf("failed generating expiring cert: %v", err)
}
reader := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
&kamajiv1alpha1.TenantControlPlane{ObjectMeta: metav1.ObjectMeta{Name: "tcp-a", Namespace: "default"}},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "cert-valid",
Namespace: "default",
Labels: map[string]string{
constants.ControlPlaneLabelKey: "tcp-a",
constants.ControllerLabelResource: utilities.CertificateX509Label,
},
},
Data: map[string][]byte{"tls.crt": validCertPEM},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "cert-expiring",
Namespace: "default",
Labels: map[string]string{
constants.ControlPlaneLabelKey: "tcp-a",
constants.ControllerLabelResource: utilities.CertificateX509Label,
},
},
Data: map[string][]byte{"tls.crt": expiringCertPEM},
},
&corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "cert-invalid",
Namespace: "default",
Labels: map[string]string{
constants.ControlPlaneLabelKey: "tcp-a",
constants.ControllerLabelResource: utilities.CertificateX509Label,
},
},
Data: map[string][]byte{"tls.crt": []byte("not-a-certificate")},
},
).Build()
registry := prometheus.NewRegistry()
recorder := metrics.NewRecorder(registry)
s := &CertificateLifecycle{
Deadline: 24 * time.Hour,
client: reader,
Metrics: recorder,
}
if err := s.refreshCertificatesMetrics(t.Context()); err != nil {
t.Fatalf("refreshCertificatesMetrics returned error: %v", err)
}
family := mustMetricFamilyFromGatherer(t, registry, "kamaji_certificates_current")
if got := gaugeValueByLabels(t, family, map[string]string{"tcp_namespace": "default", "tcp_name": "tcp-a", "status": metrics.CertificateStatusValid, "strategy": metrics.CertificateStrategyX509}); got != 1 {
t.Fatalf("expected valid/x509 certificates gauge to be 1, got %v", got)
}
if got := gaugeValueByLabels(t, family, map[string]string{"tcp_namespace": "default", "tcp_name": "tcp-a", "status": metrics.CertificateStatusExpiring, "strategy": metrics.CertificateStrategyX509}); got != 1 {
t.Fatalf("expected expiring/x509 certificates gauge to be 1, got %v", got)
}
if got := gaugeValueByLabels(t, family, map[string]string{"tcp_namespace": "default", "tcp_name": "tcp-a", "status": metrics.CertificateStatusInvalid, "strategy": metrics.CertificateStrategyX509}); got != 1 {
t.Fatalf("expected invalid/x509 certificates gauge to be 1, got %v", got)
}
if got := gaugeValueByLabels(t, family, map[string]string{"tcp_namespace": "default", "tcp_name": "tcp-a", "status": metrics.CertificateStatusValid, "strategy": metrics.CertificateStrategyKubeconfig}); got != 0 {
t.Fatalf("expected valid/kubeconfig certificates gauge to be 0, got %v", got)
}
}
func testCertificatePEM(notAfter time.Time) ([]byte, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, err
}
template := &x509.Certificate{
SerialNumber: big.NewInt(1),
Subject: pkix.Name{
CommonName: "metrics-test",
},
NotBefore: time.Now().Add(-time.Minute),
NotAfter: notAfter,
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
derBytes, err := x509.CreateCertificate(rand.Reader, template, template, &privateKey.PublicKey, privateKey)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}), nil
}