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  `