github.com/cloudfoundry-community/cloudfoundry-cli@v6.44.1-0.20240130060226-cda5ed8e89a5+incompatible/integration/v6/isolated/verbose_flag_test.go (about) 1 package isolated 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strconv" 9 "strings" 10 11 "code.cloudfoundry.org/cli/integration/helpers" 12 "code.cloudfoundry.org/cli/util/configv3" 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/ginkgo/extensions/table" 15 . "github.com/onsi/gomega" 16 . "github.com/onsi/gomega/gbytes" 17 . "github.com/onsi/gomega/gexec" 18 ) 19 20 var _ = Describe("Verbose", func() { 21 Context("v2 legacy", func() { 22 DescribeTable("displays verbose output", 23 func(command func() *Session) { 24 helpers.LoginCF() 25 26 session := command() 27 Eventually(session).Should(Say("REQUEST:")) 28 Eventually(session).Should(Say("GET /v2/organizations")) 29 Eventually(session).Should(Say("RESPONSE:")) 30 Eventually(session).Should(Exit(0)) 31 }, 32 33 Entry("when the -v option is provided with additional command", func() *Session { 34 return helpers.CF("-v", "orgs") 35 }), 36 37 Entry("when the CF_TRACE env variable is set", func() *Session { 38 return helpers.CFWithEnv(map[string]string{"CF_TRACE": "true"}, "orgs") 39 }), 40 ) 41 }) 42 43 Context("v2 refactor", func() { 44 DescribeTable("displays verbose output to terminal", 45 func(env string, configTrace string, flag bool) { 46 tmpDir, err := ioutil.TempDir("", "") 47 defer os.RemoveAll(tmpDir) 48 Expect(err).NotTo(HaveOccurred()) 49 50 helpers.LoginCF() 51 helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace) 52 53 var envMap map[string]string 54 if env != "" { 55 if string(env[0]) == "/" { 56 env = filepath.Join(tmpDir, env) 57 } 58 envMap = map[string]string{"CF_TRACE": env} 59 } 60 61 // We use 'create-user' because it makes a request via the UAA client 62 // and a request via the CC client, testing the logging wrapper in both 63 // clients. 64 randomUsername := helpers.NewUsername() 65 randomPassword := helpers.NewPassword() 66 command := []string{"create-user", randomUsername, randomPassword} 67 68 if flag { 69 command = append(command, "-v") 70 } 71 72 if configTrace != "" { 73 if string(configTrace[0]) == "/" { 74 configTrace = filepath.Join(tmpDir, configTrace) 75 } 76 session := helpers.CF("config", "--trace", configTrace) 77 Eventually(session).Should(Exit(0)) 78 } 79 80 session := helpers.CFWithEnv(envMap, command...) 81 82 Eventually(session).Should(Say("REQUEST:")) 83 Eventually(session).Should(Say("GET /v2/info")) 84 Eventually(session).Should(Say("RESPONSE:")) 85 Eventually(session).Should(Say(`"token_endpoint": "http.*"`)) 86 Eventually(session).Should(Say("REQUEST:")) 87 Eventually(session).Should(Say("POST /Users")) 88 Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS)) 89 Eventually(session).Should(Say("RESPONSE:")) 90 Eventually(session).Should(Say("REQUEST:")) 91 Eventually(session).Should(Say("POST /v2/users")) 92 Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS)) 93 Eventually(session).Should(Say("RESPONSE:")) 94 Eventually(session).Should(Exit(0)) 95 }, 96 97 Entry("CF_TRACE true: enables verbose", "true", "", false), 98 Entry("CF_TRACE true, config trace false: enables verbose", "true", "false", false), 99 Entry("CF_TRACE true, config trace file path: enables verbose AND logging to file", "true", "/foo", false), 100 101 Entry("CF_TRACE false, '-v': enables verbose", "false", "", true), 102 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true), 103 104 Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true), 105 Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false), 106 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true), 107 108 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true), 109 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false), 110 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true), 111 ) 112 113 DescribeTable("displays verbose output to multiple files", 114 func(env string, configTrace string, flag bool, location []string) { 115 tmpDir, err := ioutil.TempDir("", "") 116 defer os.RemoveAll(tmpDir) 117 Expect(err).NotTo(HaveOccurred()) 118 119 helpers.LoginCF() 120 helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace) 121 122 var envMap map[string]string 123 if env != "" { 124 if string(env[0]) == "/" { 125 env = filepath.Join(tmpDir, env) 126 } 127 envMap = map[string]string{"CF_TRACE": env} 128 } 129 130 // We use 'create-user' because it makes a request via the UAA client 131 // and a request via the CC client, testing the logging wrapper in both 132 // clients. 133 randomUsername := helpers.NewUsername() 134 randomPassword := helpers.NewPassword() 135 command := []string{"create-user", randomUsername, randomPassword} 136 137 if flag { 138 command = append(command, "-v") 139 } 140 141 if configTrace != "" { 142 if string(configTrace[0]) == "/" { 143 configTrace = filepath.Join(tmpDir, configTrace) 144 } 145 session := helpers.CF("config", "--trace", configTrace) 146 Eventually(session).Should(Exit(0)) 147 } 148 149 session := helpers.CFWithEnv(envMap, command...) 150 Eventually(session).Should(Exit(0)) 151 152 for _, filePath := range location { 153 contents, err := ioutil.ReadFile(tmpDir + filePath) 154 Expect(err).ToNot(HaveOccurred()) 155 156 Expect(string(contents)).To(MatchRegexp("REQUEST:")) 157 Expect(string(contents)).To(MatchRegexp("POST /Users")) 158 Expect(string(contents)).To(MatchRegexp("RESPONSE:")) 159 Expect(string(contents)).To(MatchRegexp("REQUEST:")) 160 Expect(string(contents)).To(MatchRegexp("POST /v2/users")) 161 Expect(string(contents)).To(MatchRegexp("RESPONSE:")) 162 163 stat, err := os.Stat(tmpDir + filePath) 164 Expect(err).ToNot(HaveOccurred()) 165 166 if runtime.GOOS == "windows" { 167 Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String())) 168 } else { 169 Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String())) 170 } 171 } 172 }, 173 174 Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}), 175 176 Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}), 177 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}), 178 179 Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}), 180 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}), 181 182 Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}), 183 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}), 184 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}), 185 Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}), 186 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}), 187 ) 188 }) 189 190 Context("v3", func() { 191 DescribeTable("displays verbose output to terminal", 192 func(env string, configTrace string, flag bool) { 193 tmpDir, err := ioutil.TempDir("", "") 194 defer os.RemoveAll(tmpDir) 195 Expect(err).NotTo(HaveOccurred()) 196 197 helpers.SetupCF(ReadOnlyOrg, ReadOnlySpace) 198 199 // Invalidate the access token to cause a token refresh in order to 200 // test the call to the UAA. 201 helpers.SetConfig(func(config *configv3.Config) { 202 config.ConfigFile.AccessToken = helpers.ExpiredAccessToken() 203 }) 204 205 var envMap map[string]string 206 if env != "" { 207 if string(env[0]) == "/" { 208 env = filepath.Join(tmpDir, env) 209 } 210 envMap = map[string]string{"CF_TRACE": env} 211 } 212 213 command := []string{"run-task", "app", "echo"} 214 215 if flag { 216 command = append(command, "-v") 217 } 218 219 if configTrace != "" { 220 if string(configTrace[0]) == "/" { 221 configTrace = filepath.Join(tmpDir, configTrace) 222 } 223 session := helpers.CF("config", "--trace", configTrace) 224 Eventually(session).Should(Exit(0)) 225 } 226 227 session := helpers.CFWithEnv(envMap, command...) 228 // implicit access token refresh 229 Eventually(session).Should(Say("REQUEST:")) 230 Eventually(session).Should(Say("POST /oauth/token")) 231 Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS)) 232 Eventually(session).Should(Say(`\[PRIVATE DATA HIDDEN\]`)) //This is required to test the previous line. If it fails, the previous matcher went too far. 233 Eventually(session).Should(Say("RESPONSE:")) 234 // actual request 235 Eventually(session).Should(Say("REQUEST:")) 236 Eventually(session).Should(Say("GET /v3/apps")) 237 Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS)) 238 Eventually(session).Should(Say("RESPONSE:")) 239 240 Eventually(session).Should(Exit(1)) 241 }, 242 243 Entry("CF_TRACE true: enables verbose", "true", "", false), 244 Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false), 245 Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false), 246 247 Entry("CF_TRACE false, '-v': enables verbose", "false", "", true), 248 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true), 249 250 Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true), 251 Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false), 252 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true), 253 254 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true), 255 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false), 256 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true), 257 ) 258 259 DescribeTable("displays verbose output to multiple files", 260 func(env string, configTrace string, flag bool, location []string) { 261 tmpDir, err := ioutil.TempDir("", "") 262 defer os.RemoveAll(tmpDir) 263 Expect(err).NotTo(HaveOccurred()) 264 265 helpers.SetupCF(ReadOnlyOrg, ReadOnlySpace) 266 267 // Invalidate the access token to cause a token refresh in order to 268 // test the call to the UAA. 269 helpers.SetConfig(func(config *configv3.Config) { 270 config.ConfigFile.AccessToken = helpers.ExpiredAccessToken() 271 }) 272 273 var envMap map[string]string 274 if env != "" { 275 if string(env[0]) == "/" { 276 env = filepath.Join(tmpDir, env) 277 } 278 envMap = map[string]string{"CF_TRACE": env} 279 } 280 281 command := []string{"run-task", "app", "echo"} 282 283 if flag { 284 command = append(command, "-v") 285 } 286 287 if configTrace != "" { 288 if string(configTrace[0]) == "/" { 289 configTrace = filepath.Join(tmpDir, configTrace) 290 } 291 session := helpers.CF("config", "--trace", configTrace) 292 Eventually(session).Should(Exit(0)) 293 } 294 295 session := helpers.CFWithEnv(envMap, command...) 296 Eventually(session).Should(Exit(1)) 297 298 for _, filePath := range location { 299 contents, err := ioutil.ReadFile(tmpDir + filePath) 300 Expect(err).ToNot(HaveOccurred()) 301 302 Expect(string(contents)).To(MatchRegexp("REQUEST:")) 303 Expect(string(contents)).To(MatchRegexp("GET /v3/apps")) 304 Expect(string(contents)).To(MatchRegexp("RESPONSE:")) 305 Expect(string(contents)).To(MatchRegexp("REQUEST:")) 306 Expect(string(contents)).To(MatchRegexp("POST /oauth/token")) 307 Expect(string(contents)).To(MatchRegexp("RESPONSE:")) 308 309 stat, err := os.Stat(tmpDir + filePath) 310 Expect(err).ToNot(HaveOccurred()) 311 312 if runtime.GOOS == "windows" { 313 Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String())) 314 } else { 315 Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String())) 316 } 317 } 318 }, 319 320 Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}), 321 322 Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}), 323 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}), 324 325 Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}), 326 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}), 327 328 Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}), 329 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}), 330 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}), 331 Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}), 332 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}), 333 ) 334 }) 335 336 Describe("NOAA", func() { 337 var orgName string 338 339 BeforeEach(func() { 340 orgName = helpers.NewOrgName() 341 spaceName := helpers.NewSpaceName() 342 343 helpers.SetupCF(orgName, spaceName) 344 }) 345 346 AfterEach(func() { 347 Eventually(helpers.CF("config", "--trace", "false")).Should(Exit(0)) 348 helpers.QuickDeleteOrg(orgName) 349 }) 350 351 DescribeTable("displays verbose output to terminal", 352 func(env string, configTrace string, flag bool) { 353 tmpDir, err := ioutil.TempDir("", "") 354 defer os.RemoveAll(tmpDir) 355 Expect(err).NotTo(HaveOccurred()) 356 357 appName := helpers.PrefixedRandomName("app") 358 359 helpers.WithHelloWorldApp(func(appDir string) { 360 Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 361 }) 362 363 var envMap map[string]string 364 if env != "" { 365 if string(env[0]) == "/" { 366 env = filepath.Join(tmpDir, env) 367 } 368 envMap = map[string]string{"CF_TRACE": env} 369 } 370 371 command := []string{"logs", appName} 372 373 if flag { 374 command = append(command, "-v") 375 } 376 377 if configTrace != "" { 378 if string(configTrace[0]) == "/" { 379 configTrace = filepath.Join(tmpDir, configTrace) 380 } 381 session := helpers.CF("config", "--trace", configTrace) 382 Eventually(session).Should(Exit(0)) 383 } 384 385 session := helpers.CFWithEnv(envMap, command...) 386 387 Eventually(session).Should(Say("WEBSOCKET REQUEST:")) 388 Eventually(session).Should(Say(`Authorization: \[PRIVATE DATA HIDDEN\]`)) 389 Eventually(session.Kill()).Should(Exit()) 390 }, 391 392 Entry("CF_TRACE true: enables verbose", "true", "", false), 393 Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false), 394 Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false), 395 396 Entry("CF_TRACE false, '-v': enables verbose", "false", "", true), 397 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true), 398 399 Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true), 400 Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false), 401 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true), 402 403 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true), 404 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false), 405 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true), 406 ) 407 408 DescribeTable("displays verbose output to multiple files", 409 func(env string, configTrace string, location []string) { 410 tmpDir, err := ioutil.TempDir("", "") 411 defer os.RemoveAll(tmpDir) 412 Expect(err).NotTo(HaveOccurred()) 413 414 appName := helpers.PrefixedRandomName("app") 415 416 helpers.WithHelloWorldApp(func(appDir string) { 417 Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 418 }) 419 420 var envMap map[string]string 421 if env != "" { 422 if string(env[0]) == "/" { 423 env = filepath.Join(tmpDir, env) 424 } 425 envMap = map[string]string{"CF_TRACE": env} 426 } 427 428 if configTrace != "" { 429 if strings.HasPrefix(configTrace, "/") { 430 configTrace = filepath.Join(tmpDir, configTrace) 431 } 432 session := helpers.CF("config", "--trace", configTrace) 433 Eventually(session).Should(Exit(0)) 434 } 435 436 session := helpers.CFWithEnv(envMap, "logs", "-v", appName) 437 438 Eventually(session).Should(Say("WEBSOCKET RESPONSE")) 439 Eventually(session.Kill()).Should(Exit()) 440 441 for _, filePath := range location { 442 contents, err := ioutil.ReadFile(tmpDir + filePath) 443 Expect(err).ToNot(HaveOccurred()) 444 445 Expect(string(contents)).To(MatchRegexp("WEBSOCKET REQUEST:")) 446 Expect(string(contents)).To(MatchRegexp(`Authorization: \[PRIVATE DATA HIDDEN\]`)) 447 448 stat, err := os.Stat(tmpDir + filePath) 449 Expect(err).ToNot(HaveOccurred()) 450 451 if runtime.GOOS == "windows" { 452 Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String())) 453 } else { 454 Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String())) 455 } 456 } 457 }, 458 459 Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", []string{"/foo"}), 460 461 Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", []string{"/foo"}), 462 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", []string{"/foo"}), 463 464 Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", []string{"/foo"}), 465 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", []string{"/foo"}), 466 467 Entry("CF_TRACE filepath: enables logging to file", "/foo", "", []string{"/foo"}), 468 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", []string{"/foo"}), 469 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", []string{"/foo"}), 470 Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", []string{"/foo", "/bar"}), 471 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", []string{"/foo", "/bar"}), 472 ) 473 }) 474 475 Describe("routing", func() { 476 BeforeEach(func() { 477 helpers.SkipIfNoRoutingAPI() 478 }) 479 480 When("the user does not provide the -v flag, the CF_TRACE env var, or the --trace config option", func() { 481 It("should not log requests", func() { 482 tmpDir, err := ioutil.TempDir("", "") 483 defer os.RemoveAll(tmpDir) 484 Expect(err).NotTo(HaveOccurred()) 485 486 helpers.LoginCF() 487 helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace) 488 489 command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"} 490 491 session := helpers.CF(command...) 492 493 Consistently(session).ShouldNot(Say(`GET /routing/v1`)) 494 Eventually(session).Should(Exit(0)) 495 }) 496 }) 497 498 DescribeTable("verbose logging to stdout", 499 func(cfTraceEnvVar string, configTraceValue string, vFlagSet bool) { 500 tmpDir, err := ioutil.TempDir("", "") 501 defer os.RemoveAll(tmpDir) 502 Expect(err).NotTo(HaveOccurred()) 503 504 helpers.LoginCF() 505 helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace) 506 507 var envTraceFile string 508 if _, err := strconv.ParseBool(cfTraceEnvVar); err != nil && len(cfTraceEnvVar) > 0 { 509 cfTraceEnvVar = filepath.Join(tmpDir, cfTraceEnvVar) 510 envTraceFile = cfTraceEnvVar 511 } 512 envMap := map[string]string{"CF_TRACE": cfTraceEnvVar} 513 514 command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"} 515 516 if vFlagSet { 517 command = append(command, "-v") 518 } 519 520 var configTraceFile string 521 if configTraceValue != "" { 522 if _, err := strconv.ParseBool(configTraceValue); err != nil && len(configTraceValue) > 0 { 523 configTraceValue = filepath.Join(tmpDir, configTraceValue) 524 configTraceFile = configTraceValue 525 } 526 session := helpers.CF("config", "--trace", configTraceValue) 527 Eventually(session).Should(Exit(0)) 528 } 529 530 session := helpers.CFWithEnv(envMap, command...) 531 532 Eventually(session).Should(Say(`GET /routing/v1/router_groups\?name=default-tcp`)) 533 Eventually(session).Should(Exit(0)) 534 535 if len(envTraceFile) > 0 { 536 assertLogsWrittenToFile(envTraceFile, "GET /routing/v1/router_groups?name=default-tcp") 537 } 538 539 if len(configTraceFile) > 0 { 540 assertLogsWrittenToFile(configTraceFile, "GET /routing/v1/router_groups?name=default-tcp") 541 } 542 }, 543 544 Entry("CF_TRACE=true, enables verbose", "true", "", false), 545 Entry("CF_TRACE=true, config trace false: enables verbose", "true", "false", false), 546 Entry("CF_TRACE=true, config trace file path: enables verbose AND logging to file", "true", "/foo", false), 547 548 Entry("CF_TRACE=false, '-v': enables verbose", "false", "", true), 549 Entry("CF_TRACE=false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true), 550 551 Entry("CF_TRACE unset, '-v': enables verbose", "", "", true), 552 Entry("CF_TRACE unset, config trace true: enables verbose", "", "true", false), 553 Entry("CF_TRACE unset, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true), 554 555 Entry("CF_TRACE=filepath, '-v': enables logging to file", "/foo", "", true), 556 Entry("CF_TRACE=filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false), 557 ) 558 559 DescribeTable("verbose logging to a file", 560 func(cfTraceEnvVar string, configTraceValue string, vFlagSet bool) { 561 tmpDir, err := ioutil.TempDir("", "") 562 defer os.RemoveAll(tmpDir) 563 Expect(err).NotTo(HaveOccurred()) 564 565 helpers.LoginCF() 566 helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace) 567 568 var envMap map[string]string 569 570 var envTraceFile string 571 if cfTraceEnvVar != "" { 572 if _, err := strconv.ParseBool(cfTraceEnvVar); err != nil { 573 cfTraceEnvVar = filepath.Join(tmpDir, cfTraceEnvVar) 574 envTraceFile = cfTraceEnvVar 575 } 576 envMap = map[string]string{"CF_TRACE": cfTraceEnvVar} 577 } 578 579 var configTraceFile string 580 if configTraceValue != "" { 581 if _, err := strconv.ParseBool(configTraceValue); err != nil { 582 configTraceValue = filepath.Join(tmpDir, configTraceValue) 583 configTraceFile = configTraceValue 584 } 585 session := helpers.CF("config", "--trace", configTraceValue) 586 Eventually(session).Should(Exit(0)) 587 } 588 589 command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"} 590 591 if vFlagSet { 592 command = append(command, "-v") 593 } 594 595 session := helpers.CFWithEnv(envMap, command...) 596 Eventually(session).Should(Exit(0)) 597 598 if len(envTraceFile) > 0 { 599 assertLogsWrittenToFile(envTraceFile, "GET /routing/v1/router_groups?name=default-tcp") 600 } 601 602 if len(configTraceFile) > 0 { 603 assertLogsWrittenToFile(configTraceFile, "GET /routing/v1/router_groups?name=default-tcp") 604 } 605 }, 606 607 Entry("CF_TRACE=false, config trace file path: enables logging to file", "false", "/foo", false), 608 Entry("CF_TRACE unset, config trace file path: enables logging to file", "", "/foo", false), 609 Entry("CF_TRACE=filepath: enables logging to file", "/foo", "", false), 610 ) 611 612 When("the values of CF_TRACE and config.trace are two different filepaths", func() { 613 var ( 614 configTraceFile, envTraceFile string 615 cfEnv map[string]string 616 ) 617 618 BeforeEach(func() { 619 helpers.LoginCF() 620 helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace) 621 622 tmpDir, err := ioutil.TempDir("", "") 623 defer os.RemoveAll(tmpDir) 624 Expect(err).NotTo(HaveOccurred()) 625 626 configTraceFile = filepath.Join(tmpDir, "/foo") 627 session := helpers.CF("config", "--trace", configTraceFile) 628 Eventually(session).Should(Exit(0)) 629 630 envTraceFile = filepath.Join(tmpDir, "/bar") 631 cfEnv = map[string]string{ 632 "CF_TRACE": envTraceFile, 633 } 634 }) 635 636 It("logs verbose output to both files", func() { 637 command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"} 638 639 session := helpers.CFWithEnv(cfEnv, command...) 640 Eventually(session).Should(Exit(0)) 641 642 assertLogsWrittenToFile(envTraceFile, "GET /routing/v1/router_groups?name=default-tcp") 643 assertLogsWrittenToFile(configTraceFile, "GET /routing/v1/router_groups?name=default-tcp") 644 645 configStat, err := os.Stat(configTraceFile) 646 Expect(err).ToNot(HaveOccurred()) 647 648 envStat, err := os.Stat(envTraceFile) 649 Expect(err).ToNot(HaveOccurred()) 650 651 var fileMode os.FileMode 652 if runtime.GOOS == "windows" { 653 fileMode = os.FileMode(0666) 654 } else { 655 fileMode = os.FileMode(0600) 656 } 657 658 Expect(configStat.Mode().String()).To(Equal(fileMode.String())) 659 Expect(envStat.Mode().String()).To(Equal(fileMode.String())) 660 }) 661 }) 662 }) 663 }) 664 665 func assertLogsWrittenToFile(filepath string, expected string) { 666 contents, err := ioutil.ReadFile(filepath) 667 Expect(err).ToNot(HaveOccurred()) 668 Expect(string(contents)).To(ContainSubstring(expected), "Logging to a file failed") 669 }