Skip to content

Commit 977ce8b

Browse files
authored
Merge pull request #1159 from Adirio/extract-resource
🏃 Extract Resource from the v1 scaffolding package
2 parents eb3d796 + 4d63aef commit 977ce8b

40 files changed

+293
-267
lines changed

cmd/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import (
2929

3030
"sigs.k8s.io/kubebuilder/cmd/util"
3131
"sigs.k8s.io/kubebuilder/pkg/scaffold"
32-
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/resource"
32+
"sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
3333
"sigs.k8s.io/kubebuilder/plugins/addon"
3434
)
3535

cmd/webhook_v1.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ import (
3131
"sigs.k8s.io/kubebuilder/pkg/scaffold"
3232
"sigs.k8s.io/kubebuilder/pkg/scaffold/input"
3333
"sigs.k8s.io/kubebuilder/pkg/scaffold/project"
34+
"sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
3435
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/manager"
35-
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/resource"
3636
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/webhook"
3737
)
3838

cmd/webhook_v2.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ import (
3030
"sigs.k8s.io/kubebuilder/pkg/scaffold"
3131
"sigs.k8s.io/kubebuilder/pkg/scaffold/input"
3232
"sigs.k8s.io/kubebuilder/pkg/scaffold/project"
33-
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/resource"
34-
resourcev2 "sigs.k8s.io/kubebuilder/pkg/scaffold/v2"
33+
"sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
34+
scaffoldv2 "sigs.k8s.io/kubebuilder/pkg/scaffold/v2"
3535
"sigs.k8s.io/kubebuilder/pkg/scaffold/v2/webhook"
3636
)
3737

@@ -92,8 +92,8 @@ You need to implement the conversion.Hub and conversion.Convertible interfaces f
9292
os.Exit(1)
9393
}
9494

95-
err = (&resourcev2.Main{}).Update(
96-
&resourcev2.MainUpdateOptions{
95+
err = (&scaffoldv2.Main{}).Update(
96+
&scaffoldv2.MainUpdateOptions{
9797
Project: &projectInfo,
9898
WireResource: false,
9999
WireController: false,

pkg/scaffold/api.go

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@ import (
2222
"strings"
2323

2424
"github.com/gobuffalo/flect"
25+
2526
"sigs.k8s.io/kubebuilder/pkg/model"
2627
"sigs.k8s.io/kubebuilder/pkg/scaffold/input"
2728
"sigs.k8s.io/kubebuilder/pkg/scaffold/project"
29+
"sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
2830
"sigs.k8s.io/kubebuilder/pkg/scaffold/util"
2931
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/controller"
30-
resourcev1 "sigs.k8s.io/kubebuilder/pkg/scaffold/v1/resource"
31-
resourcev2 "sigs.k8s.io/kubebuilder/pkg/scaffold/v2"
32+
crdv1 "sigs.k8s.io/kubebuilder/pkg/scaffold/v1/crd"
33+
scaffoldv2 "sigs.k8s.io/kubebuilder/pkg/scaffold/v2"
3234
crdv2 "sigs.k8s.io/kubebuilder/pkg/scaffold/v2/crd"
3335
)
3436

@@ -40,7 +42,7 @@ type API struct {
4042
// Plugins is the list of plugins we should allow to transform our generated scaffolding
4143
Plugins []Plugin
4244

43-
Resource *resourcev1.Resource
45+
Resource *resource.Resource
4446

4547
project *input.ProjectFile
4648

@@ -91,7 +93,7 @@ func (api *API) Scaffold() error {
9193
}
9294

9395
func (api *API) buildUniverse() *model.Universe {
94-
resource := &model.Resource{
96+
resourceModel := &model.Resource{
9597
Namespaced: api.Resource.Namespaced,
9698
Group: api.Resource.Group,
9799
Version: api.Resource.Version,
@@ -100,10 +102,10 @@ func (api *API) buildUniverse() *model.Universe {
100102
Plural: flect.Pluralize(strings.ToLower(api.Resource.Kind)),
101103
}
102104

103-
resource.GoPackage, resource.GroupDomain = util.GetResourceInfo(api.Resource, api.project.Repo, api.project.Domain)
105+
resourceModel.GoPackage, resourceModel.GroupDomain = util.GetResourceInfo(api.Resource, api.project.Repo, api.project.Domain)
104106

105107
return &model.Universe{
106-
Resource: resource,
108+
Resource: resourceModel,
107109
}
108110
}
109111

@@ -117,14 +119,14 @@ func (api *API) scaffoldV1() error {
117119
fmt.Sprintf("%s_types_test.go", strings.ToLower(r.Kind))))
118120

119121
err := (&Scaffold{}).Execute(api.buildUniverse(), input.Options{},
120-
&resourcev1.Register{Resource: r},
121-
&resourcev1.Types{Resource: r},
122-
&resourcev1.VersionSuiteTest{Resource: r},
123-
&resourcev1.TypesTest{Resource: r},
124-
&resourcev1.Doc{Resource: r},
125-
&resourcev1.Group{Resource: r},
126-
&resourcev1.AddToScheme{Resource: r},
127-
&resourcev1.CRDSample{Resource: r},
122+
&crdv1.Register{Resource: r},
123+
&crdv1.Types{Resource: r},
124+
&crdv1.VersionSuiteTest{Resource: r},
125+
&crdv1.TypesTest{Resource: r},
126+
&crdv1.Doc{Resource: r},
127+
&crdv1.Group{Resource: r},
128+
&crdv1.AddToScheme{Resource: r},
129+
&crdv1.CRDSample{Resource: r},
128130
)
129131
if err != nil {
130132
return fmt.Errorf("error scaffolding APIs: %v", err)
@@ -169,13 +171,13 @@ func (api *API) scaffoldV2() error {
169171
fmt.Sprintf("%s_types.go", strings.ToLower(r.Kind))))
170172

171173
files := []input.File{
172-
&resourcev2.Types{
174+
&scaffoldv2.Types{
173175
Input: input.Input{
174176
Path: filepath.Join("api", r.Version, fmt.Sprintf("%s_types.go", strings.ToLower(r.Kind))),
175177
},
176178
Resource: r},
177-
&resourcev2.Group{Resource: r},
178-
&resourcev2.CRDSample{Resource: r},
179+
&scaffoldv2.Group{Resource: r},
180+
&scaffoldv2.CRDSample{Resource: r},
179181
&crdv2.EnableWebhookPatch{Resource: r},
180182
&crdv2.EnableCAInjectionPatch{Resource: r},
181183
}
@@ -226,8 +228,8 @@ func (api *API) scaffoldV2() error {
226228
Plugins: api.Plugins,
227229
}
228230

229-
ctrlScaffolder := &resourcev2.Controller{Resource: r}
230-
testsuiteScaffolder := &resourcev2.ControllerSuiteTest{Resource: r}
231+
ctrlScaffolder := &scaffoldv2.Controller{Resource: r}
232+
testsuiteScaffolder := &scaffoldv2.ControllerSuiteTest{Resource: r}
231233
err := scaffold.Execute(
232234
api.buildUniverse(),
233235
input.Options{},
@@ -244,8 +246,8 @@ func (api *API) scaffoldV2() error {
244246
}
245247
}
246248

247-
err := (&resourcev2.Main{}).Update(
248-
&resourcev2.MainUpdateOptions{
249+
err := (&scaffoldv2.Main{}).Update(
250+
&scaffoldv2.MainUpdateOptions{
249251
Project: api.project,
250252
WireResource: api.DoResource,
251253
WireController: api.DoController,
@@ -260,10 +262,10 @@ func (api *API) scaffoldV2() error {
260262

261263
// Since we support single group only in v2 scaffolding, validate if resource
262264
// being created belongs to existing group.
263-
func (api *API) validateResourceGroup(resource *resourcev1.Resource) error {
265+
func (api *API) validateResourceGroup(r *resource.Resource) error {
264266
for _, existingGroup := range api.project.ResourceGroups() {
265-
if strings.ToLower(resource.Group) != strings.ToLower(existingGroup) {
266-
return fmt.Errorf("Group '%s' is not same as existing group '%s'. Multiple groups are not supported yet.", resource.Group, existingGroup)
267+
if strings.ToLower(r.Group) != strings.ToLower(existingGroup) {
268+
return fmt.Errorf("Group '%s' is not same as existing group '%s'. Multiple groups are not supported yet.", r.Group, existingGroup)
267269
}
268270
}
269271
return nil
File renamed without changes.
File renamed without changes.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package resource_test
2+
3+
import (
4+
. "github.com/onsi/ginkgo"
5+
. "github.com/onsi/gomega"
6+
7+
. "sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
8+
)
9+
10+
var _ = Describe("Resource", func() {
11+
Describe("scaffolding an API", func() {
12+
It("should succeed if the Resource is valid", func() {
13+
instance := &Resource{Group: "crew", Version: "v1", Kind: "FirstMate"}
14+
Expect(instance.Validate()).To(Succeed())
15+
})
16+
17+
It("should fail if the Group is not specified", func() {
18+
instance := &Resource{Version: "v1", Kind: "FirstMate"}
19+
Expect(instance.Validate()).NotTo(Succeed())
20+
Expect(instance.Validate().Error()).To(ContainSubstring("group cannot be empty"))
21+
})
22+
23+
It("should fail if the Group is not all lowercase", func() {
24+
instance := &Resource{Group: "Crew", Version: "v1", Kind: "FirstMate"}
25+
Expect(instance.Validate()).NotTo(Succeed())
26+
Expect(instance.Validate().Error()).To(ContainSubstring("group name is invalid: ([a DNS-1123 subdomain must consist of lower case alphanumeric characters"))
27+
})
28+
29+
It("should fail if the Group contains non-alpha characters", func() {
30+
instance := &Resource{Group: "crew1*?", Version: "v1", Kind: "FirstMate"}
31+
Expect(instance.Validate()).NotTo(Succeed())
32+
Expect(instance.Validate().Error()).To(ContainSubstring("group name is invalid: ([a DNS-1123 subdomain must consist of lower case alphanumeric characters"))
33+
})
34+
35+
It("should fail if the Version is not specified", func() {
36+
instance := &Resource{Group: "crew", Kind: "FirstMate"}
37+
Expect(instance.Validate()).NotTo(Succeed())
38+
Expect(instance.Validate().Error()).To(ContainSubstring("version cannot be empty"))
39+
})
40+
41+
It("should fail if the Version does not match the version format", func() {
42+
instance := &Resource{Group: "crew", Version: "1", Kind: "FirstMate"}
43+
Expect(instance.Validate()).NotTo(Succeed())
44+
Expect(instance.Validate().Error()).To(ContainSubstring(
45+
`version must match ^v\d+(alpha\d+|beta\d+)?$ (was 1)`))
46+
47+
instance = &Resource{Group: "crew", Version: "1beta1", Kind: "FirstMate"}
48+
Expect(instance.Validate()).NotTo(Succeed())
49+
Expect(instance.Validate().Error()).To(ContainSubstring(
50+
`version must match ^v\d+(alpha\d+|beta\d+)?$ (was 1beta1)`))
51+
52+
instance = &Resource{Group: "crew", Version: "a1beta1", Kind: "FirstMate"}
53+
Expect(instance.Validate()).NotTo(Succeed())
54+
Expect(instance.Validate().Error()).To(ContainSubstring(
55+
`version must match ^v\d+(alpha\d+|beta\d+)?$ (was a1beta1)`))
56+
57+
instance = &Resource{Group: "crew", Version: "v1beta", Kind: "FirstMate"}
58+
Expect(instance.Validate()).NotTo(Succeed())
59+
Expect(instance.Validate().Error()).To(ContainSubstring(
60+
`version must match ^v\d+(alpha\d+|beta\d+)?$ (was v1beta)`))
61+
62+
instance = &Resource{Group: "crew", Version: "v1beta1alpha1", Kind: "FirstMate"}
63+
Expect(instance.Validate()).NotTo(Succeed())
64+
Expect(instance.Validate().Error()).To(ContainSubstring(
65+
`version must match ^v\d+(alpha\d+|beta\d+)?$ (was v1beta1alpha1)`))
66+
})
67+
68+
It("should fail if the Kind is not specified", func() {
69+
instance := &Resource{Group: "crew", Version: "v1"}
70+
Expect(instance.Validate()).NotTo(Succeed())
71+
Expect(instance.Validate().Error()).To(ContainSubstring("kind cannot be empty"))
72+
})
73+
74+
It("should fail if the Kind is not pascal cased", func() {
75+
// Base case
76+
instance := &Resource{Group: "crew", Kind: "FirstMate", Version: "v1"}
77+
Expect(instance.Validate()).To(Succeed())
78+
79+
// Can't detect this case :(
80+
instance = &Resource{Group: "crew", Kind: "Firstmate", Version: "v1"}
81+
Expect(instance.Validate()).To(Succeed())
82+
83+
instance = &Resource{Group: "crew", Kind: "firstMate", Version: "v1"}
84+
Expect(instance.Validate()).NotTo(Succeed())
85+
Expect(instance.Validate().Error()).To(ContainSubstring(
86+
`kind must be PascalCase (expected FirstMate was firstMate)`))
87+
88+
instance = &Resource{Group: "crew", Kind: "firstmate", Version: "v1"}
89+
Expect(instance.Validate()).NotTo(Succeed())
90+
Expect(instance.Validate().Error()).To(ContainSubstring(
91+
`kind must be PascalCase (expected Firstmate was firstmate)`))
92+
})
93+
94+
It("should default the Resource by pluralizing the Kind", func() {
95+
instance := &Resource{Group: "crew", Kind: "FirstMate", Version: "v1"}
96+
Expect(instance.Validate()).To(Succeed())
97+
Expect(instance.Resource).To(Equal("firstmates"))
98+
99+
instance = &Resource{Group: "crew", Kind: "Fish", Version: "v1"}
100+
Expect(instance.Validate()).To(Succeed())
101+
Expect(instance.Resource).To(Equal("fish"))
102+
103+
instance = &Resource{Group: "crew", Kind: "Helmswoman", Version: "v1"}
104+
Expect(instance.Validate()).To(Succeed())
105+
Expect(instance.Resource).To(Equal("helmswomen"))
106+
})
107+
108+
It("should allow Cat as a Kind", func() {
109+
instance := &Resource{Group: "crew", Kind: "Cat", Version: "v1"}
110+
Expect(instance.Validate()).To(Succeed())
111+
Expect(instance.Resource).To(Equal("cats"))
112+
})
113+
114+
It("should allow hyphens in group names", func() {
115+
instance := &Resource{Group: "my-project", Kind: "Cat", Version: "v1"}
116+
Expect(instance.Validate()).To(Succeed())
117+
Expect(instance.GroupImportSafe).To(Equal("myproject"))
118+
})
119+
120+
It("should keep the Resource if specified", func() {
121+
instance := &Resource{Group: "crew", Kind: "FirstMate", Version: "v1", Resource: "myresource"}
122+
Expect(instance.Validate()).To(Succeed())
123+
Expect(instance.Resource).To(Equal("myresource"))
124+
})
125+
})
126+
})

pkg/scaffold/util/util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
"path/filepath"
2424
"strings"
2525

26-
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/resource"
26+
"sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
2727
)
2828

2929
func GetResourceInfo(r *resource.Resource, repo, domain string) (resourcePackage, groupDomain string) {

pkg/scaffold/v1/controller/add.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
"strings"
2323

2424
"sigs.k8s.io/kubebuilder/pkg/scaffold/input"
25-
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/resource"
25+
"sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
2626
)
2727

2828
var _ input.File = &AddController{}

pkg/scaffold/v1/controller/controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525

2626
"github.com/gobuffalo/flect"
2727
"sigs.k8s.io/kubebuilder/pkg/scaffold/input"
28-
"sigs.k8s.io/kubebuilder/pkg/scaffold/v1/resource"
28+
"sigs.k8s.io/kubebuilder/pkg/scaffold/resource"
2929
)
3030

3131
// Controller scaffolds a Controller for a Resource

0 commit comments

Comments
 (0)