sigs.k8s.io/kubebuilder/v3@v3.14.0/pkg/plugins/golang/v4/scaffolds/internal/templates/controllers/controller_test_template.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  	"path/filepath"
    21  
    22  	log "github.com/sirupsen/logrus"
    23  
    24  	"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
    25  )
    26  
    27  var _ machinery.Template = &ControllerTest{}
    28  
    29  // ControllerTest scaffolds the file that sets up the controller unit tests
    30  // nolint:maligned
    31  type ControllerTest struct {
    32  	machinery.TemplateMixin
    33  	machinery.MultiGroupMixin
    34  	machinery.BoilerplateMixin
    35  	machinery.ResourceMixin
    36  
    37  	Force bool
    38  
    39  	DoAPI bool
    40  }
    41  
    42  // SetTemplateDefaults implements file.Template
    43  func (f *ControllerTest) SetTemplateDefaults() error {
    44  	if f.Path == "" {
    45  		if f.MultiGroup && f.Resource.Group != "" {
    46  			f.Path = filepath.Join("internal", "controller", "%[group]", "%[kind]_controller_test.go")
    47  		} else {
    48  			f.Path = filepath.Join("internal", "controller", "%[kind]_controller_test.go")
    49  		}
    50  	}
    51  
    52  	f.Path = f.Resource.Replacer().Replace(f.Path)
    53  	log.Println(f.Path)
    54  
    55  	f.TemplateBody = controllerTestTemplate
    56  
    57  	if f.Force {
    58  		f.IfExistsAction = machinery.OverwriteFile
    59  	}
    60  
    61  	return nil
    62  }
    63  
    64  const controllerTestTemplate = `{{ .Boilerplate }}
    65  
    66  {{if and .MultiGroup .Resource.Group }}
    67  package {{ .Resource.PackageName }}
    68  {{else}}
    69  package controller
    70  {{end}}
    71  
    72  import (
    73  	{{ if .DoAPI -}}
    74  	"context"
    75  	{{- end }}
    76  	. "github.com/onsi/ginkgo/v2"
    77  	{{ if .DoAPI -}}
    78  
    79  	. "github.com/onsi/gomega"
    80  	"k8s.io/apimachinery/pkg/api/errors"
    81  	"k8s.io/apimachinery/pkg/types"
    82  	"sigs.k8s.io/controller-runtime/pkg/reconcile"
    83  
    84  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    85  	{{ if not (isEmptyStr .Resource.Path) -}}
    86  	{{ .Resource.ImportAlias }} "{{ .Resource.Path }}"
    87  	{{- end }}
    88  	{{- end }}
    89  )
    90  
    91  var _ = Describe("{{ .Resource.Kind }} Controller", func() {
    92  	Context("When reconciling a resource", func() {
    93  		{{ if .DoAPI -}}
    94  		const resourceName = "test-resource"
    95  
    96  		ctx := context.Background()
    97  
    98  		typeNamespacedName := types.NamespacedName{
    99  			Name:      resourceName,
   100  			Namespace: "default",  // TODO(user):Modify as needed
   101  		}
   102  		{{ lower .Resource.Kind }} := &{{ .Resource.ImportAlias }}.{{ .Resource.Kind }}{}
   103  
   104  		BeforeEach(func() {
   105  			By("creating the custom resource for the Kind {{ .Resource.Kind }}")
   106  			err := k8sClient.Get(ctx, typeNamespacedName, {{ lower .Resource.Kind }})
   107  			if err != nil && errors.IsNotFound(err) {
   108  				resource := &{{ .Resource.ImportAlias }}.{{ .Resource.Kind }}{
   109  					ObjectMeta: metav1.ObjectMeta{
   110  						Name:      resourceName,
   111  						Namespace: "default",
   112  					},
   113  					// TODO(user): Specify other spec details if needed.
   114  				}
   115  				Expect(k8sClient.Create(ctx, resource)).To(Succeed())
   116  			}
   117  		})
   118  
   119  		AfterEach(func() {
   120  			// TODO(user): Cleanup logic after each test, like removing the resource instance.
   121  			resource := &{{ .Resource.ImportAlias }}.{{ .Resource.Kind }}{}
   122  			err := k8sClient.Get(ctx, typeNamespacedName, resource)
   123  			Expect(err).NotTo(HaveOccurred())
   124  
   125  			By("Cleanup the specific resource instance {{ .Resource.Kind }}")
   126  			Expect(k8sClient.Delete(ctx, resource)).To(Succeed())
   127  		})
   128  		{{- end }}
   129  		It("should successfully reconcile the resource", func() {
   130  			{{ if .DoAPI -}}
   131  			By("Reconciling the created resource")
   132  			controllerReconciler := &{{ .Resource.Kind }}Reconciler{
   133  				Client: k8sClient,
   134  				Scheme: k8sClient.Scheme(),
   135  			}
   136  
   137  			_, err := controllerReconciler.Reconcile(ctx, reconcile.Request{
   138  				NamespacedName: typeNamespacedName,
   139  			})
   140  			Expect(err).NotTo(HaveOccurred())
   141  			{{- end }}
   142  			// TODO(user): Add more specific assertions depending on your controller's reconciliation logic.
   143  			// Example: If you expect a certain status condition after reconciliation, verify it here.
   144  		})
   145  	})
   146  })
   147  `