github.com/defensepoint-snyk-test/helm-new@v0.0.0-20211130153739-c57ea64d6603/cmd/helm/helm_test.go (about) 1 /* 2 Copyright The Helm 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 main 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "regexp" 27 "strings" 28 "testing" 29 30 "github.com/spf13/cobra" 31 32 "k8s.io/client-go/util/homedir" 33 "k8s.io/helm/pkg/helm" 34 "k8s.io/helm/pkg/helm/environment" 35 "k8s.io/helm/pkg/helm/helmpath" 36 "k8s.io/helm/pkg/proto/hapi/release" 37 "k8s.io/helm/pkg/repo" 38 ) 39 40 // releaseCmd is a command that works with a FakeClient 41 type releaseCmd func(c *helm.FakeClient, out io.Writer) *cobra.Command 42 43 // runReleaseCases runs a set of release cases through the given releaseCmd. 44 func runReleaseCases(t *testing.T, tests []releaseCase, rcmd releaseCmd) { 45 var buf bytes.Buffer 46 for _, tt := range tests { 47 t.Run(tt.name, func(t *testing.T) { 48 c := &helm.FakeClient{ 49 Rels: tt.rels, 50 Responses: tt.responses, 51 } 52 cmd := rcmd(c, &buf) 53 cmd.ParseFlags(tt.flags) 54 err := cmd.RunE(cmd, tt.args) 55 if (err != nil) != tt.err { 56 t.Errorf("expected error, got '%v'", err) 57 } 58 re := regexp.MustCompile(tt.expected) 59 if !re.Match(buf.Bytes()) { 60 t.Errorf("expected\n%q\ngot\n%q", tt.expected, buf.String()) 61 } 62 buf.Reset() 63 }) 64 } 65 } 66 67 // releaseCase describes a test case that works with releases. 68 type releaseCase struct { 69 name string 70 args []string 71 flags []string 72 // expected is the string to be matched. This supports regular expressions. 73 expected string 74 err bool 75 resp *release.Release 76 // Rels are the available releases at the start of the test. 77 rels []*release.Release 78 responses map[string]release.TestRun_Status 79 } 80 81 // tempHelmHome sets up a Helm Home in a temp dir. 82 // 83 // This does not clean up the directory. You must do that yourself. 84 // You must also set helmHome yourself. 85 func tempHelmHome(t *testing.T) (helmpath.Home, error) { 86 oldhome := settings.Home 87 dir, err := ioutil.TempDir("", "helm_home-") 88 if err != nil { 89 return helmpath.Home("n/"), err 90 } 91 92 settings.Home = helmpath.Home(dir) 93 if err := ensureTestHome(settings.Home, t); err != nil { 94 return helmpath.Home("n/"), err 95 } 96 settings.Home = oldhome 97 return helmpath.Home(dir), nil 98 } 99 100 // ensureTestHome creates a home directory like ensureHome, but without remote references. 101 // 102 // t is used only for logging. 103 func ensureTestHome(home helmpath.Home, t *testing.T) error { 104 configDirectories := []string{home.String(), home.Repository(), home.Cache(), home.LocalRepository(), home.Plugins(), home.Starters()} 105 for _, p := range configDirectories { 106 if fi, err := os.Stat(p); err != nil { 107 if err := os.MkdirAll(p, 0755); err != nil { 108 return fmt.Errorf("Could not create %s: %s", p, err) 109 } 110 } else if !fi.IsDir() { 111 return fmt.Errorf("%s must be a directory", p) 112 } 113 } 114 115 repoFile := home.RepositoryFile() 116 if fi, err := os.Stat(repoFile); err != nil { 117 rf := repo.NewRepoFile() 118 rf.Add(&repo.Entry{ 119 Name: "charts", 120 URL: "http://example.com/foo", 121 Cache: "charts-index.yaml", 122 }, &repo.Entry{ 123 Name: "local", 124 URL: "http://localhost.com:7743/foo", 125 Cache: "local-index.yaml", 126 }) 127 if err := rf.WriteFile(repoFile, 0644); err != nil { 128 return err 129 } 130 } else if fi.IsDir() { 131 return fmt.Errorf("%s must be a file, not a directory", repoFile) 132 } 133 if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate { 134 t.Log("Updating repository file format...") 135 if err := r.WriteFile(repoFile, 0644); err != nil { 136 return err 137 } 138 } 139 140 localRepoIndexFile := home.LocalRepository(localRepositoryIndexFile) 141 if fi, err := os.Stat(localRepoIndexFile); err != nil { 142 i := repo.NewIndexFile() 143 if err := i.WriteFile(localRepoIndexFile, 0644); err != nil { 144 return err 145 } 146 147 //TODO: take this out and replace with helm update functionality 148 os.Symlink(localRepoIndexFile, home.CacheIndex("local")) 149 } else if fi.IsDir() { 150 return fmt.Errorf("%s must be a file, not a directory", localRepoIndexFile) 151 } 152 153 t.Logf("$HELM_HOME has been configured at %s.\n", settings.Home.String()) 154 return nil 155 156 } 157 158 func TestRootCmd(t *testing.T) { 159 cleanup := resetEnv() 160 defer cleanup() 161 162 tests := []struct { 163 name string 164 args []string 165 envars map[string]string 166 home string 167 }{ 168 { 169 name: "defaults", 170 args: []string{"home"}, 171 home: filepath.Join(homedir.HomeDir(), ".helm"), 172 }, 173 { 174 name: "with --home set", 175 args: []string{"--home", "/foo"}, 176 home: "/foo", 177 }, 178 { 179 name: "subcommands with --home set", 180 args: []string{"home", "--home", "/foo"}, 181 home: "/foo", 182 }, 183 { 184 name: "with $HELM_HOME set", 185 args: []string{"home"}, 186 envars: map[string]string{"HELM_HOME": "/bar"}, 187 home: "/bar", 188 }, 189 { 190 name: "subcommands with $HELM_HOME set", 191 args: []string{"home"}, 192 envars: map[string]string{"HELM_HOME": "/bar"}, 193 home: "/bar", 194 }, 195 { 196 name: "with $HELM_HOME and --home set", 197 args: []string{"home", "--home", "/foo"}, 198 envars: map[string]string{"HELM_HOME": "/bar"}, 199 home: "/foo", 200 }, 201 } 202 203 // ensure not set locally 204 os.Unsetenv("HELM_HOME") 205 206 for _, tt := range tests { 207 t.Run(tt.name, func(t *testing.T) { 208 defer os.Unsetenv("HELM_HOME") 209 210 for k, v := range tt.envars { 211 os.Setenv(k, v) 212 } 213 214 cmd := newRootCmd(tt.args) 215 cmd.SetOutput(ioutil.Discard) 216 cmd.SetArgs(tt.args) 217 cmd.Run = func(*cobra.Command, []string) {} 218 if err := cmd.Execute(); err != nil { 219 t.Errorf("unexpected error: %s", err) 220 } 221 222 if settings.Home.String() != tt.home { 223 t.Errorf("expected home %q, got %q", tt.home, settings.Home) 224 } 225 homeFlag := cmd.Flag("home").Value.String() 226 homeFlag = os.ExpandEnv(homeFlag) 227 if homeFlag != tt.home { 228 t.Errorf("expected home %q, got %q", tt.home, homeFlag) 229 } 230 }) 231 } 232 } 233 234 func TestTLSFlags(t *testing.T) { 235 cleanup := resetEnv() 236 defer cleanup() 237 238 homePath := os.Getenv("HELM_HOME") 239 if homePath == "" { 240 homePath = filepath.Join(homedir.HomeDir(), ".helm") 241 } 242 243 home := helmpath.Home(homePath) 244 245 tests := []struct { 246 name string 247 args []string 248 envars map[string]string 249 settings environment.EnvSettings 250 }{ 251 { 252 name: "defaults", 253 args: []string{"version", "-c"}, 254 settings: environment.EnvSettings{ 255 TillerHost: "", 256 TillerConnectionTimeout: 300, 257 TillerNamespace: "kube-system", 258 Home: home, 259 Debug: false, 260 KubeContext: "", 261 KubeConfig: "", 262 TLSEnable: false, 263 TLSVerify: false, 264 TLSServerName: "", 265 TLSCaCertFile: home.TLSCaCert(), 266 TLSCertFile: home.TLSCert(), 267 TLSKeyFile: home.TLSKey(), 268 }, 269 }, 270 { 271 name: "tls enable", 272 args: []string{"version", "-c", "--tls"}, 273 settings: environment.EnvSettings{ 274 TillerHost: "", 275 TillerConnectionTimeout: 300, 276 TillerNamespace: "kube-system", 277 Home: home, 278 Debug: false, 279 KubeContext: "", 280 KubeConfig: "", 281 TLSEnable: true, 282 TLSVerify: false, 283 TLSServerName: "", 284 TLSCaCertFile: home.TLSCaCert(), 285 TLSCertFile: home.TLSCert(), 286 TLSKeyFile: home.TLSKey(), 287 }, 288 }, 289 { 290 name: "tls verify", 291 args: []string{"version", "-c", "--tls-verify"}, 292 settings: environment.EnvSettings{ 293 TillerHost: "", 294 TillerConnectionTimeout: 300, 295 TillerNamespace: "kube-system", 296 Home: home, 297 Debug: false, 298 KubeContext: "", 299 KubeConfig: "", 300 TLSEnable: false, 301 TLSVerify: true, 302 TLSServerName: "", 303 TLSCaCertFile: home.TLSCaCert(), 304 TLSCertFile: home.TLSCert(), 305 TLSKeyFile: home.TLSKey(), 306 }, 307 }, 308 { 309 name: "tls servername", 310 args: []string{"version", "-c", "--tls-hostname=foo"}, 311 settings: environment.EnvSettings{ 312 TillerHost: "", 313 TillerConnectionTimeout: 300, 314 TillerNamespace: "kube-system", 315 Home: home, 316 Debug: false, 317 KubeContext: "", 318 KubeConfig: "", 319 TLSEnable: false, 320 TLSVerify: false, 321 TLSServerName: "foo", 322 TLSCaCertFile: home.TLSCaCert(), 323 TLSCertFile: home.TLSCert(), 324 TLSKeyFile: home.TLSKey(), 325 }, 326 }, 327 { 328 name: "tls cacert", 329 args: []string{"version", "-c", "--tls-ca-cert=/foo"}, 330 settings: environment.EnvSettings{ 331 TillerHost: "", 332 TillerConnectionTimeout: 300, 333 TillerNamespace: "kube-system", 334 Home: home, 335 Debug: false, 336 KubeContext: "", 337 KubeConfig: "", 338 TLSEnable: false, 339 TLSVerify: false, 340 TLSServerName: "", 341 TLSCaCertFile: "/foo", 342 TLSCertFile: home.TLSCert(), 343 TLSKeyFile: home.TLSKey(), 344 }, 345 }, 346 { 347 name: "tls cert", 348 args: []string{"version", "-c", "--tls-cert=/foo"}, 349 settings: environment.EnvSettings{ 350 TillerHost: "", 351 TillerConnectionTimeout: 300, 352 TillerNamespace: "kube-system", 353 Home: home, 354 Debug: false, 355 KubeContext: "", 356 KubeConfig: "", 357 TLSEnable: false, 358 TLSVerify: false, 359 TLSServerName: "", 360 TLSCaCertFile: home.TLSCaCert(), 361 TLSCertFile: "/foo", 362 TLSKeyFile: home.TLSKey(), 363 }, 364 }, 365 { 366 name: "tls key", 367 args: []string{"version", "-c", "--tls-key=/foo"}, 368 settings: environment.EnvSettings{ 369 TillerHost: "", 370 TillerConnectionTimeout: 300, 371 TillerNamespace: "kube-system", 372 Home: home, 373 Debug: false, 374 KubeContext: "", 375 KubeConfig: "", 376 TLSEnable: false, 377 TLSVerify: false, 378 TLSServerName: "", 379 TLSCaCertFile: home.TLSCaCert(), 380 TLSCertFile: home.TLSCert(), 381 TLSKeyFile: "/foo", 382 }, 383 }, 384 { 385 name: "tls enable envvar", 386 args: []string{"version", "-c"}, 387 envars: map[string]string{"HELM_TLS_ENABLE": "true"}, 388 settings: environment.EnvSettings{ 389 TillerHost: "", 390 TillerConnectionTimeout: 300, 391 TillerNamespace: "kube-system", 392 Home: home, 393 Debug: false, 394 KubeContext: "", 395 KubeConfig: "", 396 TLSEnable: true, 397 TLSVerify: false, 398 TLSServerName: "", 399 TLSCaCertFile: home.TLSCaCert(), 400 TLSCertFile: home.TLSCert(), 401 TLSKeyFile: home.TLSKey(), 402 }, 403 }, 404 { 405 name: "tls verify envvar", 406 args: []string{"version", "-c"}, 407 envars: map[string]string{"HELM_TLS_VERIFY": "true"}, 408 settings: environment.EnvSettings{ 409 TillerHost: "", 410 TillerConnectionTimeout: 300, 411 TillerNamespace: "kube-system", 412 Home: home, 413 Debug: false, 414 KubeContext: "", 415 KubeConfig: "", 416 TLSEnable: false, 417 TLSVerify: true, 418 TLSServerName: "", 419 TLSCaCertFile: home.TLSCaCert(), 420 TLSCertFile: home.TLSCert(), 421 TLSKeyFile: home.TLSKey(), 422 }, 423 }, 424 { 425 name: "tls servername envvar", 426 args: []string{"version", "-c"}, 427 envars: map[string]string{"HELM_TLS_HOSTNAME": "foo"}, 428 settings: environment.EnvSettings{ 429 TillerHost: "", 430 TillerConnectionTimeout: 300, 431 TillerNamespace: "kube-system", 432 Home: home, 433 Debug: false, 434 KubeContext: "", 435 KubeConfig: "", 436 TLSEnable: false, 437 TLSVerify: false, 438 TLSServerName: "foo", 439 TLSCaCertFile: home.TLSCaCert(), 440 TLSCertFile: home.TLSCert(), 441 TLSKeyFile: home.TLSKey(), 442 }, 443 }, 444 { 445 name: "tls cacert envvar", 446 args: []string{"version", "-c"}, 447 envars: map[string]string{"HELM_TLS_CA_CERT": "/foo"}, 448 settings: environment.EnvSettings{ 449 TillerHost: "", 450 TillerConnectionTimeout: 300, 451 TillerNamespace: "kube-system", 452 Home: home, 453 Debug: false, 454 KubeContext: "", 455 KubeConfig: "", 456 TLSEnable: false, 457 TLSVerify: false, 458 TLSServerName: "", 459 TLSCaCertFile: "/foo", 460 TLSCertFile: home.TLSCert(), 461 TLSKeyFile: home.TLSKey(), 462 }, 463 }, 464 { 465 name: "tls cert envvar", 466 args: []string{"version", "-c"}, 467 envars: map[string]string{"HELM_TLS_CERT": "/foo"}, 468 settings: environment.EnvSettings{ 469 TillerHost: "", 470 TillerConnectionTimeout: 300, 471 TillerNamespace: "kube-system", 472 Home: home, 473 Debug: false, 474 KubeContext: "", 475 KubeConfig: "", 476 TLSEnable: false, 477 TLSVerify: false, 478 TLSServerName: "", 479 TLSCaCertFile: home.TLSCaCert(), 480 TLSCertFile: "/foo", 481 TLSKeyFile: home.TLSKey(), 482 }, 483 }, 484 { 485 name: "tls key envvar", 486 args: []string{"version", "-c"}, 487 envars: map[string]string{"HELM_TLS_KEY": "/foo"}, 488 settings: environment.EnvSettings{ 489 TillerHost: "", 490 TillerConnectionTimeout: 300, 491 TillerNamespace: "kube-system", 492 Home: home, 493 Debug: false, 494 KubeContext: "", 495 KubeConfig: "", 496 TLSEnable: false, 497 TLSVerify: false, 498 TLSServerName: "", 499 TLSCaCertFile: home.TLSCaCert(), 500 TLSCertFile: home.TLSCert(), 501 TLSKeyFile: "/foo", 502 }, 503 }, 504 } 505 506 // ensure not set locally 507 tlsEnvvars := []string{ 508 "HELM_TLS_HOSTNAME", 509 "HELM_TLS_CA_CERT", 510 "HELM_TLS_CERT", 511 "HELM_TLS_KEY", 512 "HELM_TLS_VERIFY", 513 "HELM_TLS_ENABLE", 514 } 515 516 for i := range tlsEnvvars { 517 os.Unsetenv(tlsEnvvars[i]) 518 } 519 520 for _, tt := range tests { 521 t.Run(tt.name, func(t *testing.T) { 522 523 for k, v := range tt.envars { 524 os.Setenv(k, v) 525 defer os.Unsetenv(k) 526 } 527 528 cmd := newRootCmd(tt.args) 529 cmd.SetOutput(ioutil.Discard) 530 cmd.SetArgs(tt.args) 531 cmd.Run = func(*cobra.Command, []string) {} 532 if err := cmd.Execute(); err != nil { 533 t.Errorf("unexpected error: %s", err) 534 } 535 536 if settings != tt.settings { 537 t.Errorf("expected settings %v, got %v", tt.settings, settings) 538 } 539 }) 540 } 541 } 542 543 func resetEnv() func() { 544 origSettings := settings 545 origEnv := os.Environ() 546 return func() { 547 settings = origSettings 548 for _, pair := range origEnv { 549 kv := strings.SplitN(pair, "=", 2) 550 os.Setenv(kv[0], kv[1]) 551 } 552 } 553 }