Skip to content

Commit

Permalink
Merge pull request #189 from mengqiy/addTest
Browse files Browse the repository at this point in the history
add a bit more tests for CRD
  • Loading branch information
k8s-ci-robot authored Apr 13, 2019
2 parents 4d1a473 + c68ab3a commit 647e7c5
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 27 deletions.
165 changes: 165 additions & 0 deletions pkg/crd/v2/multiversion_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package v2

import (
"reflect"
"testing"

"github.com/ghodss/yaml"

"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/runtime/schema"
)

type multiVersionTestcase struct {
inputPackage string
types []string

listFilesFn listFilesFn
listDirsFn listDirsFn
// map of path to file content.
inputFiles map[string][]byte

expectedCrdSpecs map[schema.GroupKind][]byte
}

func TestMultiVerGenerate(t *testing.T) {
testcases := []multiVersionTestcase{
{
inputPackage: "github.com/myorg/myapi",
types: []string{"Toy"},
listDirsFn: func(pkgPath string) (strings []string, e error) {
return []string{"v1", "v1alpha1"}, nil
},
listFilesFn: func(pkgPath string) (s string, strings []string, e error) {
return pkgPath, []string{"types.go"}, nil
},
inputFiles: map[string][]byte{
"github.com/myorg/myapi/v1/types.go": []byte(`
package v1
// +groupName=foo.bar.com
// +versionName=v1
// +kubebuilder:resource:path=toys,shortName=to;ty
// +kubebuilder:singular=toy
// Toy is a toy struct
type Toy struct {
// +kubebuilder:validation:Maximum=90
// +kubebuilder:validation:Minimum=1
// Replicas is a number
Replicas int32 ` + "`" + `json:"replicas"` + "`" + `
}
`),
"github.com/myorg/myapi/v1alpha1/types.go": []byte(`
package v1alpha1
// +groupName=foo.bar.com
// +versionName=v1alpha1
// +kubebuilder:resource:path=toys,shortName=to;ty
// +kubebuilder:singular=toy
// Toy is a toy struct
type Toy struct {
// +kubebuilder:validation:MaxLength=15
// +kubebuilder:validation:MinLength=1
// Name is a string
Name string ` + "`" + `json:"name,omitempty"` + "`" + `
// +kubebuilder:validation:Maximum=100
// +kubebuilder:validation:Minimum=1
// Replicas is a number
Replicas int32 ` + "`" + `json:"replicas"` + "`" + `
}
`),
},
expectedCrdSpecs: map[schema.GroupKind][]byte{
schema.GroupKind{Group: "foo.bar.com", Kind: "Toy"}: []byte(`group: foo.bar.com
names:
kind: Toy
plural: toys
shortNames:
- to
- ty
singular: toy
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: Toy is a toy struct
properties:
replicas:
description: Replicas is a number
maximum: 90
minimum: 1
type: integer
required:
- replicas
type: object
served: true
storage: false
- name: v1alpha1
schema:
openAPIV3Schema:
description: Toy is a toy struct
properties:
name:
description: Name is a string
maxLength: 15
minLength: 1
type: string
replicas:
description: Replicas is a number
maximum: 100
minimum: 1
type: integer
required:
- replicas
type: object
served: true
storage: false
`),
},
},
}
for _, tc := range testcases {
fs, err := prepareTestFs(tc.inputFiles)
if err != nil {
t.Errorf("unable to prepare the in-memory fs for testing: %v", err)
continue
}

op := &MultiVersionOptions{
InputPackage: tc.inputPackage,
Types: tc.types,
listDirsFn: tc.listDirsFn,
listFilesFn: tc.listFilesFn,
fs: fs,
}

crdSpecs := op.parse()

if len(tc.expectedCrdSpecs) > 0 {
expectedSpecsByKind := map[schema.GroupKind]*v1beta1.CustomResourceDefinitionSpec{}
for gk := range tc.expectedCrdSpecs {
var spec v1beta1.CustomResourceDefinitionSpec
err = yaml.Unmarshal(tc.expectedCrdSpecs[gk], &spec)
if err != nil {
t.Errorf("unable to unmarshal the expected crd spec: %v", err)
continue
}
expectedSpecsByKind[gk] = &spec
}

if !reflect.DeepEqual(crdSpecs, crdSpecByKind(expectedSpecsByKind)) {
t.Errorf("expected:\n%+v,\nbut got:\n%+v\n", expectedSpecsByKind, crdSpecs)
continue
}
}
}
}
31 changes: 9 additions & 22 deletions pkg/crd/v2/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func (pr *prsr) processTopLevelMarkers(comments []*ast.CommentGroup) {
log.Fatalf("can't have different group names %q and %q one package", pr.generatorOptions.group, group)
}
if pr.generatorOptions == nil {
pr.generatorOptions = &toplevelGeneratorOptions{group: group}
pr.generatorOptions = &pkglevelGeneratorOptions{group: group}
} else {
pr.generatorOptions.group = group
}
Expand All @@ -182,7 +182,7 @@ func (pr *prsr) processTopLevelMarkers(comments []*ast.CommentGroup) {
log.Fatalf("can't have different version names %q and %q one package", pr.generatorOptions.version, version)
}
if pr.generatorOptions == nil {
pr.generatorOptions = &toplevelGeneratorOptions{version: version}
pr.generatorOptions = &pkglevelGeneratorOptions{version: version}
} else {
pr.generatorOptions.version = version
}
Expand Down Expand Up @@ -256,46 +256,33 @@ func (pr *prsr) parseTypesInPackage(pkgName string, referencedTypes map[string]b
mergeDefs(pkgDefs, childDefs)
}

return pkgDefs, pkgCRDSpecs
return pkgDefs, pr.fanoutPkgLevelOptions(pkgCRDSpecs)
}

type toplevelGeneratorOptions struct {
type pkglevelGeneratorOptions struct {
group string
version string
}

type prsr struct {
generatorOptions *toplevelGeneratorOptions
generatorOptions *pkglevelGeneratorOptions

listFilesFn listFilesFn
fs afero.Fs
}

func (pr *prsr) linkCRDSpec(defs v1beta1.JSONSchemaDefinitions, crdSpecs crdSpecByKind) crdSpecByKind {
func (pr *prsr) fanoutPkgLevelOptions(crdSpecs crdSpecByKind) crdSpecByKind {
rtCRDSpecs := crdSpecByKind{}
for gk := range crdSpecs {
if pr.generatorOptions != nil {
crdSpecs[gk].Group = pr.generatorOptions.group
if len(crdSpecs[gk].Versions) == 1 {
crdSpecs[gk].Versions[0].Name = pr.generatorOptions.version
}
rtCRDSpecs[schema.GroupKind{Group: pr.generatorOptions.group, Kind: gk.Kind}] = crdSpecs[gk]
} else {
rtCRDSpecs[gk] = crdSpecs[gk]
}

if len(crdSpecs[gk].Versions) == 0 {
log.Printf("no version for CRD %q", gk)
continue
}
if len(crdSpecs[gk].Versions) > 1 {
log.Fatalf("the number of versions in one package is more than 1")
}
def, ok := defs[gk.Kind]
if !ok {
log.Printf("can't get json shchema for %q", gk)
continue
}
crdSpecs[gk].Versions[0].Schema = &v1beta1.CustomResourceValidation{
OpenAPIV3Schema: &def,
}
}
return rtCRDSpecs
}
23 changes: 22 additions & 1 deletion pkg/crd/v2/singleversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ func (op *SingleVersionOptions) parse() (v1beta1.JSONSchemaDefinitions, crdSpecB
defs = newDefs
}

return defs, pr.linkCRDSpec(defs, crdSpecs)
pr.linkCRDSpec(defs, crdSpecs)
return defs, crdSpecs
}

func (op *SingleVersionGenerator) Generate() {
Expand All @@ -109,3 +110,23 @@ func (op *SingleVersionGenerator) Generate() {

op.write(op.outputCRD, op.Types)
}

func (pr *prsr) linkCRDSpec(defs v1beta1.JSONSchemaDefinitions, crdSpecs crdSpecByKind) {
for gk := range crdSpecs {
if len(crdSpecs[gk].Versions) == 0 {
log.Printf("no version for CRD %q", gk)
continue
}
if len(crdSpecs[gk].Versions) > 1 {
log.Fatalf("the number of versions in one package should not be more than 1")
}
def, ok := defs[gk.Kind]
if !ok {
log.Printf("can't get json shchema for %q", gk)
continue
}
crdSpecs[gk].Versions[0].Schema = &v1beta1.CustomResourceValidation{
OpenAPIV3Schema: &def,
}
}
}
75 changes: 71 additions & 4 deletions pkg/crd/v2/singleversion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,11 @@ import (
"reflect"
"testing"

"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/ghodss/yaml"
"github.com/spf13/afero"

"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/runtime/schema"
)

type singleVersionTestcase struct {
Expand Down Expand Up @@ -72,6 +71,74 @@ type Toy struct {
type: object
`),
},
{
inputPackage: "github.com/myorg/myapi",
types: []string{"Toy"},
flatten: false,
listFilesFn: func(pkgPath string) (s string, strings []string, e error) {
return "github.com/myorg/myapi", []string{"types.go"}, nil
},
inputFiles: map[string][]byte{
"github.com/myorg/myapi/types.go": []byte(`
package myapi
// +groupName=foo.bar.com
// +versionName=v1
// +kubebuilder:resource:path=toys,shortName=to;ty
// +kubebuilder:singular=toy
// Toy is a toy struct
type Toy struct {
// +kubebuilder:validation:Maximum=90
// +kubebuilder:validation:Minimum=1
// Replicas is a number
Replicas int32 ` + "`" + `json:"replicas"` + "`" + `
}
`),
},
expectedDefs: []byte(`Toy:
description: Toy is a toy struct
properties:
replicas:
description: Replicas is a number
maximum: 90
minimum: 1
type: integer
required:
- replicas
type: object
`),
expectedCrdSpecs: map[schema.GroupKind][]byte{
schema.GroupKind{Group: "foo.bar.com", Kind: "Toy"}: []byte(`group: foo.bar.com
names:
kind: Toy
plural: toys
shortNames:
- to
- ty
singular: toy
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: Toy is a toy struct
properties:
replicas:
description: Replicas is a number
maximum: 90
minimum: 1
type: integer
required:
- replicas
type: object
served: true
storage: false
`),
},
},
}
for _, tc := range testcases {
fs, err := prepareTestFs(tc.inputFiles)
Expand Down Expand Up @@ -118,8 +185,8 @@ type Toy struct {
expectedSpecsByKind[gk] = &spec
}

if !reflect.DeepEqual(crdSpecs, expectedSpecsByKind) {
t.Errorf("expected: %s, but got: %s", expectedSpecsByKind, crdSpecs)
if !reflect.DeepEqual(crdSpecs, crdSpecByKind(expectedSpecsByKind)) {
t.Errorf("expected:\n%+v,\nbut got:\n%+v\n", expectedSpecsByKind, crdSpecs)
continue
}
}
Expand Down

0 comments on commit 647e7c5

Please sign in to comment.