sigs.k8s.io/cluster-api@v1.7.1/internal/runtime/registry/registry_test.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 registry 18 19 import ( 20 "testing" 21 22 . "github.com/onsi/gomega" 23 "github.com/onsi/gomega/format" 24 "github.com/onsi/gomega/types" 25 "github.com/pkg/errors" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/utils/ptr" 28 29 runtimev1 "sigs.k8s.io/cluster-api/exp/runtime/api/v1alpha1" 30 runtimecatalog "sigs.k8s.io/cluster-api/exp/runtime/catalog" 31 ) 32 33 func TestColdRegistry(t *testing.T) { 34 g := NewWithT(t) 35 36 r := New() 37 g.Expect(r.IsReady()).To(BeFalse()) 38 39 // Add, Remove, List and Get should fail with a cold registry. 40 g.Expect(r.Add(&runtimev1.ExtensionConfig{})).ToNot(Succeed()) 41 g.Expect(r.Remove(&runtimev1.ExtensionConfig{})).ToNot(Succeed()) 42 _, err := r.List(runtimecatalog.GroupHook{Group: "foo", Hook: "bak"}) 43 g.Expect(err).To(HaveOccurred()) 44 _, err = r.Get("foo") 45 g.Expect(err).To(HaveOccurred()) 46 } 47 48 func TestWarmUpRegistry(t *testing.T) { 49 g := NewWithT(t) 50 51 extensionConfigList := &runtimev1.ExtensionConfigList{ 52 Items: []runtimev1.ExtensionConfig{ 53 { 54 ObjectMeta: metav1.ObjectMeta{ 55 Name: "test-extension", 56 }, 57 Status: runtimev1.ExtensionConfigStatus{ 58 Handlers: []runtimev1.ExtensionHandler{ 59 { 60 Name: "handler.test-extension", 61 RequestHook: runtimev1.GroupVersionHook{ 62 APIVersion: "foo/v1alpha1", 63 Hook: "bak", 64 }, 65 }, 66 }, 67 }, 68 }, 69 }, 70 } 71 72 // WarmUp registry. 73 r := New() 74 g.Expect(r.WarmUp(extensionConfigList)).To(Succeed()) 75 g.Expect(r.IsReady()).To(BeTrue()) 76 77 // A second WarmUp should fail, registry should stay ready. 78 g.Expect(r.WarmUp(extensionConfigList)).ToNot(Succeed()) 79 g.Expect(r.IsReady()).To(BeTrue()) 80 81 // Add, Remove, List and Get should work with a warmed up registry. 82 g.Expect(r.Add(&runtimev1.ExtensionConfig{})).To(Succeed()) 83 g.Expect(r.Remove(&runtimev1.ExtensionConfig{})).To(Succeed()) 84 85 registrations, err := r.List(runtimecatalog.GroupHook{Group: "foo", Hook: "bak"}) 86 g.Expect(err).ToNot(HaveOccurred()) 87 g.Expect(registrations).To(HaveLen(1)) 88 g.Expect(registrations[0].Name).To(Equal("handler.test-extension")) 89 90 registration, err := r.Get("handler.test-extension") 91 g.Expect(err).ToNot(HaveOccurred()) 92 g.Expect(registration.Name).To(Equal("handler.test-extension")) 93 } 94 95 func TestRegistry(t *testing.T) { 96 g := NewWithT(t) 97 98 extension1 := &runtimev1.ExtensionConfig{ 99 ObjectMeta: metav1.ObjectMeta{ 100 Name: "extension1", 101 }, 102 Spec: runtimev1.ExtensionConfigSpec{ 103 ClientConfig: runtimev1.ClientConfig{ 104 URL: ptr.To("https://extesions1.com/"), 105 }, 106 }, 107 Status: runtimev1.ExtensionConfigStatus{ 108 Handlers: []runtimev1.ExtensionHandler{ 109 { 110 Name: "foo.extension1", 111 RequestHook: runtimev1.GroupVersionHook{ 112 APIVersion: "hook.runtime.cluster.x-k8s.io/v1alpha1", 113 Hook: "BeforeClusterUpgrade", 114 }, 115 }, 116 { 117 Name: "bar.extension1", 118 RequestHook: runtimev1.GroupVersionHook{ 119 APIVersion: "hook.runtime.cluster.x-k8s.io/v1alpha1", 120 Hook: "BeforeClusterUpgrade", 121 }, 122 }, 123 { 124 Name: "baz.extension1", 125 RequestHook: runtimev1.GroupVersionHook{ 126 APIVersion: "hook.runtime.cluster.x-k8s.io/v1alpha1", 127 Hook: "AfterClusterUpgrade", 128 }, 129 }, 130 }, 131 }, 132 } 133 134 extension2 := &runtimev1.ExtensionConfig{ 135 ObjectMeta: metav1.ObjectMeta{ 136 Name: "extension2", 137 }, 138 Spec: runtimev1.ExtensionConfigSpec{ 139 ClientConfig: runtimev1.ClientConfig{ 140 URL: ptr.To("https://extesions2.com/"), 141 }, 142 }, 143 Status: runtimev1.ExtensionConfigStatus{ 144 Handlers: []runtimev1.ExtensionHandler{ 145 { 146 Name: "qux.extension2", 147 RequestHook: runtimev1.GroupVersionHook{ 148 APIVersion: "hook.runtime.cluster.x-k8s.io/v1alpha1", 149 Hook: "AfterClusterUpgrade", 150 }, 151 }, 152 }, 153 }, 154 } 155 156 // WarmUp with extension1 157 e := New() 158 err := e.WarmUp(&runtimev1.ExtensionConfigList{Items: []runtimev1.ExtensionConfig{*extension1}}) 159 g.Expect(err).ToNot(HaveOccurred()) 160 g.Expect(e.IsReady()).To(BeTrue()) 161 162 // Get an extension by name 163 registration, err := e.Get("foo.extension1") 164 g.Expect(err).ToNot(HaveOccurred()) 165 g.Expect(registration.Name).To(Equal("foo.extension1")) 166 167 // List all BeforeClusterUpgrade extensions 168 registrations, err := e.List(runtimecatalog.GroupHook{Group: "hook.runtime.cluster.x-k8s.io", Hook: "BeforeClusterUpgrade"}) 169 g.Expect(err).ToNot(HaveOccurred()) 170 g.Expect(registrations).To(HaveLen(2)) 171 g.Expect(registrations).To(ContainExtension("foo.extension1")) 172 g.Expect(registrations).To(ContainExtension("bar.extension1")) 173 174 // List all AfterClusterUpgrade extensions 175 registrations, err = e.List(runtimecatalog.GroupHook{Group: "hook.runtime.cluster.x-k8s.io", Hook: "AfterClusterUpgrade"}) 176 g.Expect(err).ToNot(HaveOccurred()) 177 g.Expect(registrations).To(HaveLen(1)) 178 g.Expect(registrations).To(ContainExtension("baz.extension1")) 179 180 // Add extension2 with one more AfterClusterUpgrade and check it is there 181 g.Expect(e.Add(extension2)).To(Succeed()) 182 183 registrations, err = e.List(runtimecatalog.GroupHook{Group: "hook.runtime.cluster.x-k8s.io", Hook: "AfterClusterUpgrade"}) 184 g.Expect(err).ToNot(HaveOccurred()) 185 g.Expect(registrations).To(HaveLen(2)) 186 g.Expect(registrations).To(ContainExtension("baz.extension1")) 187 g.Expect(registrations).To(ContainExtension("qux.extension2")) 188 189 // Remove extension1 and check everything is updated 190 g.Expect(e.Remove(extension1)).To(Succeed()) 191 192 registrations, err = e.List(runtimecatalog.GroupHook{Group: "hook.runtime.cluster.x-k8s.io", Hook: "BeforeClusterUpgrade"}) 193 g.Expect(err).ToNot(HaveOccurred()) 194 g.Expect(registrations).To(BeEmpty()) 195 196 registrations, err = e.List(runtimecatalog.GroupHook{Group: "hook.runtime.cluster.x-k8s.io", Hook: "AfterClusterUpgrade"}) 197 g.Expect(err).ToNot(HaveOccurred()) 198 g.Expect(registrations).To(HaveLen(1)) 199 g.Expect(registrations).To(ContainExtension("qux.extension2")) 200 } 201 202 func ContainExtension(name string) types.GomegaMatcher { 203 return &ContainExtensionMatcher{ 204 name: name, 205 } 206 } 207 208 type ContainExtensionMatcher struct { 209 name string 210 } 211 212 func (matcher *ContainExtensionMatcher) Match(actual interface{}) (success bool, err error) { 213 ext, ok := actual.([]*ExtensionRegistration) 214 if !ok { 215 return false, errors.Errorf("Expecting *ExtensionRegistration, got %t", actual) 216 } 217 218 for _, e := range ext { 219 if e.Name == matcher.name { 220 return true, nil 221 } 222 } 223 return false, nil 224 } 225 226 func (matcher *ContainExtensionMatcher) FailureMessage(actual interface{}) (message string) { 227 return format.Message(actual, "to contain element matching", matcher.name) 228 } 229 230 func (matcher *ContainExtensionMatcher) NegatedFailureMessage(actual interface{}) (message string) { 231 return format.Message(actual, "not to contain element matching", matcher.name) 232 }