sigs.k8s.io/cluster-api@v1.7.1/cmd/clusterctl/client/repository/components_client_test.go (about) 1 /* 2 Copyright 2019 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 repository 18 19 import ( 20 "context" 21 "fmt" 22 "testing" 23 24 . "github.com/onsi/gomega" 25 "github.com/pkg/errors" 26 27 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 28 clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" 29 "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" 30 yaml "sigs.k8s.io/cluster-api/cmd/clusterctl/client/yamlprocessor" 31 "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test" 32 utilyaml "sigs.k8s.io/cluster-api/util/yaml" 33 ) 34 35 const ( 36 variableName = "FOO" 37 variableValue = "foo" 38 ) 39 40 var controllerYaml = []byte("apiVersion: apps/v1\n" + 41 "kind: Deployment\n" + 42 "metadata:\n" + 43 " name: my-controller\n" + 44 "spec:\n" + 45 " template:\n" + 46 " spec:\n" + 47 " containers:\n" + 48 " - name: manager\n" + 49 " image: docker.io/library/image:latest\n") 50 51 const namespaceName = "capa-system" 52 53 var namespaceYaml = []byte("apiVersion: v1\n" + 54 "kind: Namespace\n" + 55 "metadata:\n" + 56 fmt.Sprintf(" name: %s", namespaceName)) 57 58 var configMapYaml = []byte("apiVersion: v1\n" + 59 "data:\n" + 60 fmt.Sprintf(" variable: ${%s}\n", variableName) + 61 "kind: ConfigMap\n" + 62 "metadata:\n" + 63 " name: manager") 64 65 func Test_componentsClient_Get(t *testing.T) { 66 g := NewWithT(t) 67 68 p1 := config.NewProvider("p1", "", clusterctlv1.BootstrapProviderType) 69 70 configClient, err := config.New(context.Background(), "", config.InjectReader(test.NewFakeReader().WithVar(variableName, variableValue))) 71 g.Expect(err).ToNot(HaveOccurred()) 72 73 type fields struct { 74 provider config.Provider 75 repository Repository 76 processor yaml.Processor 77 } 78 type args struct { 79 version string 80 targetNamespace string 81 skipVariables bool 82 } 83 type want struct { 84 provider config.Provider 85 version string 86 targetNamespace string 87 variables []string 88 } 89 tests := []struct { 90 name string 91 fields fields 92 args args 93 want want 94 wantErr bool 95 }{ 96 { 97 name: "successfully gets the components", 98 fields: fields{ 99 provider: p1, 100 repository: NewMemoryRepository(). 101 WithPaths("root", "components.yaml"). 102 WithDefaultVersion("v1.0.0"). 103 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(namespaceYaml, controllerYaml, configMapYaml)), 104 }, 105 args: args{ 106 version: "v1.0.0", 107 targetNamespace: "", 108 }, 109 want: want{ 110 provider: p1, 111 version: "v1.0.0", // version detected 112 targetNamespace: namespaceName, // default targetNamespace detected 113 variables: []string{variableName}, // variable detected 114 }, 115 wantErr: false, 116 }, 117 { 118 name: "successfully gets the components even with SkipTemplateProcess defined", 119 fields: fields{ 120 provider: p1, 121 repository: NewMemoryRepository(). 122 WithPaths("root", "components.yaml"). 123 WithDefaultVersion("v1.0.0"). 124 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(namespaceYaml, controllerYaml, configMapYaml)), 125 }, 126 args: args{ 127 version: "v1.0.0", 128 targetNamespace: "", 129 skipVariables: true, 130 }, 131 want: want{ 132 provider: p1, 133 version: "v1.0.0", // version detected 134 targetNamespace: namespaceName, // default targetNamespace detected 135 variables: []string{variableName}, // variable detected 136 }, 137 wantErr: false, 138 }, 139 { 140 name: "targetNamespace overrides default targetNamespace", 141 fields: fields{ 142 provider: p1, 143 repository: NewMemoryRepository(). 144 WithPaths("root", "components.yaml"). 145 WithDefaultVersion("v1.0.0"). 146 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(namespaceYaml, controllerYaml, configMapYaml)), 147 }, 148 args: args{ 149 version: "v1.0.0", 150 targetNamespace: "ns2", 151 }, 152 want: want{ 153 provider: p1, 154 version: "v1.0.0", // version detected 155 targetNamespace: "ns2", // targetNamespace overrides default targetNamespace 156 variables: []string{variableName}, // variable detected 157 }, 158 wantErr: false, 159 }, 160 { 161 name: "Fails if components file does not exists", 162 fields: fields{ 163 provider: p1, 164 repository: NewMemoryRepository(). 165 WithPaths("root", "components.yaml"). 166 WithDefaultVersion("v1.0.0"), 167 }, 168 args: args{ 169 version: "v1.0.0", 170 targetNamespace: "", 171 }, 172 wantErr: true, 173 }, 174 { 175 name: "Fails if default targetNamespace does not exists", 176 fields: fields{ 177 provider: p1, 178 repository: NewMemoryRepository(). 179 WithPaths("root", "components.yaml"). 180 WithDefaultVersion("v1.0.0"). 181 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(controllerYaml, configMapYaml)), 182 }, 183 args: args{ 184 version: "v1.0.0", 185 targetNamespace: "", 186 }, 187 wantErr: true, 188 }, 189 { 190 name: "Pass if default targetNamespace does not exists but a target targetNamespace is set", 191 fields: fields{ 192 provider: p1, 193 repository: NewMemoryRepository(). 194 WithPaths("root", "components.yaml"). 195 WithDefaultVersion("v1.0.0"). 196 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(controllerYaml, configMapYaml)), 197 }, 198 args: args{ 199 version: "v1.0.0", 200 targetNamespace: "ns2", 201 }, 202 want: want{ 203 provider: p1, 204 version: "v1.0.0", // version detected 205 targetNamespace: "ns2", // target targetNamespace applied 206 variables: []string{variableName}, // variable detected 207 }, 208 wantErr: false, 209 }, 210 { 211 name: "Fails if requested version does not exists", 212 fields: fields{ 213 provider: p1, 214 repository: NewMemoryRepository(). 215 WithPaths("root", "components.yaml"). 216 WithDefaultVersion("v1.0.0"). 217 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(controllerYaml, configMapYaml)), 218 }, 219 args: args{ 220 version: "v2.0.0", 221 targetNamespace: "", 222 }, 223 wantErr: true, 224 }, 225 { 226 name: "Fails if yaml processor cannot get Variables", 227 fields: fields{ 228 provider: p1, 229 repository: NewMemoryRepository(). 230 WithPaths("root", "components.yaml"). 231 WithDefaultVersion("v1.0.0"). 232 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(namespaceYaml, controllerYaml, configMapYaml)), 233 processor: test.NewFakeProcessor().WithGetVariablesErr(errors.New("cannot get vars")), 234 }, 235 args: args{ 236 version: "v1.0.0", 237 targetNamespace: "default", 238 }, 239 wantErr: true, 240 }, 241 { 242 name: "Fails if yaml processor cannot process the raw yaml", 243 fields: fields{ 244 provider: p1, 245 repository: NewMemoryRepository(). 246 WithPaths("root", "components.yaml"). 247 WithDefaultVersion("v1.0.0"). 248 WithFile("v1.0.0", "components.yaml", utilyaml.JoinYaml(namespaceYaml, controllerYaml, configMapYaml)), 249 250 processor: test.NewFakeProcessor().WithProcessErr(errors.New("cannot process")), 251 }, 252 args: args{ 253 version: "v1.0.0", 254 targetNamespace: "default", 255 }, 256 wantErr: true, 257 }, 258 } 259 for _, tt := range tests { 260 t.Run(tt.name, func(t *testing.T) { 261 gs := NewWithT(t) 262 263 ctx := context.Background() 264 265 options := ComponentsOptions{ 266 Version: tt.args.version, 267 TargetNamespace: tt.args.targetNamespace, 268 SkipTemplateProcess: tt.args.skipVariables, 269 } 270 f := newComponentsClient(tt.fields.provider, tt.fields.repository, configClient) 271 if tt.fields.processor != nil { 272 f.processor = tt.fields.processor 273 } 274 got, err := f.Get(ctx, options) 275 if tt.wantErr { 276 gs.Expect(err).To(HaveOccurred()) 277 return 278 } 279 gs.Expect(err).ToNot(HaveOccurred()) 280 281 gs.Expect(got.Name()).To(Equal(tt.want.provider.Name())) 282 gs.Expect(got.Type()).To(Equal(tt.want.provider.Type())) 283 gs.Expect(got.Version()).To(Equal(tt.want.version)) 284 gs.Expect(got.TargetNamespace()).To(Equal(tt.want.targetNamespace)) 285 gs.Expect(got.Variables()).To(Equal(tt.want.variables)) 286 287 yaml, err := got.Yaml() 288 if err != nil { 289 t.Errorf("got.Yaml() error = %v", err) 290 return 291 } 292 293 if !tt.args.skipVariables && len(tt.want.variables) > 0 { 294 gs.Expect(yaml).To(ContainSubstring(variableValue)) 295 } 296 297 // Verify that when SkipTemplateProcess is set we have all the variables 298 // in the template without the values processed. 299 if tt.args.skipVariables { 300 for _, v := range tt.want.variables { 301 gs.Expect(yaml).To(ContainSubstring(v)) 302 } 303 } 304 305 for _, o := range got.Objs() { 306 for _, v := range []string{clusterctlv1.ClusterctlLabel, clusterv1.ProviderNameLabel} { 307 gs.Expect(o.GetLabels()).To(HaveKey(v)) 308 } 309 } 310 }) 311 } 312 }