sigs.k8s.io/kubebuilder/v3@v3.14.0/pkg/plugins/golang/v4/scaffolds/internal/templates/controllers/controller_suitetest.go (about) 1 /* 2 Copyright 2022 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 controllers 18 19 import ( 20 "fmt" 21 "path/filepath" 22 23 log "github.com/sirupsen/logrus" 24 25 "sigs.k8s.io/kubebuilder/v3/pkg/machinery" 26 ) 27 28 var _ machinery.Template = &SuiteTest{} 29 var _ machinery.Inserter = &SuiteTest{} 30 31 // SuiteTest scaffolds the file that sets up the controller tests 32 // nolint:maligned 33 type SuiteTest struct { 34 machinery.TemplateMixin 35 machinery.MultiGroupMixin 36 machinery.BoilerplateMixin 37 machinery.ResourceMixin 38 39 // K8SVersion define the k8s version used to do the scaffold 40 // so that is possible retrieve the binaries 41 K8SVersion string 42 43 // CRDDirectoryRelativePath define the Path for the CRD 44 CRDDirectoryRelativePath string 45 46 Force bool 47 } 48 49 // SetTemplateDefaults implements file.Template 50 func (f *SuiteTest) SetTemplateDefaults() error { 51 if f.Path == "" { 52 if f.MultiGroup && f.Resource.Group != "" { 53 f.Path = filepath.Join("internal", "controller", "%[group]", "suite_test.go") 54 } else { 55 f.Path = filepath.Join("internal", "controller", "suite_test.go") 56 } 57 } 58 59 f.Path = f.Resource.Replacer().Replace(f.Path) 60 log.Println(f.Path) 61 62 f.TemplateBody = fmt.Sprintf(controllerSuiteTestTemplate, 63 machinery.NewMarkerFor(f.Path, importMarker), 64 machinery.NewMarkerFor(f.Path, addSchemeMarker), 65 ) 66 67 // If is multigroup the path needs to be ../../ since it has 68 // the group dir. 69 f.CRDDirectoryRelativePath = `"..",".."` 70 if f.MultiGroup && f.Resource.Group != "" { 71 f.CRDDirectoryRelativePath = `"..", "..",".."` 72 } 73 74 if f.Force { 75 f.IfExistsAction = machinery.OverwriteFile 76 } 77 78 return nil 79 } 80 81 const ( 82 importMarker = "imports" 83 addSchemeMarker = "scheme" 84 ) 85 86 // GetMarkers implements file.Inserter 87 func (f *SuiteTest) GetMarkers() []machinery.Marker { 88 return []machinery.Marker{ 89 machinery.NewMarkerFor(f.Path, importMarker), 90 machinery.NewMarkerFor(f.Path, addSchemeMarker), 91 } 92 } 93 94 const ( 95 apiImportCodeFragment = `%s "%s" 96 ` 97 addschemeCodeFragment = `err = %s.AddToScheme(scheme.Scheme) 98 Expect(err).NotTo(HaveOccurred()) 99 100 ` 101 ) 102 103 // GetCodeFragments implements file.Inserter 104 func (f *SuiteTest) GetCodeFragments() machinery.CodeFragmentsMap { 105 fragments := make(machinery.CodeFragmentsMap, 2) 106 107 // Generate import code fragments 108 imports := make([]string, 0) 109 if f.Resource.Path != "" { 110 imports = append(imports, fmt.Sprintf(apiImportCodeFragment, f.Resource.ImportAlias(), f.Resource.Path)) 111 } 112 113 // Generate add scheme code fragments 114 addScheme := make([]string, 0) 115 if f.Resource.Path != "" { 116 addScheme = append(addScheme, fmt.Sprintf(addschemeCodeFragment, f.Resource.ImportAlias())) 117 } 118 119 // Only store code fragments in the map if the slices are non-empty 120 if len(imports) != 0 { 121 fragments[machinery.NewMarkerFor(f.Path, importMarker)] = imports 122 } 123 if len(addScheme) != 0 { 124 fragments[machinery.NewMarkerFor(f.Path, addSchemeMarker)] = addScheme 125 } 126 127 return fragments 128 } 129 130 const controllerSuiteTestTemplate = `{{ .Boilerplate }} 131 132 {{if and .MultiGroup .Resource.Group }} 133 package {{ .Resource.PackageName }} 134 {{else}} 135 package controller 136 {{end}} 137 138 import ( 139 "fmt" 140 "path/filepath" 141 "runtime" 142 "testing" 143 144 . "github.com/onsi/ginkgo/v2" 145 . "github.com/onsi/gomega" 146 147 "k8s.io/client-go/kubernetes/scheme" 148 "k8s.io/client-go/rest" 149 "sigs.k8s.io/controller-runtime/pkg/client" 150 "sigs.k8s.io/controller-runtime/pkg/envtest" 151 logf "sigs.k8s.io/controller-runtime/pkg/log" 152 "sigs.k8s.io/controller-runtime/pkg/log/zap" 153 %s 154 ) 155 156 // These tests use Ginkgo (BDD-style Go testing framework). Refer to 157 // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 158 159 var cfg *rest.Config 160 var k8sClient client.Client 161 var testEnv *envtest.Environment 162 163 func TestControllers(t *testing.T) { 164 RegisterFailHandler(Fail) 165 166 RunSpecs(t, "Controller Suite") 167 } 168 169 var _ = BeforeSuite(func() { 170 logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 171 172 By("bootstrapping test environment") 173 testEnv = &envtest.Environment{ 174 CRDDirectoryPaths: []string{filepath.Join({{ .CRDDirectoryRelativePath }}, "config", "crd", "bases")}, 175 ErrorIfCRDPathMissing: {{ .Resource.HasAPI }}, 176 177 // The BinaryAssetsDirectory is only required if you want to run the tests directly 178 // without call the makefile target test. If not informed it will look for the 179 // default path defined in controller-runtime which is /usr/local/kubebuilder/. 180 // Note that you must have the required binaries setup under the bin directory to perform 181 // the tests directly. When we run make test it will be setup and used automatically. 182 BinaryAssetsDirectory: filepath.Join({{ .CRDDirectoryRelativePath }}, "bin", "k8s", 183 fmt.Sprintf("{{ .K8SVersion }}-%%s-%%s", runtime.GOOS, runtime.GOARCH)), 184 } 185 186 var err error 187 // cfg is defined in this file globally. 188 cfg, err = testEnv.Start() 189 Expect(err).NotTo(HaveOccurred()) 190 Expect(cfg).NotTo(BeNil()) 191 192 %s 193 194 k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 195 Expect(err).NotTo(HaveOccurred()) 196 Expect(k8sClient).NotTo(BeNil()) 197 198 }) 199 200 var _ = AfterSuite(func() { 201 By("tearing down the test environment") 202 err := testEnv.Stop() 203 Expect(err).NotTo(HaveOccurred()) 204 }) 205 `