Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ go 1.25.5
require (
github.com/buger/jsonparser v1.1.1
github.com/google/uuid v1.6.0
github.com/meshery/meshery-operator v0.8.11
github.com/meshery/meshkit v0.8.54
github.com/myntra/pipeline v0.0.0-20180618182531-2babf4864ce8
github.com/sirupsen/logrus v1.9.3
Expand All @@ -21,6 +20,7 @@ require (
k8s.io/apimachinery v0.34.2
k8s.io/client-go v0.34.2
k8s.io/kubectl v0.34.2
sigs.k8s.io/controller-runtime v0.20.1
sigs.k8s.io/yaml v1.6.0
)

Expand Down Expand Up @@ -50,6 +50,7 @@ require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/evanphx/json-patch v5.9.11+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
Expand Down Expand Up @@ -113,6 +114,8 @@ require (
github.com/nats-io/nkeys v0.4.9 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/oapi-codegen/runtime v1.1.2 // indirect
github.com/onsi/ginkgo/v2 v2.22.2 // indirect
github.com/onsi/gomega v1.36.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
Expand Down Expand Up @@ -166,7 +169,6 @@ require (
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
oras.land/oras-go/v2 v2.6.0 // indirect
sigs.k8s.io/controller-runtime v0.20.1 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/kustomize/api v0.20.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
Expand Down Expand Up @@ -229,8 +231,6 @@ github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/meshery/meshery-operator v0.8.11 h1:eDo2Sw0jjVrXsvvhF8LenADM58pK+7Z68ROPVIejTPc=
github.com/meshery/meshery-operator v0.8.11/go.mod h1:hQEtFKKa5Fr/Mskk6bV5ip3bQ0+3F0u1voYS3XisBp4=
github.com/meshery/meshkit v0.8.54 h1:WxsYNITaK+IwzXFRbTzl2qkcygVVDRA7lVSPoQIA+ZQ=
github.com/meshery/meshkit v0.8.54/go.mod h1:YmqM1i4vRD7W+Agf7KOXJchy6Haq/g1fABy7oYcnYo8=
github.com/meshery/schemas v0.8.93 h1:kCib7RSzph+AbR6r2yQpFnLpK+zxyVxn0B3O6RbtXuM=
Expand Down Expand Up @@ -404,6 +404,10 @@ go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
Expand Down
73 changes: 54 additions & 19 deletions internal/config/crd_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ import (
"errors"
"fmt"

"github.com/meshery/meshery-operator/pkg/client"
"github.com/meshery/meshkit/utils"
"golang.org/x/exp/slices"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/retry"
ctrlclient "sigs.k8s.io/controller-runtime/pkg/client"
)

var (
Expand Down Expand Up @@ -195,24 +197,57 @@ func filterBlacklistedPipelines(pipelines PipelineConfigs, blackList []string) P
return result
}

func PatchCRVersion(config *rest.Config) error {
meshsyncClient, err := client.New(config)
// PatchCRVersion updates the MeshSync CR version safely.
// It uses Controller Runtime patterns for idempotency and conflict handling.
func PatchCRVersion(ctx context.Context, config *rest.Config) error {
// 1. Init Controller Runtime Client
cl, err := ctrlclient.New(config, ctrlclient.Options{})
if err != nil {
return ErrInitConfig(fmt.Errorf("unable to update MeshSync configuration"))
}
return ErrInitConfig(fmt.Errorf("unable to create controller-runtime client: %w", err))
}

// 2. Define the Object (Using Unstructured to avoid circular dependencies)
obj := &unstructured.Unstructured{}
obj.SetGroupVersionKind(schema.GroupVersionKind{
Group: group,
Version: version,
Kind: "MeshSync",
})

key := types.NamespacedName{Name: crName, Namespace: namespace}

// 3. Retry Logic (Standard Kubernetes RetryOnConflict)
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
// Fetch current CR
if err := cl.Get(context.TODO(), key, obj); err != nil {
if k8serrors.IsNotFound(err) {
// GUARD: CR doesn't exist, so we skip patching (Fixes #422)
return nil
}
// Use existing error pattern
return ErrInitConfig(fmt.Errorf("unable to get MeshSync CR %s/%s: %w", namespace, crName, err))
}

patchedResource := map[string]interface{}{
"spec": map[string]interface{}{
"version": Server["version"],
},
}
byt, err := utils.Marshal(patchedResource)
if err != nil {
return ErrInitConfig(fmt.Errorf("unable to update MeshSync configuration"))
}
_, err = meshsyncClient.CoreV1Alpha1().MeshSyncs("meshery").Patch(context.TODO(), crName, types.MergePatchType, []byte(byt), metav1.PatchOptions{})
if err != nil {
return ErrInitConfig(fmt.Errorf("unable to update MeshSync configuration"))
}
return nil
// Idempotency: Check if version already matches
specVersion, found, _ := unstructured.NestedString(obj.Object, "spec", "version")
if found && specVersion == Server["version"] {
// Version already matches, no update needed
return nil
}

// Prepare Patch (MergeFrom handles JSON generation automatically)
patch := ctrlclient.MergeFrom(obj.DeepCopy())

// Update the version field in the object
if err := unstructured.SetNestedField(obj.Object, Server["version"], "spec", "version"); err != nil {
return ErrInitConfig(fmt.Errorf("unable to set version field: %w", err))
}

// Apply Patch
if err := cl.Patch(context.TODO(), obj, patch); err != nil {
return err // RetryOnConflict will catch this and retry if it's a conflict
}

return nil
})
}
2 changes: 1 addition & 1 deletion internal/config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (p PipelineConfigs) Add(pc PipelineConfig) PipelineConfigs {
func (p PipelineConfigs) Delete(pc PipelineConfig) PipelineConfigs {
for index, pipelineConfig := range p {
if pipelineConfig.Name == pc.Name {
p = slices.Delete[PipelineConfigs](p, index, index+1)
p = slices.Delete(p, index, index+1)
break
}
}
Expand Down
10 changes: 7 additions & 3 deletions pkg/lib/meshsync/meshsync.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,13 @@
}

if useCRDFlag {
// this patch only make sense when CRD is present when in cluster
if errPatchCRVersion := config.PatchCRVersion(&kubeClient.RestConfig); errPatchCRVersion != nil {
log.Warnf("meshsync: %v", errPatchCRVersion)
// Only attempt to patch MeshSync CR/version if the MeshSync CR object exists.
if _, errGetCR := config.GetMeshsyncCRD(kubeClient.DynamicKubeClient); errGetCR == nil {
if errPatchCRVersion := config.PatchCRVersion(&kubeClient.RestConfig); errPatchCRVersion != nil {

Check failure on line 76 in pkg/lib/meshsync/meshsync.go

View workflow job for this annotation

GitHub Actions / Integration tests

not enough arguments in call to config.PatchCRVersion

Check failure on line 76 in pkg/lib/meshsync/meshsync.go

View workflow job for this annotation

GitHub Actions / golangci-lint (ubuntu-24.04, 1.25.x)

not enough arguments in call to config.PatchCRVersion
log.Warnf("meshsync: %v", errPatchCRVersion)
}
} else {
log.Debugf("meshsync: skipping PatchCRVersion because MeshSync CR not found: %v", errGetCR)
}
}

Expand Down
Loading