sigs.k8s.io/cluster-api@v1.7.1/cmd/clusterctl/client/config/reader_viper_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 config 18 19 import ( 20 "context" 21 "fmt" 22 "net/http" 23 "net/http/httptest" 24 "os" 25 "path/filepath" 26 "strings" 27 "testing" 28 29 . "github.com/onsi/gomega" 30 ) 31 32 func Test_viperReader_Init(t *testing.T) { 33 g := NewWithT(t) 34 35 // Change HOME dir and do not specify config file 36 // (.cluster-api/clusterctl) in it. 37 clusterctlHomeDir, err := os.MkdirTemp("", "clusterctl-default") 38 g.Expect(err).ToNot(HaveOccurred()) 39 defer os.RemoveAll(clusterctlHomeDir) 40 41 dir, err := os.MkdirTemp("", "clusterctl") 42 g.Expect(err).ToNot(HaveOccurred()) 43 defer os.RemoveAll(dir) 44 45 configFile := filepath.Join(dir, "clusterctl.yaml") 46 g.Expect(os.WriteFile(configFile, []byte("bar: bar"), 0600)).To(Succeed()) 47 48 configFileBadContents := filepath.Join(dir, "clusterctl-bad.yaml") 49 g.Expect(os.WriteFile(configFileBadContents, []byte("bad-contents"), 0600)).To(Succeed()) 50 51 // To test the remote config file 52 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { 53 w.Header().Set("Content-Type", "text/plain") 54 _, err := w.Write([]byte("bar: bar")) 55 g.Expect(err).ToNot(HaveOccurred()) 56 })) 57 defer ts.Close() 58 59 // To test the remote config file when fails to fetch 60 tsFail := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { 61 w.WriteHeader(http.StatusNotFound) 62 })) 63 defer tsFail.Close() 64 65 tests := []struct { 66 name string 67 configPath string 68 configDirs []string 69 expectErr bool 70 }{ 71 { 72 name: "reads in config successfully", 73 configPath: configFile, 74 configDirs: []string{clusterctlHomeDir}, 75 expectErr: false, 76 }, 77 { 78 name: "returns error for invalid config file path", 79 configPath: "do-not-exist.yaml", 80 configDirs: []string{clusterctlHomeDir}, 81 expectErr: true, 82 }, 83 { 84 name: "does not return error if default file doesn't exist", 85 configPath: "", 86 configDirs: []string{clusterctlHomeDir}, 87 expectErr: false, 88 }, 89 { 90 name: "returns error for malformed config", 91 configPath: configFileBadContents, 92 configDirs: []string{clusterctlHomeDir}, 93 expectErr: true, 94 }, 95 { 96 name: "reads in config from remote successfully", 97 configPath: ts.URL, 98 configDirs: []string{clusterctlHomeDir}, 99 expectErr: false, 100 }, 101 { 102 name: "fail to read remote config", 103 configPath: tsFail.URL, 104 configDirs: []string{clusterctlHomeDir}, 105 expectErr: true, 106 }, 107 } 108 109 for _, tt := range tests { 110 t.Run(tt.name, func(t *testing.T) { 111 gg := NewWithT(t) 112 113 ctx := context.Background() 114 115 v, _ := newViperReader(injectConfigPaths(tt.configDirs)) 116 if tt.expectErr { 117 gg.Expect(v.Init(ctx, tt.configPath)).ToNot(Succeed()) 118 return 119 } 120 gg.Expect(v.Init(ctx, tt.configPath)).To(Succeed()) 121 }) 122 } 123 } 124 125 func Test_viperReader_Get(t *testing.T) { 126 g := NewWithT(t) 127 128 dir, err := os.MkdirTemp("", "clusterctl") 129 g.Expect(err).ToNot(HaveOccurred()) 130 defer os.RemoveAll(dir) 131 132 _ = os.Setenv("FOO", "foo") 133 134 configFile := filepath.Join(dir, "clusterctl.yaml") 135 g.Expect(os.WriteFile(configFile, []byte("bar: bar"), 0600)).To(Succeed()) 136 137 type args struct { 138 key string 139 } 140 tests := []struct { 141 name string 142 args args 143 want string 144 wantErr bool 145 }{ 146 { 147 name: "Read from env", 148 args: args{ 149 key: "FOO", 150 }, 151 want: "foo", 152 wantErr: false, 153 }, 154 { 155 name: "Read from file", 156 args: args{ 157 key: "BAR", 158 }, 159 want: "bar", 160 wantErr: false, 161 }, 162 { 163 name: "Fails if missing", 164 args: args{ 165 key: "BAZ", 166 }, 167 want: "", 168 wantErr: true, 169 }, 170 } 171 for _, tt := range tests { 172 t.Run(tt.name, func(t *testing.T) { 173 gs := NewWithT(t) 174 175 ctx := context.Background() 176 177 v, _ := newViperReader(injectConfigPaths([]string{dir})) 178 179 gs.Expect(v.Init(ctx, configFile)).To(Succeed()) 180 181 got, err := v.Get(tt.args.key) 182 if tt.wantErr { 183 gs.Expect(err).To(HaveOccurred()) 184 return 185 } 186 187 gs.Expect(err).ToNot(HaveOccurred()) 188 gs.Expect(got).To(Equal(tt.want)) 189 }) 190 } 191 } 192 193 func Test_viperReader_GetWithoutDefaultConfig(t *testing.T) { 194 g := NewWithT(t) 195 196 ctx := context.Background() 197 198 dir, err := os.MkdirTemp("", "clusterctl") 199 g.Expect(err).ToNot(HaveOccurred()) 200 defer os.RemoveAll(dir) 201 202 _ = os.Setenv("FOO_FOO", "bar") 203 204 v, err := newViperReader(injectConfigPaths([]string{dir})) 205 g.Expect(err).ToNot(HaveOccurred()) 206 g.Expect(v.Init(ctx, "")).To(Succeed()) 207 208 got, err := v.Get("FOO_FOO") 209 g.Expect(err).ToNot(HaveOccurred()) 210 g.Expect(got).To(Equal("bar")) 211 } 212 213 func Test_viperReader_Set(t *testing.T) { 214 g := NewWithT(t) 215 216 dir, err := os.MkdirTemp("", "clusterctl") 217 g.Expect(err).ToNot(HaveOccurred()) 218 defer os.RemoveAll(dir) 219 220 _ = os.Setenv("FOO", "foo") 221 222 configFile := filepath.Join(dir, "clusterctl.yaml") 223 224 g.Expect(os.WriteFile(configFile, []byte("bar: bar"), 0600)).To(Succeed()) 225 226 type args struct { 227 key string 228 value string 229 } 230 tests := []struct { 231 name string 232 args args 233 want string 234 }{ 235 { 236 name: "", 237 args: args{ 238 key: "FOO", 239 value: "bar", 240 }, 241 want: "bar", 242 }, 243 } 244 for _, tt := range tests { 245 t.Run(tt.name, func(t *testing.T) { 246 gs := NewWithT(t) 247 248 ctx := context.Background() 249 250 v := &viperReader{} 251 252 gs.Expect(v.Init(ctx, configFile)).To(Succeed()) 253 254 v.Set(tt.args.key, tt.args.value) 255 256 got, err := v.Get(tt.args.key) 257 gs.Expect(err).ToNot(HaveOccurred()) 258 gs.Expect(got).To(Equal(tt.want)) 259 }) 260 } 261 } 262 263 func Test_viperReader_checkDefaultConfig(t *testing.T) { 264 g := NewWithT(t) 265 dir, err := os.MkdirTemp("", "clusterctl") 266 g.Expect(err).ToNot(HaveOccurred()) 267 defer os.RemoveAll(dir) 268 dir = strings.TrimSuffix(dir, "/") 269 270 configFile := filepath.Join(dir, "clusterctl.yaml") 271 g.Expect(os.WriteFile(configFile, []byte("bar: bar"), 0600)).To(Succeed()) 272 273 type fields struct { 274 configPaths []string 275 } 276 tests := []struct { 277 name string 278 fields fields 279 want bool 280 }{ 281 { 282 name: "tmp path without final /", 283 fields: fields{ 284 configPaths: []string{dir}, 285 }, 286 want: true, 287 }, 288 { 289 name: "tmp path with final /", 290 fields: fields{ 291 configPaths: []string{fmt.Sprintf("%s/", dir)}, 292 }, 293 want: true, 294 }, 295 } 296 for _, tt := range tests { 297 t.Run(tt.name, func(t *testing.T) { 298 gs := NewWithT(t) 299 300 v := &viperReader{ 301 configPaths: tt.fields.configPaths, 302 } 303 gs.Expect(v.checkDefaultConfig()).To(Equal(tt.want)) 304 }) 305 } 306 }