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 `