From ef0ed00e1a4d5f55de8bafe26dda2d9c976205c4 Mon Sep 17 00:00:00 2001 From: Gianluca Mardente Date: Mon, 17 Aug 2026 15:27:06 +0200 Subject: [PATCH] chore: Pass validate health Jobs to sveltos-applier --- .devcontainer/devcontainer.json | 2 +- .github/workflows/codeql.yaml | 6 +- .github/workflows/main.yaml | 18 ++--- Dockerfile | 2 +- Dockerfile_WithGit | 2 +- api/v1beta1/zz_generated.deepcopy.go | 5 +- controllers/handlers_helm.go | 11 ++- controllers/handlers_kustomize.go | 26 +++++-- controllers/handlers_resources.go | 31 ++++++-- controllers/handlers_utils.go | 35 ++++++++- go.mod | 32 ++++---- go.sum | 60 +++++++-------- hack/tools/go.mod | 2 +- lib/clusterops/jobhealthcheck_default.go | 10 ++- lib/clusterops/validate_health.go | 93 +++++++++++++++++++++++- 15 files changed, 247 insertions(+), 88 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 96bf58c6..df9b8fd6 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,7 @@ "dockerfile": "${localWorkspaceFolder}/.devcontainer/Dockerfile", "context": "${localWorkspaceFolder}", "args": { - "GO_VERSION": "1.26.5", + "GO_VERSION": "1.26.6", "KUBECTX_VERSION": "0.9.5", "SVELTOSCTL_VERSION": "0.53.0" } diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index 470b5870..571d0222 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -33,10 +33,10 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: Initialize CodeQL - uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 with: languages: ${{ matrix.language }} @@ -46,6 +46,6 @@ jobs: run: go build ./... - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 + uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 with: category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 4fc5d261..9037ee66 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -17,7 +17,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: Build run: make build - name: FMT @@ -36,7 +36,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: ut run: make test env: @@ -49,7 +49,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: fv run: make create-cluster fv env: @@ -62,7 +62,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: fv run: make create-cluster new-fv env: @@ -75,7 +75,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: fv-sharding run: make create-cluster fv-sharding env: @@ -88,7 +88,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: fv-agentless run: make create-cluster fv-agentless env: @@ -101,7 +101,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: fv-pullmode run: make create-cluster-pullmode fv-pullmode env: @@ -114,7 +114,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: new-fv-pullmode run: make create-cluster-pullmode new-fv-pullmode env: @@ -127,7 +127,7 @@ jobs: - name: Set up Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: - go-version: 1.26.5 + go-version: 1.26.6 - name: fv run: make create-cluster-infra fv-namespace env: diff --git a/Dockerfile b/Dockerfile index 2b10151c..0783d6df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.26.5@sha256:3aff6657219a4d9c14e27fb1d8976c49c29fddb70ba835014f477e1c70636647 AS builder +FROM golang:1.26.6 AS builder ARG BUILDOS ARG TARGETARCH diff --git a/Dockerfile_WithGit b/Dockerfile_WithGit index 19bd2aa1..defc76f7 100644 --- a/Dockerfile_WithGit +++ b/Dockerfile_WithGit @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.26.5@sha256:3aff6657219a4d9c14e27fb1d8976c49c29fddb70ba835014f477e1c70636647 AS builder +FROM golang:1.26.6 AS builder ARG BUILDOS ARG TARGETARCH diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index ae5338bc..c6e84b84 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -21,12 +21,11 @@ limitations under the License. package v1beta1 import ( + apiv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/intstr" - - apiv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/controllers/handlers_helm.go b/controllers/handlers_helm.go index 80d493cc..9949abe1 100644 --- a/controllers/handlers_helm.go +++ b/controllers/handlers_helm.go @@ -426,7 +426,10 @@ func undeployHelmChartsInPullMode(ctx context.Context, c client.Client, clusterS if err != nil { return err } - setters := prepareSetters(clusterSummary, libsveltosv1beta1.FeatureHelm, profileRef, nil, false, true) + setters, err := prepareSetters(ctx, clusterSummary, libsveltosv1beta1.FeatureHelm, profileRef, nil, false, true, logger) + if err != nil { + return err + } // If charts have pre/post delete hooks, those need to be deployed. A ConfigurationGroup to deploy those // is created. If this does not exist yet assume we still have to deploy those. @@ -5777,7 +5780,11 @@ func commitStagedResourcesForDeployment(ctx context.Context, clusterSummary *con } // if a stale helm release is being deleted, run the pre/post delete checks - setters := prepareSetters(clusterSummary, libsveltosv1beta1.FeatureHelm, profileRef, configurationHash, includeDeployChecks, len(staleReleases) != 0) + setters, err := prepareSetters(ctx, clusterSummary, libsveltosv1beta1.FeatureHelm, profileRef, configurationHash, + includeDeployChecks, len(staleReleases) != 0, logger) + if err != nil { + return err + } // Commit deployment return pullmode.CommitStagedResourcesForDeployment(ctx, getManagementClusterClient(), clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, configv1beta1.ClusterSummaryKind, diff --git a/controllers/handlers_kustomize.go b/controllers/handlers_kustomize.go index 6824c384..d188e964 100644 --- a/controllers/handlers_kustomize.go +++ b/controllers/handlers_kustomize.go @@ -229,13 +229,7 @@ func processKustomizeDeployment(ctx context.Context, remoteRestConfig *rest.Conf } if isPullMode { - setters := prepareSetters(clusterSummary, libsveltosv1beta1.FeatureKustomize, profileRef, - configurationHash, true, false) - err = pullmode.CommitStagedResourcesForDeployment(ctx, c, - clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, configv1beta1.ClusterSummaryKind, - clusterSummary.Name, string(libsveltosv1beta1.FeatureKustomize), - logger, setters...) - if err != nil { + if err := commitPullModeKustomizeStaging(ctx, c, clusterSummary, profileRef, configurationHash, logger); err != nil { return err } @@ -254,6 +248,24 @@ func processKustomizeDeployment(ctx context.Context, remoteRestConfig *rest.Conf clusterSummary.Spec.ClusterProfileSpec.ValidateHealths, libsveltosv1beta1.FeatureKustomize, false, logger) } +// commitPullModeKustomizeStaging prepares the ConfigurationGroup setters (including any +// resolved JobCheck manifests, see prepareSetters) and commits the staged Kustomize resources +// for sveltos-applier to pick up. +func commitPullModeKustomizeStaging(ctx context.Context, c client.Client, clusterSummary *configv1beta1.ClusterSummary, + profileRef *corev1.ObjectReference, configurationHash []byte, logger logr.Logger) error { + + setters, err := prepareSetters(ctx, clusterSummary, libsveltosv1beta1.FeatureKustomize, profileRef, + configurationHash, true, false, logger) + if err != nil { + return err + } + + return pullmode.CommitStagedResourcesForDeployment(ctx, c, + clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, configv1beta1.ClusterSummaryKind, + clusterSummary.Name, string(libsveltosv1beta1.FeatureKustomize), + logger, setters...) +} + func cleanStaleKustomizeResources(ctx context.Context, clusterSummary *configv1beta1.ClusterSummary, localResourceReports, remoteResourceReports []libsveltosv1beta1.ResourceReport, logger logr.Logger, ) (localUndeployed, remoteUndeployed []libsveltosv1beta1.ResourceReport, err error) { diff --git a/controllers/handlers_resources.go b/controllers/handlers_resources.go index 86ce56e5..294f0d5f 100644 --- a/controllers/handlers_resources.go +++ b/controllers/handlers_resources.go @@ -185,13 +185,7 @@ func postProcessDeployedResources(ctx context.Context, remoteRestConfig *rest.Co } if isPullMode { - setters := prepareSetters(clusterSummary, libsveltosv1beta1.FeatureResources, profileRef, - configurationHash, true, false) - err = pullmode.CommitStagedResourcesForDeployment(ctx, c, - clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, configv1beta1.ClusterSummaryKind, - clusterSummary.Name, string(libsveltosv1beta1.FeatureResources), - logger, setters...) - if err != nil { + if err := commitPullModeResourcesStaging(ctx, c, clusterSummary, profileRef, configurationHash, logger); err != nil { return err } @@ -211,6 +205,24 @@ func postProcessDeployedResources(ctx context.Context, remoteRestConfig *rest.Co clusterSummary.Spec.ClusterProfileSpec.ValidateHealths, libsveltosv1beta1.FeatureResources, false, logger) } +// commitPullModeResourcesStaging prepares the ConfigurationGroup setters (including any +// resolved JobCheck manifests, see prepareSetters) and commits the staged resources for +// sveltos-applier to pick up. +func commitPullModeResourcesStaging(ctx context.Context, c client.Client, clusterSummary *configv1beta1.ClusterSummary, + profileRef *corev1.ObjectReference, configurationHash []byte, logger logr.Logger) error { + + setters, err := prepareSetters(ctx, clusterSummary, libsveltosv1beta1.FeatureResources, profileRef, + configurationHash, true, false, logger) + if err != nil { + return err + } + + return pullmode.CommitStagedResourcesForDeployment(ctx, c, + clusterSummary.Spec.ClusterNamespace, clusterSummary.Spec.ClusterName, configv1beta1.ClusterSummaryKind, + clusterSummary.Name, string(libsveltosv1beta1.FeatureResources), + logger, setters...) +} + func cleanStaleResources(ctx context.Context, clusterSummary *configv1beta1.ClusterSummary, localResourceReports, remoteResourceReports []libsveltosv1beta1.ResourceReport, logger logr.Logger, ) (localUndeployed, remoteUndeployed []libsveltosv1beta1.ResourceReport, err error) { @@ -504,7 +516,10 @@ func pullModeUndeployResources(ctx context.Context, c client.Client, clusterSumm return err } - setters := prepareSetters(clusterSummary, fID, profileRef, nil, false, true) + setters, err := prepareSetters(ctx, clusterSummary, fID, profileRef, nil, false, true, logger) + if err != nil { + return err + } // discard all previous staged resources. This will instruct agent to undeploy err = pullmode.RemoveDeployedResources(ctx, c, clusterSummary.Spec.ClusterNamespace, diff --git a/controllers/handlers_utils.go b/controllers/handlers_utils.go index 0c76eab9..081b4c83 100644 --- a/controllers/handlers_utils.go +++ b/controllers/handlers_utils.go @@ -1632,8 +1632,9 @@ func getPatchesHash(ctx context.Context, clusterSummary *configv1beta1.ClusterSu return hashString, nil } -func prepareSetters(clusterSummary *configv1beta1.ClusterSummary, featureID libsveltosv1beta1.FeatureID, - profileRef *corev1.ObjectReference, configurationHash []byte, includeDeployChecks, includeDeleteChecks bool) []pullmode.Option { +func prepareSetters(ctx context.Context, clusterSummary *configv1beta1.ClusterSummary, featureID libsveltosv1beta1.FeatureID, + profileRef *corev1.ObjectReference, configurationHash []byte, includeDeployChecks, includeDeleteChecks bool, + logger logr.Logger) ([]pullmode.Option, error) { setters := make([]pullmode.Option, 0) if clusterSummary.Spec.ClusterProfileSpec.SyncMode == configv1beta1.SyncModeContinuousWithDriftDetection { @@ -1674,15 +1675,41 @@ func prepareSetters(clusterSummary *configv1beta1.ClusterSummary, featureID libs pullmode.WithDeployedGVKs(gvks)) if includeDeployChecks { + preDeployCheckJobs, err := clusterops.ResolveJobChecksForPullMode(ctx, getManagementClusterDirectClient(), + clusterSummary, getSveltosNamespace(), clusterSummary.Spec.ClusterProfileSpec.PreDeployChecks, logger) + if err != nil { + return nil, err + } + validateHealthJobs, err := clusterops.ResolveJobChecksForPullMode(ctx, getManagementClusterDirectClient(), + clusterSummary, getSveltosNamespace(), clusterSummary.Spec.ClusterProfileSpec.ValidateHealths, logger) + if err != nil { + return nil, err + } + setters = append(setters, pullmode.WithPreDeployChecks(clusterSummary.Spec.ClusterProfileSpec.PreDeployChecks), - pullmode.WithValidateHealths(clusterSummary.Spec.ClusterProfileSpec.ValidateHealths)) + pullmode.WithPreDeployCheckJobs(preDeployCheckJobs), + pullmode.WithValidateHealths(clusterSummary.Spec.ClusterProfileSpec.ValidateHealths), + pullmode.WithValidateHealthJobs(validateHealthJobs)) } if includeDeleteChecks { + preDeleteCheckJobs, err := clusterops.ResolveJobChecksForPullMode(ctx, getManagementClusterDirectClient(), + clusterSummary, getSveltosNamespace(), clusterSummary.Spec.ClusterProfileSpec.PreDeleteChecks, logger) + if err != nil { + return nil, err + } + postDeleteCheckJobs, err := clusterops.ResolveJobChecksForPullMode(ctx, getManagementClusterDirectClient(), + clusterSummary, getSveltosNamespace(), clusterSummary.Spec.ClusterProfileSpec.PostDeleteChecks, logger) + if err != nil { + return nil, err + } + setters = append(setters, pullmode.WithPreDeleteChecks(clusterSummary.Spec.ClusterProfileSpec.PreDeleteChecks), + pullmode.WithPreDeleteCheckJobs(preDeleteCheckJobs), pullmode.WithPostDeleteChecks(clusterSummary.Spec.ClusterProfileSpec.PostDeleteChecks), + pullmode.WithPostDeleteCheckJobs(postDeleteCheckJobs), ) } @@ -1700,7 +1727,7 @@ func prepareSetters(clusterSummary *configv1beta1.ClusterSummary, featureID libs setters = append(setters, pullmode.WithSourceRef(&sourceRef)) - return setters + return setters, nil } func updateReloaderWithDeployedResources(ctx context.Context, clusterSummary *configv1beta1.ClusterSummary, diff --git a/go.mod b/go.mod index 66f6fa91..0cb8b851 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/projectsveltos/addon-controller -go 1.26.5 +go 1.26.6 require ( dario.cat/mergo v1.0.2 @@ -20,7 +20,7 @@ require ( github.com/onsi/gomega v1.42.1 github.com/opencontainers/image-spec v1.1.1 github.com/pkg/errors v0.9.1 - github.com/projectsveltos/libsveltos v1.13.1-0.20260817055546-e9cd5c7232a0 + github.com/projectsveltos/libsveltos v1.13.1-0.20260817131031-65ba770060a8 github.com/prometheus/client_golang v1.24.1 github.com/sigstore/cosign/v3 v3.1.3 github.com/sigstore/sigstore v1.10.9 @@ -84,22 +84,22 @@ require ( github.com/aliyun/credentials-go v1.3.2 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2 v1.43.5 // indirect - github.com/aws/aws-sdk-go-v2/config v1.32.36 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.19.35 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.36 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.36 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.36 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.37 // indirect + github.com/aws/aws-sdk-go-v2 v1.43.6 // indirect + github.com/aws/aws-sdk-go-v2/config v1.32.37 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.19.36 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.37 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.38 // indirect github.com/aws/aws-sdk-go-v2/service/ecr v1.55.3 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.10 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.16 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.36 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.5.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.33.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.45.5 // indirect - github.com/aws/smithy-go v1.27.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.17 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.37 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.5.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.33.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.45.6 // indirect + github.com/aws/smithy-go v1.27.8 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect diff --git a/go.sum b/go.sum index af60191b..9cfecc0f 100644 --- a/go.sum +++ b/go.sum @@ -140,40 +140,40 @@ github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYW github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go-v2 v1.43.5 h1:yKT5GYnFWhuDo+DqKvE5ZPwVn3RjC4MAeBtZGlh6AVM= -github.com/aws/aws-sdk-go-v2 v1.43.5/go.mod h1:wZjAJppCntyOGgVSmgVTfDyRJK5PHOasO6Wsy8U7Axk= -github.com/aws/aws-sdk-go-v2/config v1.32.36 h1:mX6ietU7UlB4w/2IUaexJdsyUDvhTd+jYPjVePiyi6s= -github.com/aws/aws-sdk-go-v2/config v1.32.36/go.mod h1:rMpV4xk7ZK59edraSaHP0jsWrztWTT5tbCwWY495hug= -github.com/aws/aws-sdk-go-v2/credentials v1.19.35 h1:Cxua2RVdRwL0sfjHM/SnQoOnQ7xKng9m5EQBO8BnZlg= -github.com/aws/aws-sdk-go-v2/credentials v1.19.35/go.mod h1:9XQ+RSIGPkycr+oCJYnB1uTv5kMVVR+rd2vYK0Hxj2w= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.36 h1:gucL1KH/PAYbpTpBg09CiVpBdTu4qkCl8C7xOTBixUg= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.36/go.mod h1:usTB+PHhNMhrx2dxUeHcM7OrT5pySvmjYI++IsefPN0= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.36 h1:5CrzwxDqf4w3x1Vs3/NiZ0nsC34Hbm3pIDMWbsLebOE= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.36/go.mod h1:A3gHdKZIvG/QXERzZwcxNS3RNDFcRCuhhTFBYp+V/nw= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.36 h1:A4N2f4YPcST0v+dWtX+xrpPPCL9VTBhoIFFUWYqbacE= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.36/go.mod h1:B/Qr859uxWUEfZeGotK5KAEoof4Q9YWgNtPSwV6jcyk= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.37 h1:oyd3ke4V9AhKcRR7rRgxk1VyI+DjK2CBQtbxh3OkdaA= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.37/go.mod h1:aA9D7SqfG9IC1b7FLD7Iyc8Q4JN0a8gHhNjN4zPlIaI= +github.com/aws/aws-sdk-go-v2 v1.43.6 h1:RrmFcqCBxkJuf7g1axVo5krB4jM/AO8r5e5oujrgdoQ= +github.com/aws/aws-sdk-go-v2 v1.43.6/go.mod h1:tXpPM+v0D1lndmga+HqqLDIzUFJlEeR21aspVklHF00= +github.com/aws/aws-sdk-go-v2/config v1.32.37 h1:Ljl7LOJB6ym0liuEl0+TZ3d7f5I8MEZN1Cj9PINlj/g= +github.com/aws/aws-sdk-go-v2/config v1.32.37/go.mod h1:WJ7pe7ZPpmG8Q5kKS53zeypIV4FBGACxmte8Uc6SgUc= +github.com/aws/aws-sdk-go-v2/credentials v1.19.36 h1:84s5xMme6ENYEdKG8rsbSFFg/8+lbHBeM9QYSO0gnDk= +github.com/aws/aws-sdk-go-v2/credentials v1.19.36/go.mod h1:c46BLdagDLIswjgt+GeQOslXgeS0E6wCacs5yZbxPGk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.37 h1:b5tb+CZItBkydC7r3hTNdSO3pszG1R2EtnA+7TePQPk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.37/go.mod h1:ZQ+6SU9X0oz6+7MUCSswv9Mjci4eaqZr21HI2RVy/yA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.37 h1:lznzIOvvbqjfe8UAaciCRJgBgJsxuTROKlhZuXQWfv8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.37/go.mod h1:otfkzyfQeMMLZAqX59GSXTL3o22BR/l6HFaRzzbWSqA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.37 h1:zCEORWo0eU0gDjG+IyApE/2B+ZGG1m+GU7B263XV8ds= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.37/go.mod h1:i6c0PEl3TNOWxRbQ++KQcVenPWS/GoQeiklKhNuqzJ8= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.38 h1:A3UAuCmx7LyUcrixBTzKJYYIUZ2yTvn6ZhT8PB+7APk= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.38/go.mod h1:1PDUYG9Z+JrbbsobsAZHjWOm9QBT/djiK3QbykTL5Z4= github.com/aws/aws-sdk-go-v2/service/ecr v1.55.3 h1:RtGctYMmkTerGClvdY6bHXdtly4FeYw9wz/NPz62LF8= github.com/aws/aws-sdk-go-v2/service/ecr v1.55.3/go.mod h1:vBfBu24Ka3/5UZtepbTV0gnc9VPLT8ok+0oDDaYAzn4= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.10 h1:1A/sI3LNMi3fhRI5TFLMwwo7ALAALSFVCSGvFlr1Iys= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.38.10/go.mod h1:Diyyyz0b43X13pdi1mVMqlTwDjOmRbJMvDsqnduUYWM= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.16 h1:iE4NGbvqUZnHDqddQAauZzCILYtFjOHwRM5MOOKLB5A= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.16/go.mod h1:VsjEgrP+ibcou8TlWA4tYaB+0OojuhirsmCe+U60hTA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.36 h1:fx2ujmozWn+C/GtfXfz5k6Ckzza40ElOpIW7d92fLWQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.36/go.mod h1:QT2ufGVJ+xTRxtXPHTQ1kHkAdWIKPCmD+BqYAXWv8/4= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.17 h1:OvYZOB3qA6zvfdRFiRFRzVSiElMYrz3GdntkXZxlp1o= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.17/go.mod h1:JgR/2Ew50ACfIWau1oeMRX59tMtC0kM+PYQGEaT04cY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.37 h1:a3D4AjrOrTrP8+d9ILBthqrElf0z1JNol09Xvnwcys8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.37/go.mod h1:ky0gTu+ukvUTuUKFIpp6Wid4oninrkCyvbFkVs0kpHM= github.com/aws/aws-sdk-go-v2/service/kms v1.53.4 h1:PEgVSsWtR8NNxsDxFL2Ywisi7R+1EFQARGsT4q3mWwI= github.com/aws/aws-sdk-go-v2/service/kms v1.53.4/go.mod h1:3EeKyDGPGSCEphG2OolwNGNF45RvQIfm27AYYpfEWrw= -github.com/aws/aws-sdk-go-v2/service/signin v1.5.5 h1:0VTFBfOgPJrUSpGMgzoi8qLcXF5dbmiBuxpo14eBWUw= -github.com/aws/aws-sdk-go-v2/service/signin v1.5.5/go.mod h1:sNZYlBxoohYMBYl47BO/bFtAM6I8HSsPa1qwwPPRGoQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.33.5 h1:jDQARFp1mJ2PEnllQf01nfFXGfWMJ59e0/HCHUTTZCk= -github.com/aws/aws-sdk-go-v2/service/sso v1.33.5/go.mod h1:OcT2AhgTuxGAwZk5hgxaNLGpS33W8s8dUQadGVDVY9I= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.5 h1:8xo1q9ttkYqMJ6vOXX67FPSpVEI7BWKVTKh77g82w+8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.5/go.mod h1:hbBeEUrZg6VddXYZpbKPyF0tl4XEnM+Dbx92RW3vmZI= -github.com/aws/aws-sdk-go-v2/service/sts v1.45.5 h1:eQ5BtXDrPg2wK0AjtVPzeBhUpYPeqHE/ptiH7xJRGek= -github.com/aws/aws-sdk-go-v2/service/sts v1.45.5/go.mod h1:f9ImhnOISY7BuTZLM8qHepCYnglHBVLk5wVzatmP++w= -github.com/aws/smithy-go v1.27.7 h1:Zgj5z4LfcDYoQIVk+n/yGdTkP/2y6ZT5vYxe0fp7bqE= -github.com/aws/smithy-go v1.27.7/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/aws-sdk-go-v2/service/signin v1.5.6 h1:i68sFvXidKlkiSvI7d7Ilc1/UvW4CtBOaivH7jhG4fs= +github.com/aws/aws-sdk-go-v2/service/signin v1.5.6/go.mod h1:/h7Obr9WTtzbjTHGASRQwLN7Bupw+TC3x8x7fyx39hE= +github.com/aws/aws-sdk-go-v2/service/sso v1.33.6 h1:tpfGChmjUmv3W9WlRvy+stwKDTbFFdq8Zk9DbFPrfMU= +github.com/aws/aws-sdk-go-v2/service/sso v1.33.6/go.mod h1:CSjiDzmG/lsKkTOYjbkM+duLmRlW+LOxD64Na44ijnI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.6 h1:49BBtY68A+KJCQ3a2F3eUe6ROsKucxUdfHKoqorc0wI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.38.6/go.mod h1:ptG2hbs7QltE1GcQY0MpS4bfrc51KCnBXUr7OT1EEfE= +github.com/aws/aws-sdk-go-v2/service/sts v1.45.6 h1:JvExZWabChDM0qJAirQYGfOYo0ndT3edXj+fqSPNjkE= +github.com/aws/aws-sdk-go-v2/service/sts v1.45.6/go.mod h1:XZcaQkV2cItp6yEkrwljyaPOf22RuX7T43jxap/FOmM= +github.com/aws/smithy-go v1.27.8 h1:FR0dxZfIlV7Z8eh2iHfIofdunw382XsDV3Mxt9nUvRY= +github.com/aws/smithy-go v1.27.8/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0 h1:JFWXO6QPihCknDdnL6VaQE57km4ZKheHIGd9YiOGcTo= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0/go.mod h1:046/oLyFlYdAghYQE2yHXi/E//VM5Cf3/dFmA+3CZ0c= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -639,8 +639,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= -github.com/projectsveltos/libsveltos v1.13.1-0.20260817055546-e9cd5c7232a0 h1:LK8aK1edMBB1Et3fkdY6dzfvIVZ9eZ4BEp3aa7kt7oc= -github.com/projectsveltos/libsveltos v1.13.1-0.20260817055546-e9cd5c7232a0/go.mod h1:dgQKoyCm3xr5TV0vJxbq+dkuBLmwm4mqt6tMAgJiP+s= +github.com/projectsveltos/libsveltos v1.13.1-0.20260817131031-65ba770060a8 h1:F4EvbmX0vecFGX01iZOeMRPGvvvw9A1kh+tg4BVQU70= +github.com/projectsveltos/libsveltos v1.13.1-0.20260817131031-65ba770060a8/go.mod h1:U6iGj5KoC/PcTD2vh3XU6gy7g11suThT6sZSEpmLEkU= github.com/projectsveltos/lua-utils/glua-json v0.0.0-20251212200258-2b3cdcb7c0f5 h1:khnc+994UszxZYu69J+R5FKiLA/Nk1JQj0EYAkwTWz0= github.com/projectsveltos/lua-utils/glua-json v0.0.0-20251212200258-2b3cdcb7c0f5/go.mod h1:yVL8KQFa9tmcxgwl9nwIMtKgtmIVC1zaFRSCfOwYvPY= github.com/projectsveltos/lua-utils/glua-runes v0.0.0-20251212200258-2b3cdcb7c0f5 h1:YbsebwRwTRhV8QacvEAdFqxcxHdeu7JTVtsBovbkgos= diff --git a/hack/tools/go.mod b/hack/tools/go.mod index 7588bcad..56b92389 100644 --- a/hack/tools/go.mod +++ b/hack/tools/go.mod @@ -1,6 +1,6 @@ module github.com/projectsveltos/addon-controller/hack/tools -go 1.26.5 +go 1.26.6 require ( github.com/a8m/envsubst v1.4.3 diff --git a/lib/clusterops/jobhealthcheck_default.go b/lib/clusterops/jobhealthcheck_default.go index 8f2b389a..134d8efb 100644 --- a/lib/clusterops/jobhealthcheck_default.go +++ b/lib/clusterops/jobhealthcheck_default.go @@ -21,16 +21,24 @@ import ( "fmt" "github.com/go-logr/logr" + batchv1 "k8s.io/api/batch/v1" libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" ) // Default JobCheck implementation: reports the feature is unavailable. A Sveltos Enterprise -// build overrides this via SetJobHealthCheckValidator before starting the manager. +// build overrides this via SetJobHealthCheckValidator/SetJobHealthCheckResolver before +// starting the manager. func init() { validateJobHealthCheck = func(_ context.Context, _ JobHealthCheckDeps, check *libsveltosv1beta1.ValidateHealth, _ logr.Logger) error { return fmt.Errorf("JobCheck (%s) requires a Sveltos Enterprise build", check.Name) } + + resolveJobHealthCheck = func(_ context.Context, _ JobHealthCheckDeps, + check *libsveltosv1beta1.ValidateHealth, _ logr.Logger) (*batchv1.Job, error) { + + return nil, fmt.Errorf("JobCheck (%s) requires a Sveltos Enterprise build", check.Name) + } } diff --git a/lib/clusterops/validate_health.go b/lib/clusterops/validate_health.go index 5234ad9f..b7e47154 100644 --- a/lib/clusterops/validate_health.go +++ b/lib/clusterops/validate_health.go @@ -29,6 +29,7 @@ import ( "github.com/go-logr/logr" lua "github.com/yuin/gopher-lua" + batchv1 "k8s.io/api/batch/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -38,6 +39,7 @@ import ( "k8s.io/client-go/rest" "k8s.io/client-go/restmapper" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/yaml" configv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1" libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1" @@ -49,6 +51,12 @@ import ( const ( defaultPrometheusPath = "api/v1/query" metricsHTTPTimeout = 30 * time.Second + + // jobHealthCheckDefaultTimeout matches the Sveltos Enterprise JobCheck Validator's own + // default (see sveltos-enterprise/jobhealthcheck), used here only as the + // ActiveDeadlineSeconds fallback when a resolved pull-mode Job's check has no explicit + // Timeout. + jobHealthCheckDefaultTimeout = 5 * time.Minute ) type healthStatus struct { @@ -80,7 +88,7 @@ type JobHealthCheckDeps struct { } // validateJobHealthCheck runs a JobCheck. JobCheck is a Sveltos Enterprise feature; the default -// (jobhealthcheck_oss.go) is a stub reporting the feature is unavailable. A Sveltos Enterprise +// (jobhealthcheck_default.go) is a stub reporting the feature is unavailable. A Sveltos Enterprise // build wires in the real implementation via SetJobHealthCheckValidator. var ( validateJobHealthCheck func(ctx context.Context, deps JobHealthCheckDeps, @@ -96,6 +104,89 @@ func SetJobHealthCheckValidator(fn func(ctx context.Context, deps JobHealthCheck validateJobHealthCheck = fn } +// resolveJobHealthCheck fetches and resolves (Cluster-field templating applied) the Job +// manifest referenced by check.JobCheck.JobRef, without running it. Used only when staging a +// pull-mode ConfigurationGroup: sveltos-applier cannot verify a Sveltos Enterprise license or +// fetch JobRef itself, so addon-controller resolves the Job once, up front, here, and stages +// the result for sveltos-applier to run unattended. Same default-stub/SetX-override pattern as +// validateJobHealthCheck. +var ( + resolveJobHealthCheck func(ctx context.Context, deps JobHealthCheckDeps, + check *libsveltosv1beta1.ValidateHealth, logger logr.Logger) (*batchv1.Job, error) +) + +// SetJobHealthCheckResolver overrides the JobCheck resolution implementation. Called by a +// Sveltos Enterprise build's composition root before starting the manager, alongside +// SetJobHealthCheckValidator; this package never imports anything private itself. +func SetJobHealthCheckResolver(fn func(ctx context.Context, deps JobHealthCheckDeps, + check *libsveltosv1beta1.ValidateHealth, logger logr.Logger) (*batchv1.Job, error)) { + + resolveJobHealthCheck = fn +} + +// ResolveJobChecksForPullMode resolves every JobCheck entry in checks (fetching JobRef's +// ConfigMap/Secret and applying Cluster-field templating, same as the push-mode path) and +// returns the resolved manifests as YAML, keyed by "/" - ready to +// stage onto a ConfigurationGroup's PreDeployCheckJobs/ValidateHealthJobs/PreDeleteCheckJobs/ +// PostDeleteCheckJobs field. Returns an empty, non-nil map when checks has no JobCheck entries. +// Fails the same way a push-mode JobCheck failure would (license, fetch, or templating error). +func ResolveJobChecksForPullMode(ctx context.Context, mgmtClient client.Client, + clusterSummary *configv1beta1.ClusterSummary, sveltosNamespace string, + checks []libsveltosv1beta1.ValidateHealth, logger logr.Logger) (map[string]string, error) { + + jobs := make(map[string]string) + + for i := range checks { + check := &checks[i] + if check.JobCheck == nil { + continue + } + + deps := JobHealthCheckDeps{ + MgmtClient: mgmtClient, + ClusterSummary: clusterSummary, + SveltosNamespace: sveltosNamespace, + } + + job, err := resolveJobHealthCheck(ctx, deps, check, logger) + if err != nil { + return nil, fmt.Errorf("failed to resolve JobCheck %q: %w", check.Name, err) + } + + // Only the resolved Job manifest travels to sveltos-applier (as YAML, keyed by + // namespace/name) - check.JobCheck.Timeout itself does not. Carry it via the Job's own + // ActiveDeadlineSeconds instead, which the Job controller already enforces natively, so + // sveltos-applier's poll loop doesn't need a side channel for it. Respects an + // ActiveDeadlineSeconds the manifest already set explicitly. + if job.Spec.ActiveDeadlineSeconds == nil { + timeout := jobHealthCheckDefaultTimeout + if check.JobCheck.Timeout != nil { + timeout = check.JobCheck.Timeout.Duration + } + seconds := int64(timeout.Seconds()) + job.Spec.ActiveDeadlineSeconds = &seconds + } + + // Same reasoning: the map is keyed by the Job's own namespace/name, not check.Name, so + // carry check.Name onto the Job itself for sveltos-applier to build a failure message + // consistent with push-mode's HealthCheckError. + if job.Annotations == nil { + job.Annotations = map[string]string{} + } + job.Annotations[libsveltosv1beta1.ValidateHealthCheckNameAnnotation] = check.Name + + content, err := yaml.Marshal(job) + if err != nil { + return nil, fmt.Errorf("failed to marshal resolved Job for JobCheck %q: %w", check.Name, err) + } + + key := fmt.Sprintf("%s/%s", job.Namespace, job.Name) + jobs[key] = string(content) + } + + return jobs, nil +} + // prometheusResponse is the top-level Prometheus HTTP API response. type prometheusResponse struct { Status string `json:"status"`