Skip to content

Commit 7c994fc

Browse files
✨ crd/gen: sort FindKubeKinds (#694)
* bug: crd/gen: Sort findGroupKinds * remove binary Co-authored-by: Ghasem Shirazi <[email protected]>
1 parent 8d80422 commit 7c994fc

File tree

6 files changed

+189
-6
lines changed

6 files changed

+189
-6
lines changed

pkg/crd/gen.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"fmt"
2121
"go/ast"
2222
"go/types"
23+
"sort"
2324

2425
apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2526
"k8s.io/apimachinery/pkg/runtime/schema"
@@ -127,7 +128,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error {
127128
crdVersions = []string{defaultVersion}
128129
}
129130

130-
for groupKind := range kubeKinds {
131+
for _, groupKind := range kubeKinds {
131132
parser.NeedCRDFor(groupKind, g.MaxDescLen)
132133
crdRaw := parser.CustomResourceDefinitions[groupKind]
133134
addAttribution(&crdRaw)
@@ -216,7 +217,7 @@ func FindMetav1(roots []*loader.Package) *loader.Package {
216217
// FindKubeKinds locates all types that contain TypeMeta and ObjectMeta
217218
// (and thus may be a Kubernetes object), and returns the corresponding
218219
// group-kinds.
219-
func FindKubeKinds(parser *Parser, metav1Pkg *loader.Package) map[schema.GroupKind]struct{} {
220+
func FindKubeKinds(parser *Parser, metav1Pkg *loader.Package) []schema.GroupKind {
220221
// TODO(directxman12): technically, we should be finding metav1 per-package
221222
kubeKinds := map[schema.GroupKind]struct{}{}
222223
for typeIdent, info := range parser.Types {
@@ -275,7 +276,15 @@ func FindKubeKinds(parser *Parser, metav1Pkg *loader.Package) map[schema.GroupKi
275276
kubeKinds[groupKind] = struct{}{}
276277
}
277278

278-
return kubeKinds
279+
groupKindList := make([]schema.GroupKind, 0, len(kubeKinds))
280+
for groupKind := range kubeKinds {
281+
groupKindList = append(groupKindList, groupKind)
282+
}
283+
sort.Slice(groupKindList, func(i, j int) bool {
284+
return groupKindList[i].String() < groupKindList[j].String()
285+
})
286+
287+
return groupKindList
279288
}
280289

281290
// filterTypesForCRDs filters out all nodes that aren't used in CRD generation,

pkg/crd/gen_integration_test.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ import (
3636

3737
var _ = Describe("CRD Generation proper defaulting", func() {
3838
var (
39-
ctx *genall.GenerationContext
40-
out *outputRule
39+
ctx, ctx2 *genall.GenerationContext
40+
out *outputRule
4141

4242
genDir = filepath.Join("testdata", "gen")
4343
)
@@ -53,6 +53,9 @@ var _ = Describe("CRD Generation proper defaulting", func() {
5353
pkgs, err := loader.LoadRoots(".")
5454
Expect(err).NotTo(HaveOccurred())
5555
Expect(pkgs).To(HaveLen(1))
56+
pkgs2, err := loader.LoadRoots("./...")
57+
Expect(err).NotTo(HaveOccurred())
58+
Expect(pkgs2).To(HaveLen(2))
5659

5760
By("setup up the context")
5861
reg := &markers.Registry{}
@@ -66,6 +69,12 @@ var _ = Describe("CRD Generation proper defaulting", func() {
6669
Checker: &loader.TypeChecker{},
6770
OutputRule: out,
6871
}
72+
ctx2 = &genall.GenerationContext{
73+
Collector: &markers.Collector{Registry: reg},
74+
Roots: pkgs2,
75+
Checker: &loader.TypeChecker{},
76+
OutputRule: out,
77+
}
6978
})
7079

7180
It("should fail to generate v1beta1 CRDs", func() {
@@ -91,6 +100,26 @@ var _ = Describe("CRD Generation proper defaulting", func() {
91100
By("comparing the two")
92101
Expect(out.buf.String()).To(Equal(string(expectedFile)), cmp.Diff(out.buf.String(), string(expectedFile)))
93102
})
103+
104+
It("should have deterministic output", func() {
105+
By("calling Generate on multple packages")
106+
gen := &crd.Generator{
107+
CRDVersions: []string{"v1"},
108+
}
109+
Expect(gen.Generate(ctx2)).NotTo(HaveOccurred())
110+
111+
By("loading the desired YAMLs")
112+
expectedFileFoos, err := ioutil.ReadFile(filepath.Join(genDir, "bar.example.com_foos.yaml"))
113+
Expect(err).NotTo(HaveOccurred())
114+
expectedFileFoos = fixAnnotations(expectedFileFoos)
115+
expectedFileZoos, err := ioutil.ReadFile(filepath.Join(genDir, "zoo", "bar.example.com_zooes.yaml"))
116+
Expect(err).NotTo(HaveOccurred())
117+
expectedFileZoos = fixAnnotations(expectedFileZoos)
118+
119+
By("comparing the two, output must be deterministic because groupKinds are sorted")
120+
expectedOut := string(expectedFileFoos) + string(expectedFileZoos)
121+
Expect(out.buf.String()).To(Equal(expectedOut), cmp.Diff(out.buf.String(), expectedOut))
122+
})
94123
})
95124

96125
// fixAnnotations fixes the attribution annotation for tests.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1beta1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: (devel)
7+
creationTimestamp: null
8+
name: zoos.bar.example.com
9+
spec:
10+
group: bar.example.com
11+
names:
12+
kind: Zoo
13+
listKind: ZooList
14+
plural: zooes
15+
singular: zoo
16+
scope: Namespaced
17+
validation:
18+
openAPIV3Schema:
19+
properties:
20+
apiVersion:
21+
description: 'APIVersion defines the versioned schema of this representation
22+
of an object. Servers should convert recognized schemas to the latest
23+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
24+
type: string
25+
kind:
26+
description: 'Kind is a string value representing the REST resource this
27+
object represents. Servers may infer this from the endpoint the client
28+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
29+
type: string
30+
metadata:
31+
type: object
32+
spec:
33+
description: Spec comments SHOULD appear in the CRD spec
34+
properties:
35+
defaultedString:
36+
description: This tests that defaulted fields are stripped for v1beta1,
37+
but not for v1
38+
type: string
39+
required:
40+
- defaultedString
41+
type: object
42+
status:
43+
description: Status comments SHOULD appear in the CRD spec
44+
type: object
45+
type: object
46+
version: zoo
47+
versions:
48+
- name: zoo
49+
served: true
50+
storage: true
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: (devel)
7+
creationTimestamp: null
8+
name: zooes.bar.example.com
9+
spec:
10+
group: bar.example.com
11+
names:
12+
kind: Zoo
13+
listKind: ZooList
14+
plural: zooes
15+
singular: zoo
16+
scope: Namespaced
17+
versions:
18+
- name: zoo
19+
schema:
20+
openAPIV3Schema:
21+
properties:
22+
apiVersion:
23+
description: 'APIVersion defines the versioned schema of this representation
24+
of an object. Servers should convert recognized schemas to the latest
25+
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
26+
type: string
27+
kind:
28+
description: 'Kind is a string value representing the REST resource this
29+
object represents. Servers may infer this from the endpoint the client
30+
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
31+
type: string
32+
metadata:
33+
type: object
34+
spec:
35+
description: Spec comments SHOULD appear in the CRD spec
36+
properties:
37+
defaultedString:
38+
default: zooDefaultString
39+
description: This tests that defaulted fields are stripped for v1beta1,
40+
but not for v1
41+
type: string
42+
required:
43+
- defaultedString
44+
type: object
45+
status:
46+
description: Status comments SHOULD appear in the CRD spec
47+
type: object
48+
type: object
49+
served: true
50+
storage: true
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
//go:generate ../../../../.run-controller-gen.sh crd:crdVersions=v1beta1 paths=. output:dir=.
17+
//go:generate mv bar.example.com_zooes.yaml bar.example.com_zooes.v1beta1.yaml
18+
//go:generate ../../../../.run-controller-gen.sh crd:crdVersions=v1 paths=. output:dir=.
19+
20+
// +groupName=bar.example.com
21+
package zoo
22+
23+
import (
24+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
)
26+
27+
type ZooSpec struct {
28+
// This tests that defaulted fields are stripped for v1beta1,
29+
// but not for v1
30+
// +kubebuilder:default=zooDefaultString
31+
DefaultedString string `json:"defaultedString"`
32+
}
33+
type ZooStatus struct{}
34+
35+
type Zoo struct {
36+
// TypeMeta comments should NOT appear in the CRD spec
37+
metav1.TypeMeta `json:",inline"`
38+
// ObjectMeta comments should NOT appear in the CRD spec
39+
metav1.ObjectMeta `json:"metadata,omitempty"`
40+
41+
// Spec comments SHOULD appear in the CRD spec
42+
Spec ZooSpec `json:"spec,omitempty"`
43+
// Status comments SHOULD appear in the CRD spec
44+
Status ZooStatus `json:"status,omitempty"`
45+
}

pkg/schemapatcher/gen.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func (g Generator) Generate(ctx *genall.GenerationContext) (result error) {
113113
}
114114

115115
// generate schemata for the types we care about, and save them to be written later.
116-
for groupKind := range crdgen.FindKubeKinds(parser, metav1Pkg) {
116+
for _, groupKind := range crdgen.FindKubeKinds(parser, metav1Pkg) {
117117
existingSet, wanted := partialCRDSets[groupKind]
118118
if !wanted {
119119
continue

0 commit comments

Comments
 (0)