github.com/cilium/controller-tools@v0.3.1-0.20230329170030-f2b7ff866fde/pkg/crd/parser_integration_test.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package crd_test
    18  
    19  import (
    20  	"io/ioutil"
    21  	"os"
    22  
    23  	"github.com/google/go-cmp/cmp"
    24  	. "github.com/onsi/ginkgo"
    25  	. "github.com/onsi/gomega"
    26  	"golang.org/x/tools/go/packages"
    27  	apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    28  	"k8s.io/apimachinery/pkg/runtime/schema"
    29  	"sigs.k8s.io/yaml"
    30  
    31  	"sigs.k8s.io/controller-tools/pkg/crd"
    32  	crdmarkers "sigs.k8s.io/controller-tools/pkg/crd/markers"
    33  	"sigs.k8s.io/controller-tools/pkg/loader"
    34  	"sigs.k8s.io/controller-tools/pkg/markers"
    35  )
    36  
    37  func packageErrors(pkg *loader.Package, filterKinds ...packages.ErrorKind) error {
    38  	toSkip := make(map[packages.ErrorKind]struct{})
    39  	for _, errKind := range filterKinds {
    40  		toSkip[errKind] = struct{}{}
    41  	}
    42  	var outErr error
    43  	packages.Visit([]*packages.Package{pkg.Package}, nil, func(pkgRaw *packages.Package) {
    44  		for _, err := range pkgRaw.Errors {
    45  			if _, skip := toSkip[err.Kind]; skip {
    46  				continue
    47  			}
    48  			outErr = err
    49  		}
    50  	})
    51  	return outErr
    52  }
    53  
    54  var _ = Describe("CRD Generation From Parsing to CustomResourceDefinition", func() {
    55  	It("should properly generate and flatten the rewritten CronJob schema", func() {
    56  		// TODO(directxman12): test generation across multiple versions (right
    57  		// now, we're trusting k/k's conversion code, though, which is probably
    58  		// fine for the time being)
    59  		By("switching into testdata to appease go modules")
    60  		cwd, err := os.Getwd()
    61  		Expect(err).NotTo(HaveOccurred())
    62  		Expect(os.Chdir("./testdata")).To(Succeed()) // go modules are directory-sensitive
    63  		defer func() { Expect(os.Chdir(cwd)).To(Succeed()) }()
    64  
    65  		By("loading the roots")
    66  		pkgs, err := loader.LoadRoots(".")
    67  		Expect(err).NotTo(HaveOccurred())
    68  		Expect(pkgs).To(HaveLen(1))
    69  		cronJobPkg := pkgs[0]
    70  
    71  		By("setting up the parser")
    72  		reg := &markers.Registry{}
    73  		Expect(crdmarkers.Register(reg)).To(Succeed())
    74  		parser := &crd.Parser{
    75  			Collector: &markers.Collector{Registry: reg},
    76  			Checker:   &loader.TypeChecker{},
    77  		}
    78  		crd.AddKnownTypes(parser)
    79  
    80  		By("requesting that the package be parsed")
    81  		parser.NeedPackage(cronJobPkg)
    82  
    83  		By("requesting that the CRD be generated")
    84  		groupKind := schema.GroupKind{Kind: "CronJob", Group: "testdata.kubebuilder.io"}
    85  		parser.NeedCRDFor(groupKind, nil)
    86  
    87  		By("checking that no errors occurred along the way (expect for type errors)")
    88  		Expect(packageErrors(cronJobPkg, packages.TypeError)).NotTo(HaveOccurred())
    89  
    90  		By("checking that the CRD is present")
    91  		Expect(parser.CustomResourceDefinitions).To(HaveKey(groupKind))
    92  
    93  		By("loading the desired YAML")
    94  		expectedFile, err := ioutil.ReadFile("testdata.kubebuilder.io_cronjobs.yaml")
    95  		Expect(err).NotTo(HaveOccurred())
    96  
    97  		By("parsing the desired YAML")
    98  		var crd apiext.CustomResourceDefinition
    99  		Expect(yaml.Unmarshal(expectedFile, &crd)).To(Succeed())
   100  		// clear the annotations -- we don't care about the attribution annotation
   101  		crd.Annotations = nil
   102  
   103  		By("comparing the two")
   104  		Expect(parser.CustomResourceDefinitions[groupKind]).To(Equal(crd), "type not as expected, check pkg/crd/testdata/README.md for more details.\n\nDiff:\n\n%s", cmp.Diff(parser.CustomResourceDefinitions[groupKind], crd))
   105  	})
   106  
   107  	It("should skip api internal package", func() {
   108  		By("switching into testdata to appease go modules")
   109  		cwd, err := os.Getwd()
   110  		Expect(err).NotTo(HaveOccurred())
   111  		Expect(os.Chdir("./testdata/internal_version")).To(Succeed()) // go modules are directory-sensitive
   112  		defer func() { Expect(os.Chdir(cwd)).To(Succeed()) }()
   113  
   114  		By("loading the roots")
   115  		pkgs, err := loader.LoadRoots(".")
   116  		Expect(err).NotTo(HaveOccurred())
   117  		Expect(pkgs).To(HaveLen(1))
   118  		cronJobPkg := pkgs[0]
   119  
   120  		By("setting up the parser")
   121  		reg := &markers.Registry{}
   122  		Expect(crdmarkers.Register(reg)).To(Succeed())
   123  		parser := &crd.Parser{
   124  			Collector: &markers.Collector{Registry: reg},
   125  			Checker:   &loader.TypeChecker{},
   126  		}
   127  		crd.AddKnownTypes(parser)
   128  
   129  		By("requesting that the package be parsed")
   130  		parser.NeedPackage(cronJobPkg)
   131  
   132  		By("checking that there is no GroupVersion")
   133  		Expect(parser.GroupVersions).To(BeEmpty())
   134  
   135  		By("checking that there are no Types")
   136  		Expect(parser.Types).To(BeEmpty())
   137  
   138  		By("checking that no errors occurred along the way (expect for type errors)")
   139  		Expect(packageErrors(cronJobPkg, packages.TypeError)).NotTo(HaveOccurred())
   140  
   141  	})
   142  })