From 00a00de6cfe080aca931ba39eb38eeb1c4e943d6 Mon Sep 17 00:00:00 2001 From: nixargh Date: Tue, 17 Dec 2024 18:27:12 +0300 Subject: [PATCH] v0.14.0 Fix CI integration tests for k8s (#7) v0.14.0: - Fixed CI integration tests for k8s - Changed unit tests for both PromQL and MetricsQL - Added 'cmd/sloth/commands/k8scontroller' --victoriametrics flag support --- .github/workflows/ci.yaml | 82 +++++++++---------- CHANGELOG.md | 10 +++ cmd/sloth/commands/k8scontroller.go | 12 +++ internal/prometheus/model_test.go | 24 +++++- scripts/check/unit-test.sh | 2 +- .../k8scontroller/k8scontroller_test.go | 41 +++++++++- 6 files changed, 126 insertions(+), 45 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 161f48f7..fd1b211f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -156,44 +156,44 @@ jobs: VERSION: "${{ steps.extract_tag.outputs.tag }}" run: make build-publish-image-all -# integration-test-k8s: -# name: Integration test Kubernetes -# runs-on: ubuntu-latest -# strategy: -# matrix: -# kubernetes: [1.31.0] -# steps: -# - uses: actions/checkout@v4 -# -# - uses: actions/setup-go@v5 -# with: -# go-version-file: go.mod -# -# - name: Execute tests -# env: -# KIND_VERSION: v0.24.0 -# run: | -# # Get dependencies. -# echo "Installing 'king' & 'kubectl'." -# curl -Lo kind https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-linux-amd64 && chmod +x kind && sudo mv kind /usr/local/bin/ -# curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v${{ matrix.kubernetes }}/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/ -# -# # Start cluster. -# echo -e "\nStarting ${{ matrix.kubernetes }} Kubernetes cluster..." -# kind create cluster --image kindest/node:v${{ matrix.kubernetes }} -# kind get kubeconfig > /tmp/test.kubeconfig -# -# # Register CRDs. -# echo -e "\nCreating our CRDs." -# kubectl apply -f ./pkg/kubernetes/gen/crd/ -# kubectl apply -f ./test/integration/crd -# -# # Build binary. -# echo -e "\nBuilding binary." -# make ci-build -# sudo mv ./bin/sloth /usr/local/bin/ -# -# # Execute integration tests. -# echo -e "\nExecuting integration tests." -# export SLOTH_INTEGRATION_KUBE_CONFIG=/tmp/test.kubeconfig -# make ci-integration-k8s + integration-test-k8s: + name: Integration test Kubernetes + runs-on: ubuntu-latest + strategy: + matrix: + kubernetes: [1.31.0] + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Execute tests + env: + KIND_VERSION: v0.24.0 + run: | + # Get dependencies. + echo "Installing 'king' & 'kubectl'." + curl -Lo kind https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-linux-amd64 && chmod +x kind && sudo mv kind /usr/local/bin/ + curl -Lo kubectl https://storage.googleapis.com/kubernetes-release/release/v${{ matrix.kubernetes }}/bin/linux/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin/ + + # Start cluster. + echo -e "\nStarting ${{ matrix.kubernetes }} Kubernetes cluster..." + kind create cluster --image kindest/node:v${{ matrix.kubernetes }} + kind get kubeconfig > /tmp/test.kubeconfig + + # Register CRDs. + echo -e "\nCreating our CRDs." + kubectl apply -f ./pkg/kubernetes/gen/crd/ + kubectl apply -f ./test/integration/crd + + # Build binary. + echo -e "\nBuilding binary." + make ci-build + sudo mv ./bin/sloth /usr/local/bin/ + + # Execute integration tests. + echo -e "\nExecuting integration tests." + export SLOTH_INTEGRATION_KUBE_CONFIG=/tmp/test.kubeconfig + make ci-integration-k8s diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ce5f686..428f5896 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.14.0] - 2024-12-17 +### Fixed +- `CI` integration tests for k8s. + +### Changed +- Run unit tests for both **PromQL** and **MetricsQL**. + +### Added +- `cmd/sloth/commands/k8scontroller` add **--victoriametrics** flag support. + ## [0.13.1] - 2024-12-16 ### Changed - Update dependencies versions a bit further. diff --git a/cmd/sloth/commands/k8scontroller.go b/cmd/sloth/commands/k8scontroller.go index 306f0bf9..017d07d8 100644 --- a/cmd/sloth/commands/k8scontroller.go +++ b/cmd/sloth/commands/k8scontroller.go @@ -69,6 +69,7 @@ type kubeControllerCommand struct { sloPeriodWindowsPath string sloPeriod string disableOptimizedRules bool + useVictoriaMetrics bool } // NewKubeControllerCommand returns the Kubernetes controller command. @@ -97,6 +98,8 @@ func NewKubeControllerCommand(app *kingpin.Application) Command { cmd.Flag("default-slo-period", "The default SLO period windows to be used for the SLOs.").Default("30d").StringVar(&c.sloPeriod) cmd.Flag("disable-optimized-rules", "If enabled it will disable optimized generated rules.").BoolVar(&c.disableOptimizedRules) + cmd.Flag("victoriametrics", "Use VictoriaMetrics parser for expressions validation.").Short('v').BoolVar(&c.useVictoriaMetrics) + return c } @@ -304,12 +307,21 @@ func (k kubeControllerCommand) Run(ctx context.Context, config RootConfig) error sliRuleGen = prometheus.SLIRecordingRulesGenerator } + // Choose Validator. + var validator prometheus.Validator + if k.useVictoriaMetrics { + validator.MetricsQL = true + } else { + validator.PromQL = true + } + // Create the generate app service (the one that the CLIs use). generator, err := generate.NewService(generate.ServiceConfig{ AlertGenerator: alert.NewGenerator(windowsRepo), SLIRecordingRulesGenerator: sliRuleGen, MetaRecordingRulesGenerator: prometheus.MetadataRecordingRulesGenerator, SLOAlertRulesGenerator: prometheus.SLOAlertRulesGenerator, + Validator: validator, Logger: generatorLogger{Logger: logger}, }) if err != nil { diff --git a/internal/prometheus/model_test.go b/internal/prometheus/model_test.go index 62ff8b92..bd9fd124 100644 --- a/internal/prometheus/model_test.go +++ b/internal/prometheus/model_test.go @@ -1,6 +1,7 @@ package prometheus_test import ( + "fmt" "testing" "time" @@ -61,7 +62,6 @@ func getGoodSLOGroup() prometheus.SLOGroup { func TestModelValidationSpec(t *testing.T) { var validator prometheus.Validator - validator.MetricsQL = true tests := map[string]struct { slo func() prometheus.SLOGroup @@ -450,8 +450,28 @@ func TestModelValidationSpec(t *testing.T) { }, } + validator.PromQL = false + validator.MetricsQL = true + for name, test := range tests { + t.Run(fmt.Sprintf("[MetricsQL] %s", name), func(t *testing.T) { + assert := assert.New(t) + + slo := test.slo() + err := slo.Validate(validator) + + if test.expErrMessage != "" { + assert.Error(err) + assert.Equal(test.expErrMessage, err.Error()) + } else { + assert.NoError(err) + } + }) + } + + validator.PromQL = true + validator.MetricsQL = false for name, test := range tests { - t.Run(name, func(t *testing.T) { + t.Run(fmt.Sprintf("[PromQL] %s", name), func(t *testing.T) { assert := assert.New(t) slo := test.slo() diff --git a/scripts/check/unit-test.sh b/scripts/check/unit-test.sh index b0dfc8bf..ffef6e01 100755 --- a/scripts/check/unit-test.sh +++ b/scripts/check/unit-test.sh @@ -4,4 +4,4 @@ set -o errexit set -o nounset go test -race -coverprofile=.test_coverage.txt $(go list ./... | grep -v /test/integration ) -go tool cover -func=.test_coverage.txt | tail -n1 | awk '{print "Total test coverage: " $3}' \ No newline at end of file +go tool cover -func=.test_coverage.txt | tail -n1 | awk '{print "Total test coverage: " $3}' diff --git a/test/integration/k8scontroller/k8scontroller_test.go b/test/integration/k8scontroller/k8scontroller_test.go index 67d2d65b..f5bfe7fe 100644 --- a/test/integration/k8scontroller/k8scontroller_test.go +++ b/test/integration/k8scontroller/k8scontroller_test.go @@ -202,7 +202,46 @@ func TestKubernetesControllerPromOperatorGenerate(t *testing.T) { for name, test := range tests { test := test - t.Run(name, func(t *testing.T) { + t.Run(fmt.Sprintf("[MetricsQL] %s", name), func(t *testing.T) { + t.Parallel() + require := require.New(t) + + // Create a context with cancel so we can stop everything at the end of the test. + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Create NS and delete on test end. + ns, deleteNS, err := k8scontroller.NewKubernetesNamespace(ctx, kubeClis.Std) + require.NoError(err) + defer func() { + err := deleteNS(ctx) + require.NoError(err) + }() + + // Run controller in background. + go func() { + // Prepare args. + args := []string{ + "--metrics-listen-addr=:0", + "--hot-reload-addr=:0", + "--sli-plugins-path=./", + fmt.Sprintf("--namespace=%s", ns), + fmt.Sprintf("--default-slo-period=%s", test.sloPeriod), + "--victoriametrics", + } + if test.customSLOPeriods { + args = append(args, "--slo-period-windows-path=./windows") + } + + // Listen on `:0` and isolate per namespace so we can run in tests parallel safely. + _, _, _ = k8scontroller.RunSlothController(ctx, config, ns, strings.Join(args, " ")) + }() + + // Execute test. + test.exec(ctx, t, ns, kubeClis) + }) + + t.Run(fmt.Sprintf("[PromQL] %s", name), func(t *testing.T) { t.Parallel() require := require.New(t)