From ee5c00be0e0aa0de6a2bcf0bf9e6d90534734490 Mon Sep 17 00:00:00 2001 From: Andrew Costa Date: Fri, 23 Feb 2024 15:07:51 -0800 Subject: [PATCH] Add "guids" as a valid package list filter - The latest version of the CF CLI (v8.7.8) introduced a change where the 'StagePackage' function now uses the "guids" query parameter when listing packages for an app. Korifi did not support this parameter, even though it claimed to support API v3.117.0. Co-authored-by: Dave Walter --- api/payloads/package.go | 6 +++++- api/payloads/package_test.go | 22 +++++++++++++++++---- api/repositories/package_repository.go | 4 +++- api/repositories/package_repository_test.go | 21 +++++++++++++++++--- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/api/payloads/package.go b/api/payloads/package.go index 44ba4f6b9..1488d0912 100644 --- a/api/payloads/package.go +++ b/api/payloads/package.go @@ -6,6 +6,7 @@ import ( "code.cloudfoundry.org/korifi/api/payloads/parse" "code.cloudfoundry.org/korifi/api/payloads/validation" "code.cloudfoundry.org/korifi/api/repositories" + jellidation "github.com/jellydator/validation" ) @@ -89,6 +90,7 @@ func (u *PackageUpdate) ToMessage(packageGUID string) repositories.UpdatePackage } type PackageList struct { + GUIDs string AppGUIDs string States string OrderBy string @@ -96,16 +98,18 @@ type PackageList struct { func (p *PackageList) ToMessage() repositories.ListPackagesMessage { return repositories.ListPackagesMessage{ + GUIDs: parse.ArrayParam(p.GUIDs), AppGUIDs: parse.ArrayParam(p.AppGUIDs), States: parse.ArrayParam(p.States), } } func (p *PackageList) SupportedKeys() []string { - return []string{"app_guids", "states", "order_by", "per_page", "page"} + return []string{"guids", "app_guids", "states", "order_by", "per_page", "page"} } func (p *PackageList) DecodeFromURLValues(values url.Values) error { + p.GUIDs = values.Get("guids") p.AppGUIDs = values.Get("app_guids") p.States = values.Get("states") p.OrderBy = values.Get("order_by") diff --git a/api/payloads/package_test.go b/api/payloads/package_test.go index 3d5fa0696..4258863bf 100644 --- a/api/payloads/package_test.go +++ b/api/payloads/package_test.go @@ -4,6 +4,7 @@ import ( "code.cloudfoundry.org/korifi/api/payloads" "code.cloudfoundry.org/korifi/api/repositories" "code.cloudfoundry.org/korifi/tools" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/onsi/gomega/gstruct" @@ -296,13 +297,14 @@ var _ = Describe("PackageUpdate", func() { var _ = Describe("PackageList", func() { DescribeTable("valid query", - func(query string, expectedPackageListQueryParameters payloads.PackageList) { - actualPackageListQueryParameters, decodeErr := decodeQuery[payloads.PackageList](query) + func(query string, expectedPackageList payloads.PackageList) { + actualPackageList, decodeErr := decodeQuery[payloads.PackageList](query) Expect(decodeErr).NotTo(HaveOccurred()) - Expect(*actualPackageListQueryParameters).To(Equal(expectedPackageListQueryParameters)) + Expect(*actualPackageList).To(Equal(expectedPackageList)) }, - Entry("app_guids", "app_guids=g1,g2", payloads.PackageList{AppGUIDs: "g1,g2"}), + Entry("guids", "guids=g1,g2", payloads.PackageList{GUIDs: "g1,g2"}), + Entry("app_guids", "app_guids=ag1,ag2", payloads.PackageList{AppGUIDs: "ag1,ag2"}), Entry("states", "states=s1,s2", payloads.PackageList{States: "s1,s2"}), Entry("created_at", "order_by=created_at", payloads.PackageList{OrderBy: "created_at"}), Entry("-created_at", "order_by=-created_at", payloads.PackageList{OrderBy: "-created_at"}), @@ -311,6 +313,18 @@ var _ = Describe("PackageList", func() { Entry("empty", "order_by=", payloads.PackageList{OrderBy: ""}), ) + DescribeTable("ToMessage", + func(packageList payloads.PackageList, expectedListPackagesMessage repositories.ListPackagesMessage) { + actualListPackagesMessage := packageList.ToMessage() + + Expect(actualListPackagesMessage).To(Equal(expectedListPackagesMessage)) + }, + Entry("guids", payloads.PackageList{GUIDs: "g1,g2", AppGUIDs: "", States: ""}, repositories.ListPackagesMessage{GUIDs: []string{"g1", "g2"}, AppGUIDs: []string{}, States: []string{}}), + Entry("app_guids", payloads.PackageList{GUIDs: "", AppGUIDs: "ag1,ag2", States: ""}, repositories.ListPackagesMessage{GUIDs: []string{}, AppGUIDs: []string{"ag1", "ag2"}, States: []string{}}), + Entry("states", payloads.PackageList{GUIDs: "", AppGUIDs: "", States: "s1,s2"}, repositories.ListPackagesMessage{GUIDs: []string{}, AppGUIDs: []string{}, States: []string{"s1", "s2"}}), + Entry("empty", payloads.PackageList{}, repositories.ListPackagesMessage{GUIDs: []string{}, AppGUIDs: []string{}, States: []string{}}), + ) + DescribeTable("invalid query", func(query string, expectedErrMsg string) { _, decodeErr := decodeQuery[payloads.PackageList](query) diff --git a/api/repositories/package_repository.go b/api/repositories/package_repository.go index 68e2d985f..b44bfd2f5 100644 --- a/api/repositories/package_repository.go +++ b/api/repositories/package_repository.go @@ -12,9 +12,9 @@ import ( "code.cloudfoundry.org/korifi/controllers/controllers/workloads" "code.cloudfoundry.org/korifi/tools/dockercfg" "code.cloudfoundry.org/korifi/tools/k8s" + "github.com/google/go-containerregistry/pkg/name" "github.com/google/uuid" - corev1 "k8s.io/api/core/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -81,6 +81,7 @@ type PackageRecord struct { } type ListPackagesMessage struct { + GUIDs []string AppGUIDs []string States []string } @@ -298,6 +299,7 @@ func (r *PackageRepo) ListPackages(ctx context.Context, authInfo authorization.I } preds := []func(korifiv1alpha1.CFPackage) bool{ + SetPredicate(message.GUIDs, func(s korifiv1alpha1.CFPackage) string { return s.Name }), SetPredicate(message.AppGUIDs, func(s korifiv1alpha1.CFPackage) string { return s.Spec.AppRef.Name }), } if len(message.States) > 0 { diff --git a/api/repositories/package_repository_test.go b/api/repositories/package_repository_test.go index 7561309fd..efeb07bbf 100644 --- a/api/repositories/package_repository_test.go +++ b/api/repositories/package_repository_test.go @@ -13,7 +13,6 @@ import ( "code.cloudfoundry.org/korifi/tests/matchers" "code.cloudfoundry.org/korifi/tools" "code.cloudfoundry.org/korifi/tools/k8s" - "sigs.k8s.io/controller-runtime/pkg/client" "github.com/google/uuid" . "github.com/onsi/ginkgo/v2" @@ -23,6 +22,7 @@ import ( "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" ) var _ = Describe("PackageRepository", func() { @@ -553,7 +553,22 @@ var _ = Describe("PackageRepository", func() { )) }) - When("app_guids filter is provided", func() { + When("the guids filter is provided", func() { + BeforeEach(func() { + listMessage = repositories.ListPackagesMessage{GUIDs: []string{package1GUID}} + }) + + It("fetches the specified package", func() { + Expect(packageList).To(ConsistOf( + MatchFields(IgnoreExtras, Fields{ + "GUID": Equal(package1GUID), + "AppGUID": Equal(appGUID), + }), + )) + }) + }) + + When("the app_guids filter is provided", func() { BeforeEach(func() { listMessage = repositories.ListPackagesMessage{AppGUIDs: []string{appGUID}} }) @@ -569,7 +584,7 @@ var _ = Describe("PackageRepository", func() { }) }) - When("State filter is provided", func() { + When("the state filter is provided", func() { When("filtering by State=READY", func() { BeforeEach(func() { listMessage = repositories.ListPackagesMessage{States: []string{"READY"}}