From c162179e1e180cb3435bfea5bc3448ead6808b0d Mon Sep 17 00:00:00 2001 From: Tony Jin Date: Thu, 13 Jun 2024 23:57:07 -0700 Subject: [PATCH] chore: enforce version to follow dns-1123 --- pkg/model/resource/gvk.go | 12 ++++-------- pkg/model/resource/gvk_test.go | 32 ++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pkg/model/resource/gvk.go b/pkg/model/resource/gvk.go index c673bc2f81b..c91a9958c59 100644 --- a/pkg/model/resource/gvk.go +++ b/pkg/model/resource/gvk.go @@ -18,24 +18,19 @@ package resource import ( "fmt" - "regexp" "strings" "sigs.k8s.io/kubebuilder/v4/pkg/internal/validation" ) const ( - versionPattern = "^v\\d+(?:alpha\\d+|beta\\d+)?$" + versionInternal = "__internal" groupRequired = "group cannot be empty if the domain is empty" versionRequired = "version cannot be empty" kindRequired = "kind cannot be empty" ) -var ( - versionRegex = regexp.MustCompile(versionPattern) -) - // GVK stores the Group - Version - Kind triplet that uniquely identifies a resource. // In kubebuilder, the k8s fully qualified group is stored as Group and Domain to improve UX. type GVK struct { @@ -60,8 +55,9 @@ func (gvk GVK) Validate() error { if gvk.Version == "" { return fmt.Errorf(versionRequired) } - if !versionRegex.MatchString(gvk.Version) { - return fmt.Errorf("Version must match %s (was %s)", versionPattern, gvk.Version) + errs := validation.IsDNS1123Label(gvk.Version) + if len(errs) > 0 && gvk.Version != versionInternal { + return fmt.Errorf("Version must respect DNS-1123 (was %s)", gvk.Version) } // Check if kind has a valid DNS1035 label value diff --git a/pkg/model/resource/gvk_test.go b/pkg/model/resource/gvk_test.go index 8b93bef4dd6..7d0c3a4ecdd 100644 --- a/pkg/model/resource/gvk_test.go +++ b/pkg/model/resource/gvk_test.go @@ -25,18 +25,21 @@ import ( var _ = Describe("GVK", func() { const ( - group = "group" - domain = "my.domain" - version = "v1" - kind = "Kind" + group = "group" + domain = "my.domain" + version = "v1" + kind = "Kind" + internalVersion = "__internal" ) gvk := GVK{Group: group, Domain: domain, Version: version, Kind: kind} Context("Validate", func() { - It("should succeed for a valid GVK", func() { - Expect(gvk.Validate()).To(Succeed()) - }) + DescribeTable("should pass valid GVKs", + func(gvk GVK) { Expect(gvk.Validate()).To(Succeed()) }, + Entry("Standard GVK", gvk), + Entry("Version (__internal)", GVK{Group: group, Domain: domain, Version: internalVersion, Kind: kind}), + ) DescribeTable("should fail for invalid GVKs", func(gvk GVK) { Expect(gvk.Validate()).NotTo(Succeed()) }, @@ -47,13 +50,14 @@ var _ = Describe("GVK", func() { Entry("Domain (non-alpha characters)", GVK{Group: group, Domain: "_*?", Version: version, Kind: kind}), Entry("Group and Domain (empty)", GVK{Group: "", Domain: "", Version: version, Kind: kind}), Entry("Version (empty)", GVK{Group: group, Domain: domain, Version: "", Kind: kind}), - Entry("Version (no v prefix)", GVK{Group: group, Domain: domain, Version: "1", Kind: kind}), - Entry("Version (wrong prefix)", GVK{Group: group, Domain: domain, Version: "a1", Kind: kind}), - Entry("Version (unstable no v prefix)", GVK{Group: group, Domain: domain, Version: "1beta1", Kind: kind}), - Entry("Version (unstable no alpha/beta number)", - GVK{Group: group, Domain: domain, Version: "v1beta", Kind: kind}), - Entry("Version (multiple unstable)", - GVK{Group: group, Domain: domain, Version: "v1beta1alpha1", Kind: kind}), + Entry("Version (wrong prefix)", GVK{Group: group, Domain: domain, Version: "-starts-with-hypen", Kind: kind}), + Entry("Version (wrong suffix)", GVK{Group: group, Domain: domain, Version: "ends-with-hypen-", Kind: kind}), + Entry("Version (uppercase)", GVK{Group: group, Domain: domain, Version: "ContainsUpperCase", Kind: kind}), + Entry("Version (special characters)", GVK{Group: group, Domain: domain, Version: "contains@symbol", Kind: kind}), + Entry("Version (exclusive numbers with invalid characters)", + GVK{Group: group, Domain: domain, Version: "12345^&*()", Kind: kind}), + Entry("Version (too long)", + GVK{Group: group, Domain: domain, Version: "a123456789012345678901234567890123456789012345678901234567890123", Kind: kind}), Entry("Kind (empty)", GVK{Group: group, Domain: domain, Version: version, Kind: ""}), Entry("Kind (whitespaces)", GVK{Group: group, Domain: domain, Version: version, Kind: "Ki nd"}), Entry("Kind (lowercase)", GVK{Group: group, Domain: domain, Version: version, Kind: "kind"}),