k8s.io/apiserver@v0.31.1/pkg/apis/apiserver/load/load_test.go (about) 1 /* 2 Copyright 2023 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 load 18 19 import ( 20 "bytes" 21 "os" 22 "reflect" 23 "strings" 24 "testing" 25 "time" 26 27 "github.com/google/go-cmp/cmp" 28 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 api "k8s.io/apiserver/pkg/apis/apiserver" 31 ) 32 33 var defaultConfig = &api.AuthorizationConfiguration{} 34 35 func writeTempFile(t *testing.T, content string) string { 36 t.Helper() 37 file, err := os.CreateTemp("", "config") 38 if err != nil { 39 t.Fatal(err) 40 } 41 t.Cleanup(func() { 42 if err := os.Remove(file.Name()); err != nil { 43 t.Fatal(err) 44 } 45 }) 46 if err := os.WriteFile(file.Name(), []byte(content), 0600); err != nil { 47 t.Fatal(err) 48 } 49 return file.Name() 50 } 51 52 func TestLoadFromFile(t *testing.T) { 53 // no file 54 { 55 _, err := LoadFromFile("") 56 if err == nil { 57 t.Fatalf("expected err: %v", err) 58 } 59 } 60 61 // empty file 62 { 63 config, err := LoadFromFile(writeTempFile(t, ``)) 64 if err != nil { 65 t.Fatalf("unexpected err: %v", err) 66 } 67 if !reflect.DeepEqual(config, defaultConfig) { 68 t.Fatalf("unexpected config:\n%s", cmp.Diff(defaultConfig, config)) 69 } 70 } 71 72 // valid file 73 { 74 input := `{ 75 "apiVersion":"apiserver.config.k8s.io/v1alpha1", 76 "kind":"AuthorizationConfiguration", 77 "authorizers":[{"type":"Webhook"}]}` 78 expect := &api.AuthorizationConfiguration{ 79 Authorizers: []api.AuthorizerConfiguration{{Type: "Webhook"}}, 80 } 81 82 config, err := LoadFromFile(writeTempFile(t, input)) 83 if err != nil { 84 t.Fatalf("unexpected err: %v", err) 85 } 86 if !reflect.DeepEqual(config, expect) { 87 t.Fatalf("unexpected config:\n%s", cmp.Diff(expect, config)) 88 } 89 } 90 91 // missing file 92 { 93 _, err := LoadFromFile(`bogus-missing-file`) 94 if err == nil { 95 t.Fatalf("expected err, got none") 96 } 97 if !strings.Contains(err.Error(), "bogus-missing-file") { 98 t.Fatalf("expected missing file error, got %v", err) 99 } 100 } 101 102 // invalid content file 103 { 104 input := `{ 105 "apiVersion":"apiserver.config.k8s.io/v99", 106 "kind":"AuthorizationConfiguration", 107 "authorizers":{"type":"Webhook"}}` 108 109 _, err := LoadFromFile(writeTempFile(t, input)) 110 if err == nil { 111 t.Fatalf("expected err, got none") 112 } 113 if !strings.Contains(err.Error(), "apiserver.config.k8s.io/v99") { 114 t.Fatalf("expected apiVersion error, got %v", err) 115 } 116 } 117 } 118 119 func TestLoadFromReader(t *testing.T) { 120 // no reader 121 { 122 config, err := LoadFromReader(nil) 123 if err != nil { 124 t.Fatalf("unexpected err: %v", err) 125 } 126 if !reflect.DeepEqual(config, defaultConfig) { 127 t.Fatalf("unexpected config:\n%s", cmp.Diff(defaultConfig, config)) 128 } 129 } 130 131 // empty reader 132 { 133 config, err := LoadFromReader(&bytes.Buffer{}) 134 if err != nil { 135 t.Fatalf("unexpected err: %v", err) 136 } 137 if !reflect.DeepEqual(config, defaultConfig) { 138 t.Fatalf("unexpected config:\n%s", cmp.Diff(defaultConfig, config)) 139 } 140 } 141 142 // valid reader 143 { 144 input := `{ 145 "apiVersion":"apiserver.config.k8s.io/v1alpha1", 146 "kind":"AuthorizationConfiguration", 147 "authorizers":[{"type":"Webhook"}]}` 148 expect := &api.AuthorizationConfiguration{ 149 Authorizers: []api.AuthorizerConfiguration{{Type: "Webhook"}}, 150 } 151 152 config, err := LoadFromReader(bytes.NewBufferString(input)) 153 if err != nil { 154 t.Fatalf("unexpected err: %v", err) 155 } 156 if !reflect.DeepEqual(config, expect) { 157 t.Fatalf("unexpected config:\n%s", cmp.Diff(expect, config)) 158 } 159 } 160 161 // invalid reader 162 { 163 input := `{ 164 "apiVersion":"apiserver.config.k8s.io/v99", 165 "kind":"AuthorizationConfiguration", 166 "authorizers":[{"type":"Webhook"}]}` 167 168 _, err := LoadFromReader(bytes.NewBufferString(input)) 169 if err == nil { 170 t.Fatalf("expected err, got none") 171 } 172 if !strings.Contains(err.Error(), "apiserver.config.k8s.io/v99") { 173 t.Fatalf("expected apiVersion error, got %v", err) 174 } 175 } 176 } 177 178 func TestLoadFromData(t *testing.T) { 179 testcases := []struct { 180 name string 181 data []byte 182 expectErr string 183 expectConfig *api.AuthorizationConfiguration 184 }{ 185 { 186 name: "nil", 187 data: nil, 188 expectConfig: defaultConfig, 189 }, 190 { 191 name: "nil", 192 data: []byte{}, 193 expectConfig: defaultConfig, 194 }, 195 { 196 name: "v1alpha1 - json", 197 data: []byte(`{ 198 "apiVersion":"apiserver.config.k8s.io/v1alpha1", 199 "kind":"AuthorizationConfiguration", 200 "authorizers":[{"type":"Webhook"}]}`), 201 expectConfig: &api.AuthorizationConfiguration{ 202 Authorizers: []api.AuthorizerConfiguration{{Type: "Webhook"}}, 203 }, 204 }, 205 { 206 name: "v1alpha1 - defaults", 207 data: []byte(`{ 208 "apiVersion":"apiserver.config.k8s.io/v1alpha1", 209 "kind":"AuthorizationConfiguration", 210 "authorizers":[{"type":"Webhook","name":"default","webhook":{}}]}`), 211 expectConfig: &api.AuthorizationConfiguration{ 212 Authorizers: []api.AuthorizerConfiguration{{ 213 Type: "Webhook", 214 Name: "default", 215 Webhook: &api.WebhookConfiguration{ 216 AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute}, 217 UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second}, 218 }, 219 }}, 220 }, 221 }, 222 { 223 name: "v1alpha1 - yaml", 224 data: []byte(` 225 apiVersion: apiserver.config.k8s.io/v1alpha1 226 kind: AuthorizationConfiguration 227 authorizers: 228 - type: Webhook 229 `), 230 expectConfig: &api.AuthorizationConfiguration{ 231 Authorizers: []api.AuthorizerConfiguration{{Type: "Webhook"}}, 232 }, 233 }, 234 { 235 name: "v1beta1 - json", 236 data: []byte(`{ 237 "apiVersion":"apiserver.config.k8s.io/v1beta1", 238 "kind":"AuthorizationConfiguration", 239 "authorizers":[{"type":"Webhook"}]}`), 240 expectConfig: &api.AuthorizationConfiguration{ 241 Authorizers: []api.AuthorizerConfiguration{{Type: "Webhook"}}, 242 }, 243 }, 244 { 245 name: "v1beta1 - defaults", 246 data: []byte(`{ 247 "apiVersion":"apiserver.config.k8s.io/v1beta1", 248 "kind":"AuthorizationConfiguration", 249 "authorizers":[{"type":"Webhook","name":"default","webhook":{}}]}`), 250 expectConfig: &api.AuthorizationConfiguration{ 251 Authorizers: []api.AuthorizerConfiguration{{ 252 Type: "Webhook", 253 Name: "default", 254 Webhook: &api.WebhookConfiguration{ 255 AuthorizedTTL: metav1.Duration{Duration: 5 * time.Minute}, 256 UnauthorizedTTL: metav1.Duration{Duration: 30 * time.Second}, 257 }, 258 }}, 259 }, 260 }, 261 { 262 name: "v1beta1 - yaml", 263 data: []byte(` 264 apiVersion: apiserver.config.k8s.io/v1beta1 265 kind: AuthorizationConfiguration 266 authorizers: 267 - type: Webhook 268 `), 269 expectConfig: &api.AuthorizationConfiguration{ 270 Authorizers: []api.AuthorizerConfiguration{{Type: "Webhook"}}, 271 }, 272 }, 273 { 274 name: "missing apiVersion", 275 data: []byte(`{"kind":"AuthorizationConfiguration"}`), 276 expectErr: `'apiVersion' is missing`, 277 }, 278 { 279 name: "missing kind", 280 data: []byte(`{"apiVersion":"apiserver.config.k8s.io/v1alpha1"}`), 281 expectErr: `'Kind' is missing`, 282 }, 283 { 284 name: "unknown group", 285 data: []byte(`{"apiVersion":"apps/v1alpha1","kind":"AuthorizationConfiguration"}`), 286 expectErr: `apps/v1alpha1`, 287 }, 288 { 289 name: "unknown version", 290 data: []byte(`{"apiVersion":"apiserver.config.k8s.io/v99","kind":"AuthorizationConfiguration"}`), 291 expectErr: `apiserver.config.k8s.io/v99`, 292 }, 293 { 294 name: "unknown kind", 295 data: []byte(`{"apiVersion":"apiserver.config.k8s.io/v1alpha1","kind":"SomeConfiguration"}`), 296 expectErr: `SomeConfiguration`, 297 }, 298 { 299 name: "unknown field", 300 data: []byte(`{ 301 "apiVersion":"apiserver.config.k8s.io/v1alpha1", 302 "kind":"AuthorizationConfiguration", 303 "authorzers":[{"type":"Webhook"}]}`), 304 expectErr: `unknown field "authorzers"`, 305 }, 306 } 307 308 for _, tc := range testcases { 309 t.Run(tc.name, func(t *testing.T) { 310 config, err := LoadFromData(tc.data) 311 if err != nil { 312 if len(tc.expectErr) == 0 { 313 t.Fatalf("unexpected error: %v", err) 314 } 315 if !strings.Contains(err.Error(), tc.expectErr) { 316 t.Fatalf("unexpected error: %v", err) 317 } 318 return 319 } 320 if len(tc.expectErr) > 0 { 321 t.Fatalf("expected err, got none") 322 } 323 324 if !reflect.DeepEqual(config, tc.expectConfig) { 325 t.Fatalf("unexpected config:\n%s", cmp.Diff(tc.expectConfig, config)) 326 } 327 }) 328 } 329 }