Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: v2.5
version: v2.11
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint

## Tool Versions
ADDLICENSE_VERSION ?= v1.1.1
GOIMPORTS_VERSION ?= v0.34.0
GOIMPORTS_VERSION ?= v0.41.0
MOCKGEN_VERSION ?= v0.6.0
GOLANGCI_LINT_VERSION ?= v2.5
GOLANGCI_LINT_VERSION ?= v2.11

.PHONY: addlicense
addlicense: $(ADDLICENSE) ## Download addlicense locally if necessary.
Expand Down
19 changes: 16 additions & 3 deletions clientutils/clientutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package clientutils

import (
"context"
"encoding/json"
"fmt"
"reflect"

Expand All @@ -19,6 +20,7 @@ import (
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
Expand Down Expand Up @@ -285,15 +287,15 @@ func GetMultiple(ctx context.Context, c client.Client, reqs []GetRequest) error
return nil
}

// apply is a PatchProvider always providing client.Apply.
// apply is a PatchProvider always providing a server-side apply patch.
type apply struct{}

// PatchFor implements PatchProvider.
func (a apply) PatchFor(obj client.Object) client.Patch {
return client.Apply
return applyPatch{}
}

// ApplyAll provides client.Apply for any given object.
// ApplyAll provides a server-side apply patch for any given object.
var ApplyAll = apply{}

// PatchProvider retrieves a patch for any given object.
Expand All @@ -307,6 +309,17 @@ type PatchRequest struct {
Patch client.Patch
}

// applyPatch uses server-side apply semantics without relying on the deprecated client.Apply constant.
type applyPatch struct{}

func (applyPatch) Type() types.PatchType {
return types.ApplyPatchType
}

func (applyPatch) Data(obj client.Object) ([]byte, error) {
return json.Marshal(obj)
}

// PatchRequestFromObjectAndProvider is a shorthand to create a PatchRequest using a client.Object and PatchProvider.
func PatchRequestFromObjectAndProvider(obj client.Object, provider PatchProvider) PatchRequest {
return PatchRequest{
Expand Down
52 changes: 26 additions & 26 deletions clientutils/clientutils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -393,19 +393,19 @@ var _ = Describe("Clientutils", func() {
})

Describe("ApplyAll", func() {
It("should return client.Apply for any object", func() {
Expect(ApplyAll.PatchFor(cm)).To(Equal(client.Apply))
Expect(ApplyAll.PatchFor(secret)).To(Equal(client.Apply))
Expect(ApplyAll.PatchFor(uPod)).To(Equal(client.Apply))
It("should return an apply patch for any object", func() {
Expect(ApplyAll.PatchFor(cm).Type()).To(Equal(types.ApplyPatchType))
Expect(ApplyAll.PatchFor(secret).Type()).To(Equal(types.ApplyPatchType))
Expect(ApplyAll.PatchFor(uPod).Type()).To(Equal(types.ApplyPatchType))
})
})

Describe("PatchRequestFromObjectAndProvider", func() {
It("should create a patch request from the given object and provider", func() {
patchProvider.EXPECT().PatchFor(cm).Return(client.Apply)
patchProvider.EXPECT().PatchFor(cm).Return(ApplyAll.PatchFor(cm))
Expect(PatchRequestFromObjectAndProvider(cm, patchProvider)).To(Equal(PatchRequest{
Object: cm,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(cm),
}))
})
})
Expand All @@ -417,19 +417,19 @@ var _ = Describe("Clientutils", func() {

It("should create patch requests from the given objects and provider", func() {
gomock.InOrder(
patchProvider.EXPECT().PatchFor(cm).Return(client.Apply),
patchProvider.EXPECT().PatchFor(secret).Return(client.Apply),
patchProvider.EXPECT().PatchFor(cm).Return(ApplyAll.PatchFor(cm)),
patchProvider.EXPECT().PatchFor(secret).Return(ApplyAll.PatchFor(secret)),
)

Expect(PatchRequestsFromObjectsAndProvider([]client.Object{cm, secret}, patchProvider)).To(Equal(
[]PatchRequest{
{
Object: cm,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(cm),
},
{
Object: secret,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(secret),
},
},
))
Expand All @@ -445,11 +445,11 @@ var _ = Describe("Clientutils", func() {
reqs := []PatchRequest{
{
Object: cm,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(cm),
},
{
Object: secret,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(secret),
},
}
Expect(ObjectsFromPatchRequests(reqs)).To(Equal([]client.Object{cm, secret}))
Expand All @@ -461,15 +461,15 @@ var _ = Describe("Clientutils", func() {
reqs := []PatchRequest{
{
Object: cm,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(cm),
},
{
Object: secret,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(secret),
},
}
someErr := fmt.Errorf("some error")
c.EXPECT().Patch(ctx, cm, client.Apply).Return(someErr)
c.EXPECT().Patch(ctx, cm, ApplyAll.PatchFor(cm)).Return(someErr)

err := PatchMultiple(ctx, c, reqs)
Expect(err).To(HaveOccurred())
Expand All @@ -480,16 +480,16 @@ var _ = Describe("Clientutils", func() {
reqs := []PatchRequest{
{
Object: cm,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(cm),
},
{
Object: secret,
Patch: client.Apply,
Patch: ApplyAll.PatchFor(secret),
},
}
gomock.InOrder(
c.EXPECT().Patch(ctx, cm, client.Apply),
c.EXPECT().Patch(ctx, secret, client.Apply),
c.EXPECT().Patch(ctx, cm, ApplyAll.PatchFor(cm)),
c.EXPECT().Patch(ctx, secret, ApplyAll.PatchFor(secret)),
)
Expect(PatchMultiple(ctx, c, reqs)).To(Succeed())
})
Expand All @@ -504,10 +504,10 @@ var _ = Describe("Clientutils", func() {
It("should abort and return any error from patching", func() {
someErr := fmt.Errorf("some error")
gomock.InOrder(
patchProvider.EXPECT().PatchFor(testdata.UnstructuredSecret()).Return(client.Apply),
patchProvider.EXPECT().PatchFor(testdata.UnstructuredConfigMap()).Return(client.Apply),
patchProvider.EXPECT().PatchFor(testdata.UnstructuredSecret()).Return(ApplyAll.PatchFor(testdata.UnstructuredSecret())),
patchProvider.EXPECT().PatchFor(testdata.UnstructuredConfigMap()).Return(ApplyAll.PatchFor(testdata.UnstructuredConfigMap())),

c.EXPECT().Patch(ctx, testdata.UnstructuredSecret(), client.Apply).Return(someErr),
c.EXPECT().Patch(ctx, testdata.UnstructuredSecret(), ApplyAll.PatchFor(testdata.UnstructuredSecret())).Return(someErr),
)

_, err := PatchMultipleFromFile(ctx, c, objectsPath, patchProvider)
Expand All @@ -517,11 +517,11 @@ var _ = Describe("Clientutils", func() {

It("should patch multiple objects from file", func() {
gomock.InOrder(
patchProvider.EXPECT().PatchFor(testdata.UnstructuredSecret()).Return(client.Apply),
patchProvider.EXPECT().PatchFor(testdata.UnstructuredConfigMap()).Return(client.Apply),
patchProvider.EXPECT().PatchFor(testdata.UnstructuredSecret()).Return(ApplyAll.PatchFor(testdata.UnstructuredSecret())),
patchProvider.EXPECT().PatchFor(testdata.UnstructuredConfigMap()).Return(ApplyAll.PatchFor(testdata.UnstructuredConfigMap())),

c.EXPECT().Patch(ctx, testdata.UnstructuredSecret(), client.Apply),
c.EXPECT().Patch(ctx, testdata.UnstructuredConfigMap(), client.Apply),
c.EXPECT().Patch(ctx, testdata.UnstructuredSecret(), ApplyAll.PatchFor(testdata.UnstructuredSecret())),
c.EXPECT().Patch(ctx, testdata.UnstructuredConfigMap(), ApplyAll.PatchFor(testdata.UnstructuredConfigMap())),
)

objs, err := PatchMultipleFromFile(ctx, c, objectsPath, patchProvider)
Expand Down
17 changes: 8 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ require (
github.com/spf13/pflag v1.0.10
github.com/stretchr/testify v1.11.1
go.uber.org/mock v0.6.0
k8s.io/api v0.34.1
k8s.io/apiextensions-apiserver v0.34.1
k8s.io/apimachinery v0.34.1
k8s.io/apiserver v0.34.1
k8s.io/client-go v0.34.1
k8s.io/api v0.35.3
k8s.io/apiextensions-apiserver v0.35.3
k8s.io/apimachinery v0.35.3
k8s.io/apiserver v0.35.3
k8s.io/client-go v0.35.3
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4
sigs.k8s.io/controller-runtime v0.22.3
sigs.k8s.io/controller-runtime v0.23.3
sigs.k8s.io/kustomize/api v0.20.1
sigs.k8s.io/kustomize/kyaml v0.20.1
sigs.k8s.io/yaml v1.6.0
Expand Down Expand Up @@ -50,7 +50,6 @@ require (
github.com/go-openapi/swag/typeutils v0.25.1 // indirect
github.com/go-openapi/swag/yamlutils v0.25.1 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
Expand Down Expand Up @@ -98,11 +97,11 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/component-base v0.34.1 // indirect
k8s.io/component-base v0.35.3 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.33.0 // indirect
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.2-0.20260122202528-d9cc6641c482 // indirect
)
Loading