diff --git a/.dockerignore b/.dockerignore index 0b531c40b..345af2338 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,3 +9,5 @@ __debug_bin* docs/ examples/ deployments/ +go.work +go.work.sum diff --git a/.gitignore b/.gitignore index b0d6d0bfa..a1bb67ab8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ apiserver.local.config/ *.csv load_test_results.txt .env +go.work +go.work.sum # Development artifact path .build/ diff --git a/Makefile b/Makefile index 61a1d8d34..e1d77a31a 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,7 @@ include make/go.mk # fmt, vet, lint, fix-headers, fix-all include make/testing.mk # test, unit, unit-clean, vulncheck, test-e2e* include make/security.mk # gosec, gosec-sarif include make/mocks.mk # generate-mocks, clean-mocks +include make/work.mk # go.work, clean-work .DEFAULT_GOAL := help diff --git a/api/Makefile b/api/Makefile index c1a0bcfa5..424595699 100644 --- a/api/Makefile +++ b/api/Makefile @@ -27,7 +27,7 @@ vet: ## Run go vet against the module .PHONY: fix fix: ## Run go fix against the module - go fix ./... + go fix -omitzero=false ./... .PHONY: tidy tidy: ## Run go tidy against the module diff --git a/controllers/functionconfigs/functionconfigreconciler_test.go b/controllers/functionconfigs/functionconfigreconciler_test.go index 13803921f..55e012645 100644 --- a/controllers/functionconfigs/functionconfigreconciler_test.go +++ b/controllers/functionconfigs/functionconfigreconciler_test.go @@ -192,7 +192,6 @@ func TestFunctionConfigReconciler(t *testing.T) { t.Fatalf("unable to add configapi to scheme: %v", err) } for _, tt := range tests { - tt := tt // pin for closure t.Run(tt.name, func(t *testing.T) { c := fake.NewClientBuilder().WithObjects(tt.objs...).WithScheme(scheme).WithStatusSubresource(&configapi.FunctionConfig{}).Build() @@ -468,13 +467,13 @@ func TestConcurrentAccessSafety(t *testing.T) { // Writer goroutine go func() { defer close(done) - for i := 0; i < 100; i++ { + for range 100 { store.UpdateExecCache(obj.Name, obj) } }() // Reader goroutine (concurrent with writer) - for i := 0; i < 100; i++ { + for range 100 { store.GetProcessorFromCache("ghcr.io/kptdev/krm-functions-catalog/set-namespace:v0.4.1") } diff --git a/controllers/packagerevisions/integration/packagerevision_integration_test.go b/controllers/packagerevisions/integration/packagerevision_integration_test.go index 259fed634..0b8f99571 100644 --- a/controllers/packagerevisions/integration/packagerevision_integration_test.go +++ b/controllers/packagerevisions/integration/packagerevision_integration_test.go @@ -126,7 +126,6 @@ var _ = Describe("PackageRevision Controller Integration", func() { } for _, tc := range transitions { - tc := tc It(fmt.Sprintf("Should transition %s -> %s and set Ready=True", tc.current, tc.desired), func() { var fetched porchv1alpha2.PackageRevision Expect(k8sClient.Get(ctx, nn, &fetched)).To(Succeed()) diff --git a/controllers/packagerevisions/pkg/controllers/packagerevision/mergekey.go b/controllers/packagerevisions/pkg/controllers/packagerevision/mergekey.go index 8580e05e7..64e910deb 100644 --- a/controllers/packagerevisions/pkg/controllers/packagerevision/mergekey.go +++ b/controllers/packagerevisions/pkg/controllers/packagerevision/mergekey.go @@ -21,6 +21,7 @@ package packagerevision import ( "bytes" "fmt" + "maps" "path" "strings" @@ -50,9 +51,7 @@ func ensureMergeKey(resources map[string]string) (map[string]string, error) { return nil, fmt.Errorf("failed to add merge-key directive: %w", err) } - for k, v := range pr.extra { - result[k] = v - } + maps.Copy(result, pr.extra) return result, nil } diff --git a/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook.go b/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook.go index eb1d9b73f..7722b1948 100644 --- a/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook.go +++ b/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook.go @@ -503,7 +503,7 @@ func (v *PackageRevisionValidator) unmarshalPackageRevision(raw []byte, fieldNam } // unmarshalInto unmarshals raw bytes into a target object, handling empty and malformed data. -func (v *PackageRevisionValidator) unmarshalInto(raw []byte, target interface{}, fieldName string) *admission.Response { +func (v *PackageRevisionValidator) unmarshalInto(raw []byte, target any, fieldName string) *admission.Response { if len(raw) == 0 { resp := admission.Errored(http.StatusBadRequest, fmt.Errorf("%s is empty", fieldName)) return &resp diff --git a/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook_test.go b/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook_test.go index fa3d3eb58..6f531e90f 100644 --- a/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook_test.go +++ b/controllers/packagerevisions/pkg/webhooks/packagerevision_webhook_test.go @@ -1174,7 +1174,7 @@ func TestUnmarshalInto(t *testing.T) { tests := []struct { name string raw []byte - target interface{} + target any fieldName string wantErr bool errMsg string diff --git a/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller-with-workspacename_test.go b/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller-with-workspacename_test.go index b4c3cd963..532e0cafd 100644 --- a/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller-with-workspacename_test.go +++ b/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller-with-workspacename_test.go @@ -784,11 +784,11 @@ status: t.Run(tn, func(t *testing.T) { var pv api.PackageVariant require.NoError(t, yaml.Unmarshal( - []byte(fmt.Sprintf(pvStr, tc.deletionPolicy)), &pv)) + fmt.Appendf(nil, pvStr, tc.deletionPolicy), &pv)) var pr porchapi.PackageRevision require.NoError(t, yaml.Unmarshal( - []byte(fmt.Sprintf(prStr, tc.prLifecycle)), &pr)) + fmt.Appendf(nil, prStr, tc.prLifecycle), &pr)) fc := &fakeClient{} reconciler := &PackageVariantReconciler{Client: fc} @@ -963,7 +963,7 @@ items: var pv api.PackageVariant require.NoError(t, yaml.Unmarshal( - []byte(fmt.Sprintf(pvStr, tc.adoptionPolicy)), &pv)) + fmt.Appendf(nil, pvStr, tc.adoptionPolicy), &pv)) actualStr := reconciler.getDownstreamPRs(context.TODO(), &pv, &prList) var actual []string diff --git a/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller.go b/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller.go index 324b039c4..2d61703f8 100644 --- a/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller.go +++ b/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller.go @@ -18,6 +18,7 @@ import ( "context" "flag" "fmt" + "maps" "strconv" "strings" @@ -601,15 +602,11 @@ func (r *PackageVariantReconciler) adoptPackageRevision(ctx context.Context, if len(pv.Spec.Labels) > 0 && pr.Labels == nil { pr.Labels = make(map[string]string) } - for k, v := range pv.Spec.Labels { - pr.Labels[k] = v - } + maps.Copy(pr.Labels, pv.Spec.Labels) if len(pv.Spec.Annotations) > 0 && pr.Annotations == nil { pr.Annotations = make(map[string]string) } - for k, v := range pv.Spec.Annotations { - pr.Annotations[k] = v - } + maps.Copy(pr.Annotations, pv.Spec.Annotations) return r.Update(ctx, pr) } @@ -872,9 +869,7 @@ func (r *PackageVariantReconciler) calculateDraftResources(ctx context.Context, } origResources := make(map[string]string, len(prr.Spec.Resources)) - for k, v := range prr.Spec.Resources { - origResources[k] = v - } + maps.Copy(origResources, prr.Spec.Resources) // Apply our mutations if err := ensurePackageContext(pv, &prr); err != nil { @@ -985,9 +980,7 @@ func ensurePackageContext(pv *configapi.PackageVariant, } // set or add keys that should be there - for k, v := range pv.Spec.PackageContext.Data { - data[k] = v - } + maps.Copy(data, pv.Spec.PackageContext.Data) // remove any keys that should go for _, k := range pv.Spec.PackageContext.RemoveKeys { diff --git a/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller_test.go b/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller_test.go index 68b01a3f5..c961ed7a9 100644 --- a/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller_test.go +++ b/controllers/packagevariants/pkg/controllers/packagevariant/packagevariant_controller_test.go @@ -787,11 +787,11 @@ status: t.Run(tn, func(t *testing.T) { var pv api.PackageVariant require.NoError(t, yaml.Unmarshal( - []byte(fmt.Sprintf(pvStr, tc.deletionPolicy)), &pv)) + fmt.Appendf(nil, pvStr, tc.deletionPolicy), &pv)) var pr porchapi.PackageRevision require.NoError(t, yaml.Unmarshal( - []byte(fmt.Sprintf(prStr, tc.prLifecycle)), &pr)) + fmt.Appendf(nil, prStr, tc.prLifecycle), &pr)) fc := &fakeClient{} reconciler := &PackageVariantReconciler{Client: fc} @@ -966,7 +966,7 @@ items: var pv api.PackageVariant require.NoError(t, yaml.Unmarshal( - []byte(fmt.Sprintf(pvStr, tc.adoptionPolicy)), &pv)) + fmt.Appendf(nil, pvStr, tc.adoptionPolicy), &pv)) actualStr := reconciler.getDownstreamPRs(context.TODO(), &pv, &prList) var actual []string diff --git a/controllers/packagevariantsets/pkg/controllers/packagevariantset/render.go b/controllers/packagevariantsets/pkg/controllers/packagevariantset/render.go index 398c11a39..8d4f8b4a4 100644 --- a/controllers/packagevariantsets/pkg/controllers/packagevariantset/render.go +++ b/controllers/packagevariantsets/pkg/controllers/packagevariantset/render.go @@ -17,6 +17,7 @@ package packagevariantset import ( "context" "fmt" + "maps" "reflect" "slices" @@ -245,9 +246,7 @@ func objectToInput(obj any) (map[string]any, error) { func copyAndOverlayMapExpr(fieldName string, inMap map[string]string, mapExprs []api.MapExpr, inputs map[string]any) (map[string]string, error) { outMap := make(map[string]string, len(inMap)) - for k, v := range inMap { - outMap[k] = v - } + maps.Copy(outMap, inMap) var err error for i, me := range mapExprs { diff --git a/controllers/packagevariantsets/pkg/controllers/packagevariantset/render_test.go b/controllers/packagevariantsets/pkg/controllers/packagevariantset/render_test.go index 0e3d67b29..2cdf95c36 100644 --- a/controllers/packagevariantsets/pkg/controllers/packagevariantset/render_test.go +++ b/controllers/packagevariantsets/pkg/controllers/packagevariantset/render_test.go @@ -16,6 +16,7 @@ package packagevariantset import ( "context" + "maps" "testing" kptfilev1 "github.com/kptdev/kpt/api/kptfile/v1" @@ -24,7 +25,6 @@ import ( api "github.com/kptdev/porch/api/porchconfig/v1alpha2" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" "sigs.k8s.io/yaml" ) @@ -105,7 +105,7 @@ func TestRenderPackageVariantSpec(t *testing.T) { packageDefault: "p", template: &api.PackageVariantTemplate{ Downstream: &api.DownstreamTemplate{ - Repo: ptr.To("my-repo-2"), + Repo: new("my-repo-2"), }, }, }, @@ -124,7 +124,7 @@ func TestRenderPackageVariantSpec(t *testing.T) { packageDefault: "p", template: &api.PackageVariantTemplate{ Downstream: &api.DownstreamTemplate{ - Package: ptr.To("new-p"), + Package: new("new-p"), }, }, }, @@ -223,8 +223,8 @@ func TestRenderPackageVariantSpec(t *testing.T) { packageDefault: "p", template: &api.PackageVariantTemplate{ Downstream: &api.DownstreamTemplate{ - RepoExpr: ptr.To("'my-repo-2'"), - PackageExpr: ptr.To("repoDefault + '-' + packageDefault"), + RepoExpr: new("'my-repo-2'"), + PackageExpr: new("repoDefault + '-' + packageDefault"), }, }, }, @@ -243,8 +243,8 @@ func TestRenderPackageVariantSpec(t *testing.T) { packageDefault: "p", template: &api.PackageVariantTemplate{ Downstream: &api.DownstreamTemplate{ - RepoExpr: ptr.To("'my-repo-2'"), - PackageExpr: ptr.To("repoDefault + '-' + packageDefault"), + RepoExpr: new("'my-repo-2'"), + PackageExpr: new("repoDefault + '-' + packageDefault"), }, Labels: map[string]string{ "foo": "bar", @@ -252,16 +252,16 @@ func TestRenderPackageVariantSpec(t *testing.T) { }, LabelExprs: []api.MapExpr{ { - Key: ptr.To("foo"), - ValueExpr: ptr.To("repoDefault"), + Key: new("foo"), + ValueExpr: new("repoDefault"), }, { - KeyExpr: ptr.To("repository.labels['efg']"), - ValueExpr: ptr.To("packageDefault + '-' + repository.name"), + KeyExpr: new("repository.labels['efg']"), + ValueExpr: new("packageDefault + '-' + repository.name"), }, { - Key: ptr.To("hello"), - Value: ptr.To("goodbye"), + Key: new("hello"), + Value: new("goodbye"), }, }, Annotations: map[string]string{ @@ -270,12 +270,12 @@ func TestRenderPackageVariantSpec(t *testing.T) { }, AnnotationExprs: []api.MapExpr{ { - Key: ptr.To("foo.org/id"), - Value: ptr.To("54321"), + Key: new("foo.org/id"), + Value: new("54321"), }, { - Key: ptr.To("bigco.com/team"), - ValueExpr: ptr.To("upstream.annotations['bigco.com/team']"), + Key: new("bigco.com/team"), + ValueExpr: new("upstream.annotations['bigco.com/team']"), }, }, }, @@ -311,16 +311,16 @@ func TestRenderPackageVariantSpec(t *testing.T) { }, DataExprs: []api.MapExpr{ { - Key: ptr.To("foo"), - ValueExpr: ptr.To("upstream.name"), + Key: new("foo"), + ValueExpr: new("upstream.name"), }, { - KeyExpr: ptr.To("upstream.namespace"), - ValueExpr: ptr.To("upstream.name"), + KeyExpr: new("upstream.namespace"), + ValueExpr: new("upstream.name"), }, { - KeyExpr: ptr.To("upstream.name"), - Value: ptr.To("foo"), + KeyExpr: new("upstream.name"), + Value: new("foo"), }, }, RemoveKeys: []string{"foobar", "barfoo"}, @@ -353,19 +353,19 @@ func TestRenderPackageVariantSpec(t *testing.T) { template: &api.PackageVariantTemplate{ Injectors: []api.InjectionSelectorTemplate{ { - Group: ptr.To("kpt.dev"), - Version: ptr.To("v1alpha1"), - Kind: ptr.To("Foo"), - Name: ptr.To("bar"), + Group: new("kpt.dev"), + Version: new("v1alpha1"), + Kind: new("Foo"), + Name: new("bar"), }, { - Group: ptr.To("kpt.dev"), - Version: ptr.To("v1alpha1"), - Kind: ptr.To("Foo"), - NameExpr: ptr.To("repository.labels['abc']"), + Group: new("kpt.dev"), + Version: new("v1alpha1"), + Kind: new("Foo"), + NameExpr: new("repository.labels['abc']"), }, { - NameExpr: ptr.To("repository.name + '-test'"), + NameExpr: new("repository.name + '-test'"), }, }, }, @@ -378,15 +378,15 @@ func TestRenderPackageVariantSpec(t *testing.T) { }, Injectors: []configapi.InjectionSelector{ { - Group: ptr.To("kpt.dev"), - Version: ptr.To("v1alpha1"), - Kind: ptr.To("Foo"), + Group: new("kpt.dev"), + Version: new("v1alpha1"), + Kind: new("Foo"), Name: "bar", }, { - Group: ptr.To("kpt.dev"), - Version: ptr.To("v1alpha1"), - Kind: ptr.To("Foo"), + Group: new("kpt.dev"), + Version: new("v1alpha1"), + Kind: new("Foo"), Name: "def", }, { @@ -419,12 +419,12 @@ func TestRenderPackageVariantSpec(t *testing.T) { }, ConfigMapExprs: []api.MapExpr{ { - Key: ptr.To("k1"), - ValueExpr: ptr.To("repository.name"), + Key: new("k1"), + ValueExpr: new("repository.name"), }, { - KeyExpr: ptr.To("'k3'"), - Value: ptr.To("bar"), + KeyExpr: new("'k3'"), + Value: new("bar"), }, }, }, @@ -436,8 +436,8 @@ func TestRenderPackageVariantSpec(t *testing.T) { }, ConfigMapExprs: []api.MapExpr{ { - Key: ptr.To("k1"), - Value: ptr.To("yo"), + Key: new("k1"), + Value: new("yo"), }, }, }, @@ -559,9 +559,7 @@ func TestEvalExpr(t *testing.T) { for tn, tc := range testCases { t.Run(tn, func(t *testing.T) { inputs := map[string]any{} - for k, v := range baseInputs { - inputs[k] = v - } + maps.Copy(inputs, baseInputs) inputs["target"] = tc.target val, err := evalExpr(tc.expr, inputs) if tc.expectedErr == "" { @@ -590,16 +588,16 @@ func TestCopyAndOverlayMapExpr(t *testing.T) { inMap: map[string]string{}, mapExprs: []api.MapExpr{ { - Key: ptr.To("foo"), - Value: ptr.To("bar"), + Key: new("foo"), + Value: new("bar"), }, { - KeyExpr: ptr.To("repoDefault"), - Value: ptr.To("barbar"), + KeyExpr: new("repoDefault"), + Value: new("barbar"), }, { - Key: ptr.To("bar"), - ValueExpr: ptr.To("packageDefault"), + Key: new("bar"), + ValueExpr: new("packageDefault"), }, }, expectedResult: map[string]string{ @@ -615,12 +613,12 @@ func TestCopyAndOverlayMapExpr(t *testing.T) { }, mapExprs: []api.MapExpr{ { - Key: ptr.To("foo"), - Value: ptr.To("new-bar"), + Key: new("foo"), + Value: new("new-bar"), }, { - Key: ptr.To("foofoo"), - Value: ptr.To("barbar"), + Key: new("foofoo"), + Value: new("barbar"), }, }, expectedResult: map[string]string{ @@ -636,12 +634,12 @@ func TestCopyAndOverlayMapExpr(t *testing.T) { }, mapExprs: []api.MapExpr{ { - KeyExpr: ptr.To("'foo'"), - Value: ptr.To("new-bar"), + KeyExpr: new("'foo'"), + Value: new("new-bar"), }, { - Key: ptr.To("bar"), - ValueExpr: ptr.To("packageDefault"), + Key: new("bar"), + ValueExpr: new("packageDefault"), }, }, expectedResult: map[string]string{ diff --git a/controllers/repositories/pkg/controllers/repository/pkgrevsync.go b/controllers/repositories/pkg/controllers/repository/pkgrevsync.go index cc8a64a79..9cf055596 100644 --- a/controllers/repositories/pkg/controllers/repository/pkgrevsync.go +++ b/controllers/repositories/pkg/controllers/repository/pkgrevsync.go @@ -23,7 +23,6 @@ import ( "github.com/kptdev/porch/pkg/repository" "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" ) @@ -292,8 +291,8 @@ func buildPackageRevision(ctx context.Context, repo *configapi.Repository, pkgRe Kind: configapi.TypeRepository.Kind, Name: repo.Name, UID: repo.UID, - Controller: ptr.To(true), - BlockOwnerDeletion: ptr.To(true), + Controller: new(true), + BlockOwnerDeletion: new(true), }, }, }, diff --git a/controllers/repositories/pkg/controllers/repository/repository_controller_test.go b/controllers/repositories/pkg/controllers/repository/repository_controller_test.go index c40be2f06..411c34f21 100644 --- a/controllers/repositories/pkg/controllers/repository/repository_controller_test.go +++ b/controllers/repositories/pkg/controllers/repository/repository_controller_test.go @@ -105,7 +105,6 @@ func TestEnsureFinalizer(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() repo := tt.repo.DeepCopy() diff --git a/func/internal/podcachemanager.go b/func/internal/podcachemanager.go index 38e7a8a3d..1feb54205 100644 --- a/func/internal/podcachemanager.go +++ b/func/internal/podcachemanager.go @@ -415,7 +415,7 @@ func (pcm *podCacheManager) findBestPod(fn *functionInfo) (int, int) { } // Round-robin among pods that have the minimum waitlist length - for i := 0; i < n; i++ { + for i := range n { idx := (fn.roundRobinIdx + i) % n if fn.pods[idx].WaitlistLen() == minWaitlist { fn.roundRobinIdx = (idx + 1) % n diff --git a/func/internal/podevaluator_podcachemanager_test.go b/func/internal/podevaluator_podcachemanager_test.go index a6a385928..2e9b94ce2 100644 --- a/func/internal/podevaluator_podcachemanager_test.go +++ b/func/internal/podevaluator_podcachemanager_test.go @@ -19,6 +19,7 @@ package internal import ( "context" "flag" + "maps" "net" "strings" "sync" @@ -33,7 +34,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/klog/v2" "k8s.io/klog/v2/ktesting" - "k8s.io/utils/ptr" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -236,8 +236,8 @@ func TestPodCacheManager(t *testing.T) { pData := podData{ image: defaultImageName, grpcConnection: grpcClient, - podKey: ptr.To(client.ObjectKeyFromObject(defaultPodObject)), - serviceKey: ptr.To(client.ObjectKeyFromObject(defaultServiceObject)), + podKey: new(client.ObjectKeyFromObject(defaultPodObject)), + serviceKey: new(client.ObjectKeyFromObject(defaultServiceObject)), } funcPodInfo := NewPodInfo(nil) @@ -370,9 +370,7 @@ func TestPodCacheManager(t *testing.T) { klog.SetLogger(logger) pcm.functions = make(map[string]*functionInfo) - for k, v := range tt.functions { - pcm.functions[k] = v - } + maps.Copy(pcm.functions, tt.functions) pcm.podManager.kubeClient = tt.kubeClient if !tt.skipRetrieve { @@ -490,9 +488,7 @@ func TestPodCacheManager(t *testing.T) { } pcm.functions = make(map[string]*functionInfo) - for k, v := range tt.functions { - pcm.functions[k] = v - } + maps.Copy(pcm.functions, tt.functions) pcm.podManager.kubeClient = tt.kubeClient diff --git a/func/internal/podevaluator_podmanager_test.go b/func/internal/podevaluator_podmanager_test.go index 81052ab71..aa6c0d9d3 100644 --- a/func/internal/podevaluator_podmanager_test.go +++ b/func/internal/podevaluator_podmanager_test.go @@ -587,8 +587,7 @@ func TestPodManager(t *testing.T) { t.SkipNow() } - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() //Set up the pod manager podReadyCh := make(chan *podReadyResponse) pm := &podManager{ diff --git a/func/internal/podevaluator_porch_parallel_execution_test.go b/func/internal/podevaluator_porch_parallel_execution_test.go index e68802948..6ad0846ba 100644 --- a/func/internal/podevaluator_porch_parallel_execution_test.go +++ b/func/internal/podevaluator_porch_parallel_execution_test.go @@ -27,7 +27,6 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -69,8 +68,7 @@ func startFakeServer(ctx context.Context, t *testing.T, delay time.Duration, log func TestPodEvaluatorExecutionParallel(t *testing.T) { const sleep = 2 * time.Second - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() addr, err := startFakeServer(ctx, t, sleep, "") if err != nil { @@ -96,7 +94,7 @@ func TestPodEvaluatorExecutionParallel(t *testing.T) { podData: podData{ image: req.image, grpcConnection: conn, - podKey: ptr.To(client.ObjectKey{}), + podKey: new(client.ObjectKey{}), }, concurrentEvaluations: counter, err: nil, diff --git a/func/internal/podevaluator_tag_resolution_test.go b/func/internal/podevaluator_tag_resolution_test.go index bf050cf6f..105799d4b 100644 --- a/func/internal/podevaluator_tag_resolution_test.go +++ b/func/internal/podevaluator_tag_resolution_test.go @@ -28,7 +28,6 @@ import ( "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" - ptr "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -86,7 +85,7 @@ func TestTagResolution(t *testing.T) { podData: podData{ image: req.image, grpcConnection: conn, - podKey: ptr.To(client.ObjectKey{}), + podKey: new(client.ObjectKey{}), }, concurrentEvaluations: counter, err: nil, @@ -134,7 +133,7 @@ func TestTagResolution(t *testing.T) { podData: podData{ image: req.image, grpcConnection: conn, - podKey: ptr.To(client.ObjectKey{}), + podKey: new(client.ObjectKey{}), }, concurrentEvaluations: counter, err: nil, diff --git a/func/server/server.go b/func/server/server.go index 5336a556b..a52b797a2 100644 --- a/func/server/server.go +++ b/func/server/server.go @@ -139,8 +139,8 @@ func run(o *options) error { podRuntime: {}, } if o.disableRuntimes != "" { - runtimesFromFlag := strings.Split(o.disableRuntimes, ",") - for _, rt := range runtimesFromFlag { + runtimesFromFlag := strings.SplitSeq(o.disableRuntimes, ",") + for rt := range runtimesFromFlag { delete(availableRuntimes, rt) } } diff --git a/internal/telemetry/otel_test.go b/internal/telemetry/otel_test.go index 05deab3e1..340a0160d 100644 --- a/internal/telemetry/otel_test.go +++ b/internal/telemetry/otel_test.go @@ -72,8 +72,7 @@ func TestPrometheusHTTPServer(t *testing.T) { legacyCounter.Inc() defer legacyregistry.Reset() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() res, err := SetupOpenTelemetry(ctx) require.NoError(t, err) @@ -121,8 +120,7 @@ func TestOtelMetricsPushHTTP(t *testing.T) { t.Setenv(ENV_OTEL_EXPORTER_OTLP_ENDPOINT, ts.URL) t.Setenv(ENV_OTEL_EXPORTER_OTLP_PROTOCOL, "http/protobuf") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() res, err := SetupOpenTelemetry(ctx) require.NoError(t, err) @@ -143,8 +141,7 @@ func TestOtelTracesPushHTTP(t *testing.T) { t.Setenv(ENV_OTEL_EXPORTER_OTLP_ENDPOINT, ts.URL) t.Setenv(ENV_OTEL_EXPORTER_OTLP_PROTOCOL, "http/protobuf") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() res, err := SetupOpenTelemetry(ctx) require.NoError(t, err) @@ -162,8 +159,7 @@ func TestSetupOpenTelemetryPrometheusEndpoint(t *testing.T) { t.Setenv(ENV_OTEL_METRICS_EXPORTER, METRICS_EXPORTER_PROMETHEUS) t.Setenv(ENV_OTEL_TRACES_EXPORTER, DEFAULT_OTEL_TRACES_EXPORTER) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() res, err := SetupOpenTelemetry(ctx) require.NoError(t, err) @@ -198,8 +194,7 @@ func TestOtelMetricsPushGRPC(t *testing.T) { t.Setenv(ENV_OTEL_EXPORTER_OTLP_ENDPOINT, fmt.Sprintf("http://localhost:%d", lis.Addr().(*net.TCPAddr).Port)) t.Setenv(ENV_OTEL_EXPORTER_OTLP_PROTOCOL, "grpc") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() res, err := SetupOpenTelemetry(ctx) require.NoError(t, err) @@ -230,8 +225,7 @@ func TestOtelTracesPushGRPC(t *testing.T) { t.Setenv(ENV_OTEL_EXPORTER_OTLP_ENDPOINT, fmt.Sprintf("http://localhost:%d", lis.Addr().(*net.TCPAddr).Port)) t.Setenv(ENV_OTEL_EXPORTER_OTLP_PROTOCOL, "grpc") - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() res, err := SetupOpenTelemetry(ctx) require.NoError(t, err) diff --git a/make/go.mk b/make/go.mk index 6214e3af5..0a73884be 100644 --- a/make/go.mk +++ b/make/go.mk @@ -29,7 +29,7 @@ vet: vet-api ## Run go vet against the codebase .PHONY: fix fix: fix-api ## Run go fix against the codebase - go fix ./... + go fix -omitzero=false ./... .PHONY: lint lint: lint-api ## Run Go linter against the codebase diff --git a/make/security.mk b/make/security.mk index f5502add2..005bd7815 100644 --- a/make/security.mk +++ b/make/security.mk @@ -1,4 +1,4 @@ -# Copyright 2025 The kpt Authors +# Copyright 2025-2026 The kpt Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,65 +14,39 @@ # Security scanning tools -##@ Security - -# Gosec configuration -GOSEC_IMAGE := securego/gosec:2.23.0 +GOSEC_VERSION ?= 2.23.0 # Gosec exclusions: # G401,G501,G505: Weak crypto (MD5/SHA1) - used for non-security purposes (git hashes, etags) # G304: File path from variable - unavoidable in file operations GOSEC_EXCLUDES := G401,G501,G505,G304 +GOSEC_ARGS ?= -stdout -verbose=text \ + -exclude-dir=generated \ + -exclude-dir=test \ + -exclude-dir=third_party \ + -exclude-dir=examples \ + -exclude-dir=internal/kpt \ + -exclude-generated \ + -severity=medium \ + -exclude=$(GOSEC_EXCLUDES) + +##@ Security .PHONY: gosec gosec: ## Inspect the source code for security problems by scanning the Go Abstract Syntax Tree -ifeq ($(CONTAINER_RUNNABLE), 0) - $(RUN_CONTAINER_COMMAND) $(GOSEC_IMAGE) \ - -fmt=html \ - -out=gosec-results.html \ - -stdout -verbose=text \ - -exclude-dir=generated \ - -exclude-dir=test \ - -exclude-dir=third_party \ - -exclude-dir=examples \ - -exclude-dir=internal/kpt \ - -exclude-generated \ - -severity=medium \ - -exclude=$(GOSEC_EXCLUDES) ./... -else - gosec -fmt=html -out=gosec-results.html -stdout -verbose=text \ - -exclude-dir=generated \ - -exclude-dir=third_party \ - -exclude-dir=test \ - -exclude-dir=examples \ - -exclude-dir=internal/kpt \ - -exclude-generated \ - -severity=medium \ - -exclude=$(GOSEC_EXCLUDES) ./... -endif + @if command -v gosec >/dev/null 2>&1; then \ + gosec -fmt=html -out=gosec-results.html $(GOSEC_ARGS) ./...; \ + else \ + go run github.com/securego/gosec/v2/cmd/gosec@v$(GOSEC_VERSION) -fmt=html -out=gosec-results.html $(GOSEC_ARGS) ./...; \ + fi .PHONY: gosec-sarif -gosec-sarif: ## Generate SARIF security report -ifeq ($(CONTAINER_RUNNABLE), 0) - $(RUN_CONTAINER_COMMAND) -e GOTOOLCHAIN=auto $(GOSEC_IMAGE) \ - -fmt=sarif \ - -out=gosec-results.sarif \ - -stdout -verbose=text \ - -exclude-dir=generated \ - -exclude-dir=test \ - -exclude-dir=third_party \ - -exclude-dir=examples \ - -exclude-dir=internal/kpt \ - -exclude-generated \ - -severity=medium \ - -exclude=$(GOSEC_EXCLUDES) ./... -else - GOTOOLCHAIN=auto gosec -fmt=sarif -out=gosec-results.sarif -stdout -verbose=text \ - -exclude-dir=generated \ - -exclude-dir=third_party \ - -exclude-dir=test \ - -exclude-dir=examples \ - -exclude-dir=internal/kpt \ - -exclude-generated \ - -severity=medium \ - -exclude=$(GOSEC_EXCLUDES) ./... -endif \ No newline at end of file +gosec-sarif: ## Generate SARIF security report + @if command -v gosec >/dev/null 2>&1; then \ + gosec -fmt=sarif -out=gosec-results.sarif $(GOSEC_ARGS) ./...; \ + else \ + go run github.com/securego/gosec/v2/cmd/gosec@v$(GOSEC_VERSION) -fmt=sarif -out=gosec-results.sarif $(GOSEC_ARGS) ./...; \ + fi + +.PHONY: install-gosec +install-gosec: ## Install the version of gosec used by the CI locally + go install github.com/securego/gosec/v2/cmd/gosec@v$(GOSEC_VERSION) diff --git a/make/work.mk b/make/work.mk new file mode 100644 index 000000000..c00a6b255 --- /dev/null +++ b/make/work.mk @@ -0,0 +1,23 @@ +# Copyright 2026 The kpt Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +##@ Workspace + +go.work: ## Initialize the go workspace + go work init + go work use . api docs + +.PHONY: +clean-work: ## Removes the workspace file + rm -f go.work go.work.sum diff --git a/pkg/apiserver/porchserver.go b/pkg/apiserver/porchserver.go index 79fa2b08a..7c2c191df 100644 --- a/pkg/apiserver/porchserver.go +++ b/pkg/apiserver/porchserver.go @@ -36,7 +36,6 @@ var _ manager.Runnable = &PorchServer{} var _ manager.LeaderElectionRunnable = &PorchServer{} func (s *PorchServer) Start(ctx context.Context) error { - return s.GenericAPIServer.PrepareRun().RunWithContext(ctx) } diff --git a/pkg/cache/crcache/packagerevision.go b/pkg/cache/crcache/packagerevision.go index 536812806..58805f844 100644 --- a/pkg/cache/crcache/packagerevision.go +++ b/pkg/cache/crcache/packagerevision.go @@ -16,6 +16,7 @@ package crcache import ( "context" + "maps" "sync" "time" @@ -75,9 +76,7 @@ func (c *cachedPackageRevision) GetPackageRevision(ctx context.Context) (*porcha if latest { // copy the labels in case the cached object is being read by another go routine labels := make(map[string]string, len(apiPR.Labels)) - for k, v := range apiPR.Labels { - labels[k] = v - } + maps.Copy(labels, apiPR.Labels) labels[porchapi.LatestPackageRevisionKey] = porchapi.LatestPackageRevisionValue apiPR.Labels = labels } diff --git a/pkg/cache/repomap/saferepomap_test.go b/pkg/cache/repomap/saferepomap_test.go index 8e6de625a..7a24a3784 100644 --- a/pkg/cache/repomap/saferepomap_test.go +++ b/pkg/cache/repomap/saferepomap_test.go @@ -97,7 +97,7 @@ func TestLoadOrCreate_Concurrent(t *testing.T) { var wg sync.WaitGroup results := make([]repository.Repository, goroutines) - for i := 0; i < goroutines; i++ { + for i := range goroutines { wg.Add(1) go func(idx int) { defer wg.Done() @@ -131,13 +131,11 @@ func TestLoadOrCreate_ConcurrentError(t *testing.T) { const goroutines = 5 var wg sync.WaitGroup - for i := 0; i < goroutines; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range goroutines { + wg.Go(func() { _, err := m.LoadOrCreate(key, create) assert.Error(t, err) - }() + }) } wg.Wait() diff --git a/pkg/cli/commands/repo/sync/command_test.go b/pkg/cli/commands/repo/sync/command_test.go index 29195a37d..a9de2c859 100644 --- a/pkg/cli/commands/repo/sync/command_test.go +++ b/pkg/cli/commands/repo/sync/command_test.go @@ -48,7 +48,7 @@ func setupTestRunner(flags map[string]string, namespace string, client client.Cl ctx: context.Background(), Command: cmd, getFlags: cmdutil.Options{ - ConfigFlags: &genericclioptions.ConfigFlags{Namespace: strPtr(namespace)}, + ConfigFlags: &genericclioptions.ConfigFlags{Namespace: new(namespace)}, }, printFlags: &get.PrintFlags{ HumanReadableFlags: &get.HumanPrintFlags{}, @@ -57,10 +57,6 @@ func setupTestRunner(flags map[string]string, namespace string, client client.Cl } } -func strPtr(s string) *string { - return &s -} - func TestRunE_VariousRunOnceScenarios(t *testing.T) { scheme := runtime.NewScheme() _ = configapi.AddToScheme(scheme) @@ -450,7 +446,7 @@ func TestRunE_MixedSyncStates(t *testing.T) { func TestNewRunnerInitialization(t *testing.T) { ctx := context.Background() - configFlags := &genericclioptions.ConfigFlags{Namespace: strPtr("default")} + configFlags := &genericclioptions.ConfigFlags{Namespace: new("default")} r := newRunner(ctx, configFlags) @@ -483,8 +479,8 @@ func TestRunE_ClientCreationFailure(t *testing.T) { ctx: context.Background(), getFlags: cmdutil.Options{ ConfigFlags: &genericclioptions.ConfigFlags{ - KubeConfig: strPtr("/invalid/path/to/kubeconfig"), - Namespace: strPtr("default"), + KubeConfig: new("/invalid/path/to/kubeconfig"), + Namespace: new("default"), }, }, client: nil, // Force client creation diff --git a/pkg/engine/builtinruntime.go b/pkg/engine/builtinruntime.go index 4555719e1..46789d8c4 100644 --- a/pkg/engine/builtinruntime.go +++ b/pkg/engine/builtinruntime.go @@ -59,7 +59,7 @@ func (br *builtinRuntime) GetRunner(ctx context.Context, funct *kptfilev1.Functi // so FindBestSemverMatch gets a bare repository name, and // we don't produce a double-tag if ref.Tag != "" { - if stripped := strings.TrimSuffix(funct.Image, ":"+ref.Tag); stripped != funct.Image { + if stripped, ok := strings.CutSuffix(funct.Image, ":"+ref.Tag); ok { klog.Infof("Image %q already contains tag %q; stripping it in favor of Tag constraint %q", funct.Image, ref.Tag, funct.Tag) funct.Image = stripped } diff --git a/pkg/externalrepo/git/annotation.go b/pkg/externalrepo/git/annotation.go index fdd6bb0d2..7cb81b52a 100644 --- a/pkg/externalrepo/git/annotation.go +++ b/pkg/externalrepo/git/annotation.go @@ -53,7 +53,7 @@ func extractGitAnnotations(commit *object.Commit) ([]gitAnnotation, error) { annotations := []gitAnnotation{} ec := errors.NewErrorCollector().WithSeparator(";").WithFormat("{%s}") - for _, line := range strings.Split(commit.Message, "\n") { + for line := range strings.SplitSeq(commit.Message, "\n") { line = strings.TrimSpace(line) if strings.HasPrefix(line, "kpt:") { annotation := gitAnnotation{} diff --git a/pkg/externalrepo/git/branchcommithash_test.go b/pkg/externalrepo/git/branchcommithash_test.go index df51df723..528e0d4ca 100644 --- a/pkg/externalrepo/git/branchcommithash_test.go +++ b/pkg/externalrepo/git/branchcommithash_test.go @@ -146,7 +146,7 @@ func TestBranchCommitHashConcurrency(t *testing.T) { results := make(chan string, numGoroutines) errors := make(chan error, numGoroutines) - for i := 0; i < numGoroutines; i++ { + for range numGoroutines { go func() { hash, err := repo.BranchCommitHash(ctx) if err != nil { @@ -159,7 +159,7 @@ func TestBranchCommitHashConcurrency(t *testing.T) { // Collect results var hashes []string - for i := 0; i < numGoroutines; i++ { + for range numGoroutines { select { case hash := <-results: hashes = append(hashes, hash) diff --git a/pkg/externalrepo/git/cachedir_pool_test.go b/pkg/externalrepo/git/cachedir_pool_test.go index 9e91de80d..cc244f40c 100644 --- a/pkg/externalrepo/git/cachedir_pool_test.go +++ b/pkg/externalrepo/git/cachedir_pool_test.go @@ -130,7 +130,7 @@ func TestDirectoryPool_ConcurrentAccess(t *testing.T) { numGoroutines := 10 // Concurrent creation - for i := 0; i < numGoroutines; i++ { + for i := range numGoroutines { wg.Add(1) go func(id int) { defer wg.Done() @@ -147,12 +147,10 @@ func TestDirectoryPool_ConcurrentAccess(t *testing.T) { assert.Equal(t, numGoroutines, shared.refCount) // Concurrent release - for i := 0; i < numGoroutines; i++ { - wg.Add(1) - go func() { - defer wg.Done() + for range numGoroutines { + wg.Go(func() { pool.releaseSharedRepository(repoDir, "concurrent-repo") - }() + }) } wg.Wait() diff --git a/pkg/externalrepo/git/ref.go b/pkg/externalrepo/git/ref.go index 94dfc31cb..2e23c9ef5 100644 --- a/pkg/externalrepo/git/ref.go +++ b/pkg/externalrepo/git/ref.go @@ -131,8 +131,8 @@ func createDeletionProposedName(key repository.PackageRevisionKey) branchName { } func trimOptionalPrefix(s, prefix string) (string, bool) { - if strings.HasPrefix(s, prefix) { - return strings.TrimPrefix(s, prefix), true + if after, ok := strings.CutPrefix(s, prefix); ok { + return after, true } return "", false } diff --git a/pkg/objects/extract.go b/pkg/objects/extract.go index c4dc75663..b13698ac9 100644 --- a/pkg/objects/extract.go +++ b/pkg/objects/extract.go @@ -61,7 +61,7 @@ func (p Parser) AsObjectList(resources map[string]string) (*ObjectList, error) { continue } // TODO: Use https://github.com/kubernetes-sigs/kustomize/blob/a5b61016bb40c30dd1b0a78290b28b2330a0383e/kyaml/kio/byteio_reader.go#L170 or similar? - for _, s := range strings.Split(fileContents, "\n---\n") { + for s := range strings.SplitSeq(fileContents, "\n---\n") { if isWhitespace(s) { continue } diff --git a/pkg/registry/porch/packagerevision_test.go b/pkg/registry/porch/packagerevision_test.go index da60bf2c4..f2caac0d6 100644 --- a/pkg/registry/porch/packagerevision_test.go +++ b/pkg/registry/porch/packagerevision_test.go @@ -476,8 +476,7 @@ func TestWatch(t *testing.T) { mockEngine.On("ObjectCache").Return(mockWatcherManager).Maybe() mockWatcherManager.On("WatchPackageRevisions", mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("error starting watch")).Maybe() - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() w, err := packagerevisions.Watch(ctx, &internalversion.ListOptions{}) require.NoError(t, err) diff --git a/pkg/registry/porch/userinfo.go b/pkg/registry/porch/userinfo.go index 7376ab6e2..145cecb36 100644 --- a/pkg/registry/porch/userinfo.go +++ b/pkg/registry/porch/userinfo.go @@ -16,6 +16,7 @@ package porch import ( "context" + "slices" "github.com/kptdev/porch/pkg/repository" "k8s.io/apiserver/pkg/authentication/user" @@ -37,12 +38,10 @@ func (p *ApiserverUserInfoProvider) GetUserInfo(ctx context.Context) *repository return nil } - for _, group := range userinfo.GetGroups() { - if group == user.AllAuthenticated { - return &repository.UserInfo{ - Name: name, // k8s authentication only provides single name; use it for both values for now. - Email: name, - } + if slices.Contains(userinfo.GetGroups(), user.AllAuthenticated) { + return &repository.UserInfo{ + Name: name, // k8s authentication only provides single name; use it for both values for now. + Email: name, } } diff --git a/pkg/registry/porch/watch_test.go b/pkg/registry/porch/watch_test.go index e65741669..86f6c1077 100644 --- a/pkg/registry/porch/watch_test.go +++ b/pkg/registry/porch/watch_test.go @@ -34,7 +34,6 @@ import ( "k8s.io/apiserver/pkg/features" utilfeature "k8s.io/apiserver/pkg/util/feature" featuregatetesting "k8s.io/component-base/featuregate/testing" - "k8s.io/utils/ptr" ) // Helper to create fake package revisions @@ -346,7 +345,7 @@ func TestCreateGenericWatch410OnPlainWatchResume(t *testing.T) { name: "initial list with sendInitialEvents=true and resourceVersion", options: &metainternalversion.ListOptions{ ResourceVersion: "some-rv.12345", - SendInitialEvents: ptr.To(true), + SendInitialEvents: new(true), AllowWatchBookmarks: true, }, expect410: false, @@ -370,7 +369,7 @@ func TestCreateGenericWatch410OnPlainWatchResume(t *testing.T) { name: "sendInitialEvents=false with resourceVersion", options: &metainternalversion.ListOptions{ ResourceVersion: "some-rv.12345", - SendInitialEvents: ptr.To(false), + SendInitialEvents: new(false), }, expect410: true, description: "sendInitialEvents=false with a resourceVersion is still a plain resume - porch cannot fulfill this", @@ -387,8 +386,7 @@ func TestCreateGenericWatch410OnPlainWatchResume(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() r := &fakePackageReader{} r.Add(1) @@ -427,8 +425,7 @@ func TestCreateGenericWatch410OnPlainWatchResume(t *testing.T) { func TestCreateGenericWatchNoGoneWhenWatchListDisabled(t *testing.T) { featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.WatchList, false) - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() r := &fakePackageReader{} r.Add(1) @@ -503,7 +500,7 @@ func TestCreateGenericWatchAllowsWatchWithSendInitialEvents(t *testing.T) { options := &metainternalversion.ListOptions{ ResourceVersion: "old-rv.12345", - SendInitialEvents: ptr.To(true), + SendInitialEvents: new(true), AllowWatchBookmarks: true, } diff --git a/pkg/registry/porch/wi/wi.go b/pkg/registry/porch/wi/wi.go index 5344743fc..1e2ed9da5 100644 --- a/pkg/registry/porch/wi/wi.go +++ b/pkg/registry/porch/wi/wi.go @@ -105,8 +105,8 @@ func (w *WITokenExchanger) findWorkloadIdentityPool(ctx context.Context, kubeSer return "", "", err } - if strings.HasPrefix(issuer, "https://container.googleapis.com/") { - path := strings.TrimPrefix(issuer, "https://container.googleapis.com/") + if after, ok := strings.CutPrefix(issuer, "https://container.googleapis.com/"); ok { + path := after tokens := strings.Split(path, "/") for i := 0; i+1 < len(tokens); i++ { if tokens[i] == "projects" { diff --git a/pkg/task/clone_test.go b/pkg/task/clone_test.go index 11bcf1188..c0ff63fd1 100644 --- a/pkg/task/clone_test.go +++ b/pkg/task/clone_test.go @@ -221,9 +221,7 @@ func startGitServer(t *testing.T, repo *gitserver.Repo, _ ...gitserver.GitServer addressChannel := make(chan net.Addr) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.ListenAndServe(ctx, "127.0.0.1:0", addressChannel) if err != nil { if err == http.ErrServerClosed { @@ -232,7 +230,7 @@ func startGitServer(t *testing.T, repo *gitserver.Repo, _ ...gitserver.GitServer t.Errorf("Git server exited with error: %v", err) } } - }() + }) // Wait for server to start up address, ok := <-addressChannel diff --git a/pkg/task/generictaskhandler.go b/pkg/task/generictaskhandler.go index a89f1bb6f..89f39beea 100644 --- a/pkg/task/generictaskhandler.go +++ b/pkg/task/generictaskhandler.go @@ -679,9 +679,7 @@ func healConfig(old, new map[string]string) (map[string]string, error) { healed := out.output.Contents - for k, v := range extra { - healed[k] = v - } + maps.Copy(healed, extra) return healed, nil } diff --git a/pkg/task/generictaskhandler_test.go b/pkg/task/generictaskhandler_test.go index 4a1e5560a..a6be4a49d 100644 --- a/pkg/task/generictaskhandler_test.go +++ b/pkg/task/generictaskhandler_test.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "maps" "strings" "testing" @@ -871,15 +872,11 @@ info: require.NoError(t, err) labels2 := kptf2.GetLabels() - for k, v := range obj2.Spec.PackageMetadata.Labels { - labels2[k] = v - } + maps.Copy(labels2, obj2.Spec.PackageMetadata.Labels) kptf2.SetLabels(labels2) annotations2 := kptf2.GetAnnotations() - for k, v := range obj2.Spec.PackageMetadata.Annotations { - annotations2[k] = v - } + maps.Copy(annotations2, obj2.Spec.PackageMetadata.Annotations) kptf2.SetAnnotations(annotations2) require.NoError(t, kptf2.WriteToPackage(resources2)) got2 := resources2["Kptfile"] diff --git a/pkg/task/mergekey.go b/pkg/task/mergekey.go index b5da66248..d772e83f6 100644 --- a/pkg/task/mergekey.go +++ b/pkg/task/mergekey.go @@ -17,6 +17,7 @@ package task import ( "context" "fmt" + "maps" "github.com/kptdev/kpt/pkg/lib/util/addmergecomment" "github.com/kptdev/porch/pkg/repository" @@ -51,9 +52,7 @@ func ensureMergeKey(_ context.Context, resources repository.PackageResources) (r return repository.PackageResources{}, fmt.Errorf("failed to add merge-key directive: %w", err) } - for k, v := range pr.extra { - result.Contents[k] = v - } + maps.Copy(result.Contents, pr.extra) return result, nil } diff --git a/pkg/task/pkgctxt.go b/pkg/task/pkgctxt.go index f6fd02a09..03ff65ee0 100644 --- a/pkg/task/pkgctxt.go +++ b/pkg/task/pkgctxt.go @@ -17,6 +17,7 @@ package task import ( "context" "fmt" + "maps" "github.com/kptdev/kpt/pkg/fn" "github.com/kptdev/kpt/pkg/lib/builtins" @@ -76,9 +77,7 @@ func (m *builtinEvalMutation) apply(ctx context.Context, resources repository.Pa return repository.PackageResources{}, nil, fmt.Errorf("failed to evaluate function %q: %w", m.function, err) } - for k, v := range pr.extra { - result.Contents[k] = v - } + maps.Copy(result.Contents, pr.extra) return result, &porchapi.TaskResult{}, nil } diff --git a/test/e2e/api/watch_test.go b/test/e2e/api/watch_test.go index c02a8eeed..3e4b4007a 100644 --- a/test/e2e/api/watch_test.go +++ b/test/e2e/api/watch_test.go @@ -17,6 +17,7 @@ package api import ( "context" "fmt" + "slices" "time" porchapi "github.com/kptdev/porch/api/porch/v1alpha1" @@ -236,13 +237,7 @@ func (t *PorchSuite) TestWatchCacheHealsAfterReconnect() { reconnectNames, _ := collectWatchNames(t, watcher2, ctx) // The reconnected watch should contain pkg-two (created while disconnected) - foundPkgTwo := false - for _, name := range reconnectNames { - if name == pr2.Name { - foundPkgTwo = true - break - } - } + foundPkgTwo := slices.Contains(reconnectNames, pr2.Name) assert.True(t.T(), foundPkgTwo, fmt.Sprintf("Reconnected watch with sendInitialEvents should include pkg-two (%s) that was created during disconnect. Got names: %v", pr2.Name, reconnectNames)) diff --git a/test/e2e/cli/cluster.go b/test/e2e/cli/cluster.go index f3c9adf92..11fd652fd 100644 --- a/test/e2e/cli/cluster.go +++ b/test/e2e/cli/cluster.go @@ -235,7 +235,7 @@ func RemovePackageRevisionFinalizers(t *testing.T, namespace string) { } } } - + t.Logf("Removing Finalizers from PackageRevisions: %v", packageRevisions) // Second pass: remove finalizers for _, pr := range packageRevisions { diff --git a/test/e2e/cli/suite.go b/test/e2e/cli/suite.go index 55f464202..c4874209f 100644 --- a/test/e2e/cli/suite.go +++ b/test/e2e/cli/suite.go @@ -577,8 +577,8 @@ func exitCode(exit error) int { func getRepoName(args []string) (string, bool) { for _, arg := range args { - if strings.HasPrefix(arg, "--name=") { - return strings.TrimPrefix(arg, "--name="), true + if after, ok := strings.CutPrefix(arg, "--name="); ok { + return after, true } } return "", false @@ -587,7 +587,7 @@ func getRepoName(args []string) (string, bool) { // parsePRNameFromOutput extracts a PackageRevision name from command output. // It looks for lines like "git.basens-clone.clone-1 created" and returns the name part. func parsePRNameFromOutput(output string) string { - for _, line := range strings.Split(strings.TrimSpace(output), "\n") { + for line := range strings.SplitSeq(strings.TrimSpace(output), "\n") { line = strings.TrimSpace(line) // Match patterns like " created", " updated", " proposed" for _, suffix := range []string{" created", " updated", " proposed", " approved", " rejected", " pushed"} { diff --git a/test/e2e/crd/helpers_test.go b/test/e2e/crd/helpers_test.go index 90da13dfe..64da8d4e6 100644 --- a/test/e2e/crd/helpers_test.go +++ b/test/e2e/crd/helpers_test.go @@ -31,7 +31,6 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -200,7 +199,7 @@ func registerV1Alpha2Repo(ctx context.Context, namespace, repoName string, opts Name: secretName, Namespace: namespace, }, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{ "username": []byte(giteaUser), "password": []byte(giteaPassword), diff --git a/test/e2e/crd/migration_rollback_test.go b/test/e2e/crd/migration_rollback_test.go index 8f5dcd45c..3a93c4e84 100644 --- a/test/e2e/crd/migration_rollback_test.go +++ b/test/e2e/crd/migration_rollback_test.go @@ -22,7 +22,6 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -64,7 +63,7 @@ var _ = Describe("Migration Rollback", Ordered, func() { secretName := repoName + "-auth" Expect(k8sClient.Create(sharedCtx, &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: secretName, Namespace: sharedNamespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, })).To(Succeed()) diff --git a/test/e2e/crd/migration_test.go b/test/e2e/crd/migration_test.go index bd773d44b..df691c721 100644 --- a/test/e2e/crd/migration_test.go +++ b/test/e2e/crd/migration_test.go @@ -25,7 +25,6 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -252,7 +251,7 @@ func registerV1Alpha1Repo(ctx context.Context, namespace, repoName string) { Name: secretName, Namespace: namespace, }, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{ "username": []byte(giteaUser), "password": []byte(giteaPassword), diff --git a/test/e2e/crd/repository_test.go b/test/e2e/crd/repository_test.go index 0d505a86e..fef0f123c 100644 --- a/test/e2e/crd/repository_test.go +++ b/test/e2e/crd/repository_test.go @@ -26,7 +26,6 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -210,7 +209,7 @@ var _ = Describe("Repository", Ordered, Label("infra"), func() { secretName := repoName + "-auth" secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: secretName, Namespace: env.Namespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } diff --git a/test/e2e/crd/validation_test.go b/test/e2e/crd/validation_test.go index 7be9281be..840f23ed3 100644 --- a/test/e2e/crd/validation_test.go +++ b/test/e2e/crd/validation_test.go @@ -22,7 +22,6 @@ import ( corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -62,7 +61,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { Name: secretName, Namespace: env.Namespace, }, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{ "username": []byte(giteaUser), "password": []byte(giteaPassword), @@ -165,7 +164,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("attempting to downgrade back to Draft with retries on conflict") var finalErr error const maxRetries = 3 - for i := 0; i < maxRetries; i++ { + for range maxRetries { prFresh := &porchv1alpha2.PackageRevision{} Expect(k8sClient.Get(env.Ctx, client.ObjectKeyFromObject(pr), prFresh)).To(Succeed()) prFresh.Spec.Lifecycle = porchv1alpha2.PackageRevisionLifecycleDraft @@ -197,7 +196,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("attempting to transition back to Proposed with retries on conflict") var finalErr error const maxRetries = 3 - for i := 0; i < maxRetries; i++ { + for range maxRetries { prFresh := &porchv1alpha2.PackageRevision{} Expect(k8sClient.Get(env.Ctx, client.ObjectKeyFromObject(pr), prFresh)).To(Succeed()) prFresh.Spec.Lifecycle = porchv1alpha2.PackageRevisionLifecycleProposed @@ -607,7 +606,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("creating auth secret for first repo") secret1 := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName1 + "-auth", Namespace: env.Namespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } @@ -641,7 +640,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { repoName2 := "conflict-repo-2" secret2 := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName2 + "-auth", Namespace: env.Namespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } @@ -682,7 +681,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("creating auth secret") secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName + "-auth", Namespace: env.Namespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } @@ -747,7 +746,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("creating auth secret") secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName + "-auth", Namespace: env.Namespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } @@ -813,7 +812,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { ns1 := env.Namespace secret1 := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName + "-auth", Namespace: ns1}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } @@ -853,7 +852,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("creating auth secret in second namespace") secret2 := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName + "-auth", Namespace: ns2}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } @@ -895,7 +894,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("creating auth secret") secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName + "-auth", Namespace: env.Namespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } @@ -960,7 +959,7 @@ var _ = Describe("Webhook Validation", Ordered, Label("validation"), func() { By("creating auth secret") secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{Name: repoName + "-auth", Namespace: env.Namespace}, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{"username": []byte(giteaUser), "password": []byte(giteaPassword)}, Type: corev1.SecretTypeBasicAuth, } diff --git a/test/e2e/suiteutils/git_stub_test_utils.go b/test/e2e/suiteutils/git_stub_test_utils.go index b0c64c6e7..f0fd1a381 100644 --- a/test/e2e/suiteutils/git_stub_test_utils.go +++ b/test/e2e/suiteutils/git_stub_test_utils.go @@ -280,9 +280,7 @@ func createLocalGitServer(t *testing.T) GitConfig { addressChannel := make(chan net.Addr) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { err := server.ListenAndServe(ctx, "127.0.0.1:0", addressChannel) if err != nil { if err == http.ErrServerClosed { @@ -291,7 +289,7 @@ func createLocalGitServer(t *testing.T) GitConfig { t.Errorf("Git server exited with error: %v", err) } } - }() + }) // Wait for server to start up address, ok := <-addressChannel diff --git a/test/e2e/suiteutils/suite_utils.go b/test/e2e/suiteutils/suite_utils.go index aeb6f144a..14f139bfe 100644 --- a/test/e2e/suiteutils/suite_utils.go +++ b/test/e2e/suiteutils/suite_utils.go @@ -42,7 +42,6 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" ) @@ -332,7 +331,7 @@ func (t *TestSuite) CreateOrUpdateSecret(name string, username string, password Name: secretName, Namespace: t.Namespace, }, - Immutable: ptr.To(true), + Immutable: new(true), Data: map[string][]byte{ "username": []byte(username), "password": []byte(password), @@ -1057,7 +1056,7 @@ func RunInParallel(functions ...func() any) []any { <-startSignal var result any - if reflect.TypeOf(fn).NumOut() == 0 { + if reflect.TypeFor[func() any]().NumOut() == 0 { fn() result = nil } else { diff --git a/test/git/pkg/testing_helpers.go b/test/git/pkg/testing_helpers.go index 666ab10ec..105b67813 100644 --- a/test/git/pkg/testing_helpers.go +++ b/test/git/pkg/testing_helpers.go @@ -88,15 +88,13 @@ func ServeExistingRepository(t *testing.T, repo *gogit.Repository) string { wg.Wait() }) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { if err := server.ListenAndServe(ctx, "127.0.0.1:0", serverAddressChannel); err != nil { if ctx.Err() == nil { t.Errorf("Git Server ListenAndServe failed: %v", err) } } - }() + }) address, ok := <-serverAddressChannel if !ok { diff --git a/test/performance/driver.go b/test/performance/driver.go index d1d763ec6..e0272a91b 100644 --- a/test/performance/driver.go +++ b/test/performance/driver.go @@ -16,6 +16,7 @@ package metrics import ( "fmt" + "maps" "strings" "time" @@ -97,9 +98,7 @@ func (b *baseDriver) updatePackageRevisionResources(repoName, pkgName, pkgRevNam if resources.Spec.Resources == nil { resources.Spec.Resources = make(map[string]string) } - for name, content := range pkgResources { - resources.Spec.Resources[name] = content - } + maps.Copy(resources.Spec.Resources, pkgResources) start = time.Now() err = retry.RetryOnConflict(retryBackoff, func() error { diff --git a/test/performance/logger.go b/test/performance/logger.go index eb252d76a..5069d6b77 100644 --- a/test/performance/logger.go +++ b/test/performance/logger.go @@ -86,7 +86,7 @@ func (l *TestLogger) Close() error { return l.file.Close() } -func (l *TestLogger) LogResult(format string, args ...interface{}) { +func (l *TestLogger) LogResult(format string, args ...any) { l.mutex.Lock() defer l.mutex.Unlock() @@ -170,7 +170,7 @@ func (l *ResultsLogger) LogDeleted(prName string, duration time.Duration) { _ = l.resultsFile.Sync() } -func (l *ResultsLogger) LogToFile(format string, args ...interface{}) { +func (l *ResultsLogger) LogToFile(format string, args ...any) { l.mutex.Lock() defer l.mutex.Unlock() diff --git a/test/performance/performance_suite.go b/test/performance/performance_suite.go index 05d8929fc..6eb163c4a 100644 --- a/test/performance/performance_suite.go +++ b/test/performance/performance_suite.go @@ -498,7 +498,7 @@ func (t *PerfTestSuite) createAndSetupRepo(repoName string) { func createGiteaRepo(ctx context.Context, opts TestOptions, repoName string) error { giteaURL := fmt.Sprintf("%s/api/v1/user/repos", strings.TrimRight(opts.giteaURL, "/")) - payload := map[string]interface{}{ + payload := map[string]any{ "name": repoName, "description": "Test repository for Porch metrics", "private": false,