github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/util/configv3/config_test.go (about) 1 package configv3_test 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "time" 10 11 . "code.cloudfoundry.org/cli/util/configv3" 12 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/ginkgo/extensions/table" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("Config", func() { 19 var homeDir string 20 21 BeforeEach(func() { 22 homeDir = setup() 23 }) 24 25 AfterEach(func() { 26 teardown(homeDir) 27 }) 28 29 Context("when there isn't a config set", func() { 30 var ( 31 oldLang string 32 oldLCAll string 33 ) 34 35 BeforeEach(func() { 36 oldLang = os.Getenv("LANG") 37 oldLCAll = os.Getenv("LC_ALL") 38 os.Unsetenv("LANG") 39 os.Unsetenv("LC_ALL") 40 }) 41 42 It("returns a default config", func() { 43 defer os.Setenv("LANG", oldLang) 44 defer os.Setenv("LC_ALL", oldLCAll) 45 46 // specifically for when we run unit tests locally 47 // we save and unset this variable in case it's present 48 // since we want to load a default config 49 envVal := os.Getenv("CF_CLI_EXPERIMENTAL") 50 os.Unsetenv("CF_CLI_EXPERIMENTAL") 51 52 config, err := LoadConfig() 53 54 // then we reset the env variable 55 os.Setenv("CF_CLI_EXPERIMENTAL", envVal) 56 57 Expect(err).ToNot(HaveOccurred()) 58 59 Expect(config).ToNot(BeNil()) 60 Expect(config.Target()).To(Equal(DefaultTarget)) 61 Expect(config.SkipSSLValidation()).To(BeFalse()) 62 Expect(config.ColorEnabled()).To(Equal(ColorEnabled)) 63 Expect(config.PluginHome()).To(Equal(filepath.Join(homeDir, ".cf", "plugins"))) 64 Expect(config.StagingTimeout()).To(Equal(DefaultStagingTimeout)) 65 Expect(config.StartupTimeout()).To(Equal(DefaultStartupTimeout)) 66 Expect(config.Locale()).To(BeEmpty()) 67 Expect(config.UAAOAuthClient()).To(Equal(DefaultUAAOAuthClient)) 68 Expect(config.UAAOAuthClientSecret()).To(Equal(DefaultUAAOAuthClientSecret)) 69 Expect(config.OverallPollingTimeout()).To(Equal(DefaultOverallPollingTimeout)) 70 71 Expect(config.PluginRepos()).To(Equal([]PluginRepos{{ 72 Name: "CF-Community", 73 URL: "https://plugins.cloudfoundry.org", 74 }})) 75 Expect(config.Experimental()).To(BeFalse()) 76 77 pluginConfig := config.Plugins() 78 Expect(pluginConfig).To(BeEmpty()) 79 80 trace, location := config.Verbose() 81 Expect(trace).To(BeFalse()) 82 Expect(location).To(BeEmpty()) 83 }) 84 }) 85 86 Context("when there is a config set", func() { 87 var ( 88 config *Config 89 err error 90 ) 91 92 Context("when UAAOAuthClient is not present", func() { 93 BeforeEach(func() { 94 rawConfig := `{}` 95 setConfig(homeDir, rawConfig) 96 97 config, err = LoadConfig() 98 Expect(err).ToNot(HaveOccurred()) 99 }) 100 101 It("sets UAAOAuthClient to the default", func() { 102 Expect(config.UAAOAuthClient()).To(Equal(DefaultUAAOAuthClient)) 103 }) 104 105 It("sets UAAOAuthClientSecret to the default", func() { 106 Expect(config.UAAOAuthClientSecret()).To(Equal(DefaultUAAOAuthClientSecret)) 107 }) 108 }) 109 110 Context("when UAAOAuthClient is empty", func() { 111 BeforeEach(func() { 112 rawConfig := ` 113 { 114 "UAAOAuthClient": "" 115 }` 116 setConfig(homeDir, rawConfig) 117 118 config, err = LoadConfig() 119 Expect(err).ToNot(HaveOccurred()) 120 }) 121 122 It("sets UAAOAuthClient to the default", func() { 123 Expect(config.UAAOAuthClient()).To(Equal(DefaultUAAOAuthClient)) 124 }) 125 126 It("sets UAAOAuthClientSecret to the default", func() { 127 Expect(config.UAAOAuthClientSecret()).To(Equal(DefaultUAAOAuthClientSecret)) 128 }) 129 }) 130 }) 131 132 Describe("check functions", func() { 133 Describe("HasTargetedOrganization", func() { 134 Context("when an organization is targeted", func() { 135 It("returns true", func() { 136 config := Config{} 137 config.SetOrganizationInformation("guid-value-1", "my-org-name") 138 Expect(config.HasTargetedOrganization()).To(BeTrue()) 139 }) 140 }) 141 142 Context("when an organization is not targeted", func() { 143 It("returns false", func() { 144 config := Config{} 145 Expect(config.HasTargetedOrganization()).To(BeFalse()) 146 }) 147 }) 148 }) 149 150 Describe("HasTargetedSpace", func() { 151 Context("when an space is targeted", func() { 152 It("returns true", func() { 153 config := Config{} 154 config.SetSpaceInformation("guid-value-1", "my-org-name", true) 155 Expect(config.HasTargetedSpace()).To(BeTrue()) 156 }) 157 }) 158 159 Context("when an space is not targeted", func() { 160 It("returns false", func() { 161 config := Config{} 162 Expect(config.HasTargetedSpace()).To(BeFalse()) 163 }) 164 }) 165 }) 166 }) 167 168 Describe("getter functions", func() { 169 Describe("Target", func() { 170 var config *Config 171 172 BeforeEach(func() { 173 rawConfig := `{ "Target":"https://api.foo.com" }` 174 setConfig(homeDir, rawConfig) 175 176 var err error 177 config, err = LoadConfig() 178 Expect(err).ToNot(HaveOccurred()) 179 Expect(config).ToNot(BeNil()) 180 }) 181 182 It("returns fields directly from config", func() { 183 Expect(config.Target()).To(Equal("https://api.foo.com")) 184 }) 185 }) 186 187 Describe("OverallPollingTimeout", func() { 188 var config *Config 189 190 Context("when AsyncTimeout is set in config", func() { 191 BeforeEach(func() { 192 rawConfig := `{ "AsyncTimeout":5 }` 193 setConfig(homeDir, rawConfig) 194 195 var err error 196 config, err = LoadConfig() 197 Expect(err).ToNot(HaveOccurred()) 198 Expect(config).ToNot(BeNil()) 199 }) 200 201 It("returns the timeout in duration form", func() { 202 Expect(config.OverallPollingTimeout()).To(Equal(5 * time.Minute)) 203 }) 204 }) 205 }) 206 207 Describe("SkipSSLValidation", func() { 208 var config *Config 209 210 BeforeEach(func() { 211 rawConfig := `{ "SSLDisabled":true }` 212 setConfig(homeDir, rawConfig) 213 214 var err error 215 config, err = LoadConfig() 216 Expect(err).ToNot(HaveOccurred()) 217 Expect(config).ToNot(BeNil()) 218 }) 219 220 It("returns fields directly from config", func() { 221 Expect(config.SkipSSLValidation()).To(BeTrue()) 222 }) 223 }) 224 225 Describe("AccessToken", func() { 226 var config *Config 227 228 BeforeEach(func() { 229 rawConfig := `{ "AccessToken":"some-token" }` 230 setConfig(homeDir, rawConfig) 231 232 var err error 233 config, err = LoadConfig() 234 Expect(err).ToNot(HaveOccurred()) 235 Expect(config).ToNot(BeNil()) 236 }) 237 238 It("returns fields directly from config", func() { 239 Expect(config.AccessToken()).To(Equal("some-token")) 240 }) 241 }) 242 243 Describe("RefreshToken", func() { 244 var config *Config 245 246 BeforeEach(func() { 247 rawConfig := `{ "RefreshToken":"some-token" }` 248 setConfig(homeDir, rawConfig) 249 250 var err error 251 config, err = LoadConfig() 252 Expect(err).ToNot(HaveOccurred()) 253 Expect(config).ToNot(BeNil()) 254 }) 255 256 It("returns fields directly from config", func() { 257 Expect(config.RefreshToken()).To(Equal("some-token")) 258 }) 259 }) 260 261 Describe("UAAOAuthClient", func() { 262 var config *Config 263 264 BeforeEach(func() { 265 rawConfig := `{ "UAAOAuthClient":"some-client" }` 266 setConfig(homeDir, rawConfig) 267 268 var err error 269 config, err = LoadConfig() 270 Expect(err).ToNot(HaveOccurred()) 271 Expect(config).ToNot(BeNil()) 272 }) 273 274 It("returns the client ID", func() { 275 Expect(config.UAAOAuthClient()).To(Equal("some-client")) 276 }) 277 }) 278 279 Describe("UAAOAuthClientSecret", func() { 280 var config *Config 281 282 BeforeEach(func() { 283 rawConfig := ` 284 { 285 "UAAOAuthClient": "some-client-id", 286 "UAAOAuthClientSecret": "some-client-secret" 287 }` 288 setConfig(homeDir, rawConfig) 289 290 var err error 291 config, err = LoadConfig() 292 Expect(err).ToNot(HaveOccurred()) 293 Expect(config).ToNot(BeNil()) 294 }) 295 296 It("returns the client secret", func() { 297 Expect(config.UAAOAuthClientSecret()).To(Equal("some-client-secret")) 298 }) 299 }) 300 301 DescribeTable("Experimental", 302 func(envVal string, expected bool) { 303 rawConfig := fmt.Sprintf(`{}`) 304 setConfig(homeDir, rawConfig) 305 306 defer os.Unsetenv("CF_CLI_EXPERIMENTAL") 307 if envVal == "" { 308 os.Unsetenv("CF_CLI_EXPERIMENTAL") 309 } else { 310 os.Setenv("CF_CLI_EXPERIMENTAL", envVal) 311 } 312 313 config, err := LoadConfig() 314 Expect(err).ToNot(HaveOccurred()) 315 Expect(config).ToNot(BeNil()) 316 317 Expect(config.Experimental()).To(Equal(expected)) 318 }, 319 320 Entry("uses default value of false if environment value is not set", "", false), 321 Entry("uses environment value if a valid environment value is set", "true", true), 322 Entry("uses default value of false if an invalid environment value is set", "something-invalid", false), 323 ) 324 325 Describe("BinaryName", func() { 326 It("returns the name used to invoke", func() { 327 config, err := LoadConfig() 328 Expect(err).ToNot(HaveOccurred()) 329 Expect(config).ToNot(BeNil()) 330 331 // Ginkgo will uses a config file as the first test argument, so that 332 // will be considered the binary name 333 Expect(config.BinaryName()).To(Equal("configv3.test")) 334 }) 335 }) 336 337 Context("when there are environment variables", func() { 338 var ( 339 originalCFStagingTimeout string 340 originalCFStartupTimeout string 341 originalHTTPSProxy string 342 343 config *Config 344 ) 345 346 BeforeEach(func() { 347 originalCFStagingTimeout = os.Getenv("CF_STAGING_TIMEOUT") 348 originalCFStartupTimeout = os.Getenv("CF_STARTUP_TIMEOUT") 349 originalHTTPSProxy = os.Getenv("https_proxy") 350 os.Setenv("CF_STAGING_TIMEOUT", "8675") 351 os.Setenv("CF_STARTUP_TIMEOUT", "309") 352 os.Setenv("https_proxy", "proxy.com") 353 354 var err error 355 config, err = LoadConfig() 356 Expect(err).ToNot(HaveOccurred()) 357 Expect(config).ToNot(BeNil()) 358 }) 359 360 AfterEach(func() { 361 os.Setenv("CF_STAGING_TIMEOUT", originalCFStagingTimeout) 362 os.Setenv("CF_STARTUP_TIMEOUT", originalCFStartupTimeout) 363 os.Setenv("https_proxy", originalHTTPSProxy) 364 }) 365 366 It("overrides specific config values", func() { 367 Expect(config.StagingTimeout()).To(Equal(time.Duration(8675) * time.Minute)) 368 Expect(config.StartupTimeout()).To(Equal(time.Duration(309) * time.Minute)) 369 Expect(config.HTTPSProxy()).To(Equal("proxy.com")) 370 }) 371 }) 372 373 Describe("APIVersion", func() { 374 It("returns the api version", func() { 375 config := Config{ 376 ConfigFile: CFConfig{ 377 APIVersion: "2.59.0", 378 }, 379 } 380 381 Expect(config.APIVersion()).To(Equal("2.59.0")) 382 }) 383 }) 384 385 Describe("MinCLIVersion", func() { 386 It("returns the minimum CLI version the CC requires", func() { 387 config := Config{ 388 ConfigFile: CFConfig{ 389 MinCLIVersion: "1.0.0", 390 }, 391 } 392 393 Expect(config.MinCLIVersion()).To(Equal("1.0.0")) 394 }) 395 }) 396 397 Describe("TargetedOrganization", func() { 398 It("returns the organization", func() { 399 organization := Organization{ 400 GUID: "some-guid", 401 Name: "some-org", 402 } 403 config := Config{ 404 ConfigFile: CFConfig{ 405 TargetedOrganization: organization, 406 }, 407 } 408 409 Expect(config.TargetedOrganization()).To(Equal(organization)) 410 }) 411 }) 412 413 Describe("TargetedSpace", func() { 414 It("returns the space", func() { 415 space := Space{ 416 GUID: "some-guid", 417 Name: "some-space", 418 } 419 config := Config{ 420 ConfigFile: CFConfig{ 421 TargetedSpace: space, 422 }, 423 } 424 425 Expect(config.TargetedSpace()).To(Equal(space)) 426 }) 427 }) 428 429 DescribeTable("Verbose", 430 func(env string, configTrace string, flag bool, expected bool, location []string) { 431 rawConfig := fmt.Sprintf(`{ "Trace":"%s" }`, configTrace) 432 setConfig(homeDir, rawConfig) 433 434 defer os.Unsetenv("CF_TRACE") 435 if env == "" { 436 os.Unsetenv("CF_TRACE") 437 } else { 438 os.Setenv("CF_TRACE", env) 439 } 440 441 config, err := LoadConfig(FlagOverride{ 442 Verbose: flag, 443 }) 444 Expect(err).ToNot(HaveOccurred()) 445 Expect(config).ToNot(BeNil()) 446 447 verbose, parsedLocation := config.Verbose() 448 Expect(verbose).To(Equal(expected)) 449 Expect(parsedLocation).To(Equal(location)) 450 }, 451 452 Entry("CF_TRACE true: enables verbose", "true", "", false, true, nil), 453 Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false, true, nil), 454 Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo/bar", false, true, []string{"/foo/bar"}), 455 456 Entry("CF_TRACE false: disables verbose", "false", "", false, false, nil), 457 Entry("CF_TRACE false, '-v': enables verbose", "false", "", true, true, nil), 458 Entry("CF_TRACE false, config trace true: disables verbose", "false", "true", false, false, nil), 459 Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo/bar", false, false, []string{"/foo/bar"}), 460 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo/bar", true, true, []string{"/foo/bar"}), 461 462 Entry("CF_TRACE empty: disables verbose", "", "", false, false, nil), 463 Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true, true, nil), 464 Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false, true, nil), 465 Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo/bar", false, false, []string{"/foo/bar"}), 466 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo/bar", true, true, []string{"/foo/bar"}), 467 468 Entry("CF_TRACE filepath: enables logging to file", "/foo/bar", "", false, false, []string{"/foo/bar"}), 469 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo/bar", "", true, true, []string{"/foo/bar"}), 470 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo/bar", "true", false, true, []string{"/foo/bar"}), 471 Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo/bar", "/baz", false, false, []string{"/foo/bar", "/baz"}), 472 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo/bar", "/baz", true, true, []string{"/foo/bar", "/baz"}), 473 ) 474 475 Describe("DialTimeout", func() { 476 var ( 477 originalDialTimeout string 478 479 config *Config 480 ) 481 482 BeforeEach(func() { 483 originalDialTimeout = os.Getenv("CF_DIAL_TIMEOUT") 484 os.Setenv("CF_DIAL_TIMEOUT", "1234") 485 486 var err error 487 config, err = LoadConfig() 488 Expect(err).ToNot(HaveOccurred()) 489 Expect(config).ToNot(BeNil()) 490 }) 491 492 AfterEach(func() { 493 os.Setenv("CF_DIAL_TIMEOUT", originalDialTimeout) 494 }) 495 496 It("returns the dial timeout", func() { 497 Expect(config.DialTimeout()).To(Equal(1234 * time.Second)) 498 }) 499 }) 500 501 Describe("BinaryVersion", func() { 502 It("returns back version.BinaryVersion", func() { 503 conf := Config{} 504 Expect(conf.BinaryVersion()).To(Equal("0.0.0-unknown-version")) 505 }) 506 }) 507 }) 508 509 Describe("Write Config", func() { 510 var config *Config 511 BeforeEach(func() { 512 config = &Config{ 513 ConfigFile: CFConfig{ 514 ConfigVersion: 3, 515 Target: "foo.com", 516 ColorEnabled: "true", 517 }, 518 ENV: EnvOverride{ 519 CFColor: "false", 520 }, 521 } 522 }) 523 524 It("writes ConfigFile to homeDir/.cf/config.json", func() { 525 err := WriteConfig(config) 526 Expect(err).ToNot(HaveOccurred()) 527 528 file, err := ioutil.ReadFile(filepath.Join(homeDir, ".cf", "config.json")) 529 Expect(err).ToNot(HaveOccurred()) 530 531 var writtenCFConfig CFConfig 532 err = json.Unmarshal(file, &writtenCFConfig) 533 Expect(err).ToNot(HaveOccurred()) 534 535 Expect(writtenCFConfig.ConfigVersion).To(Equal(config.ConfigFile.ConfigVersion)) 536 Expect(writtenCFConfig.Target).To(Equal(config.ConfigFile.Target)) 537 Expect(writtenCFConfig.ColorEnabled).To(Equal(config.ConfigFile.ColorEnabled)) 538 }) 539 }) 540 541 Describe("setter functions", func() { 542 Describe("SetTargetInformation", func() { 543 It("sets the api target and other related endpoints", func() { 544 config := Config{ 545 ConfigFile: CFConfig{ 546 TargetedOrganization: Organization{ 547 GUID: "this-is-a-guid", 548 Name: "jo bobo jim boo", 549 }, 550 TargetedSpace: Space{ 551 GUID: "this-is-a-guid", 552 Name: "jo bobo jim boo", 553 AllowSSH: true, 554 }, 555 }, 556 } 557 config.SetTargetInformation( 558 "https://api.foo.com", 559 "2.59.31", 560 "https://login.foo.com", 561 "2.0.0", 562 "wws://doppler.foo.com:443", 563 "https://uaa.foo.com", 564 "https://api.foo.com/routing", 565 true, 566 ) 567 568 Expect(config.ConfigFile.Target).To(Equal("https://api.foo.com")) 569 Expect(config.ConfigFile.APIVersion).To(Equal("2.59.31")) 570 Expect(config.ConfigFile.AuthorizationEndpoint).To(Equal("https://login.foo.com")) 571 Expect(config.ConfigFile.MinCLIVersion).To(Equal("2.0.0")) 572 Expect(config.ConfigFile.DopplerEndpoint).To(Equal("wws://doppler.foo.com:443")) 573 Expect(config.ConfigFile.UAAEndpoint).To(Equal("https://uaa.foo.com")) 574 Expect(config.ConfigFile.RoutingEndpoint).To(Equal("https://api.foo.com/routing")) 575 Expect(config.ConfigFile.SkipSSLValidation).To(BeTrue()) 576 577 Expect(config.ConfigFile.TargetedOrganization.GUID).To(BeEmpty()) 578 Expect(config.ConfigFile.TargetedOrganization.Name).To(BeEmpty()) 579 Expect(config.ConfigFile.TargetedSpace.GUID).To(BeEmpty()) 580 Expect(config.ConfigFile.TargetedSpace.Name).To(BeEmpty()) 581 Expect(config.ConfigFile.TargetedSpace.AllowSSH).To(BeFalse()) 582 }) 583 }) 584 585 Describe("SetTokenInformation", func() { 586 It("sets the authentication token information", func() { 587 var config Config 588 config.SetTokenInformation("I am the access token", "I am the refresh token", "I am the SSH OAuth client") 589 590 Expect(config.ConfigFile.AccessToken).To(Equal("I am the access token")) 591 Expect(config.ConfigFile.RefreshToken).To(Equal("I am the refresh token")) 592 Expect(config.ConfigFile.SSHOAuthClient).To(Equal("I am the SSH OAuth client")) 593 }) 594 }) 595 596 Describe("SetAccessToken", func() { 597 It("sets the authentication token information", func() { 598 var config Config 599 config.SetAccessToken("I am the access token") 600 Expect(config.ConfigFile.AccessToken).To(Equal("I am the access token")) 601 }) 602 }) 603 604 Describe("SetRefreshToken", func() { 605 It("sets the refresh token information", func() { 606 var config Config 607 config.SetRefreshToken("I am the refresh token") 608 Expect(config.ConfigFile.RefreshToken).To(Equal("I am the refresh token")) 609 }) 610 }) 611 612 Describe("SetOrganizationInformation", func() { 613 It("sets the organization GUID and name", func() { 614 config := Config{} 615 config.SetOrganizationInformation("guid-value-1", "my-org-name") 616 617 Expect(config.ConfigFile.TargetedOrganization.GUID).To(Equal("guid-value-1")) 618 Expect(config.ConfigFile.TargetedOrganization.Name).To(Equal("my-org-name")) 619 }) 620 }) 621 622 Describe("SetSpaceInformation", func() { 623 It("sets the space GUID, name, and AllowSSH", func() { 624 config := Config{} 625 config.SetSpaceInformation("guid-value-1", "my-org-name", true) 626 627 Expect(config.ConfigFile.TargetedSpace.GUID).To(Equal("guid-value-1")) 628 Expect(config.ConfigFile.TargetedSpace.Name).To(Equal("my-org-name")) 629 Expect(config.ConfigFile.TargetedSpace.AllowSSH).To(BeTrue()) 630 }) 631 }) 632 633 Describe("UnsetOrganizationInformation", func() { 634 config := Config{} 635 BeforeEach(func() { 636 config.SetOrganizationInformation("some-org-guid", "some-org") 637 }) 638 639 It("resets the org GUID and name", func() { 640 config.UnsetOrganizationInformation() 641 642 Expect(config.ConfigFile.TargetedOrganization.GUID).To(Equal("")) 643 Expect(config.ConfigFile.TargetedOrganization.Name).To(Equal("")) 644 }) 645 }) 646 647 Describe("UnsetSpaceInformation", func() { 648 config := Config{} 649 BeforeEach(func() { 650 config.SetSpaceInformation("guid-value-1", "my-org-name", true) 651 }) 652 653 It("resets the space GUID, name, and AllowSSH to default values", func() { 654 config.UnsetSpaceInformation() 655 656 Expect(config.ConfigFile.TargetedSpace.GUID).To(Equal("")) 657 Expect(config.ConfigFile.TargetedSpace.Name).To(Equal("")) 658 Expect(config.ConfigFile.TargetedSpace.AllowSSH).To(BeFalse()) 659 }) 660 }) 661 }) 662 })