github.com/sleungcy-sap/cli@v7.1.0+incompatible/integration/v7/isolated/verbose_flag_test.go (about) 1 package isolated 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "runtime" 8 "strings" 9 10 "code.cloudfoundry.org/cli/integration/helpers" 11 "code.cloudfoundry.org/cli/util/configv3" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/ginkgo/extensions/table" 14 . "github.com/onsi/gomega" 15 . "github.com/onsi/gomega/gbytes" 16 . "github.com/onsi/gomega/gexec" 17 ) 18 19 var _ = Describe("Verbose", func() { 20 BeforeEach(func() { 21 helpers.SkipIfClientCredentialsTestMode() 22 }) 23 24 DescribeTable("displays verbose output to terminal", 25 func(env string, configTrace string, flag bool) { 26 tmpDir, err := ioutil.TempDir("", "") 27 defer os.RemoveAll(tmpDir) 28 Expect(err).NotTo(HaveOccurred()) 29 30 helpers.SetupCF(ReadOnlyOrg, ReadOnlySpace) 31 32 // Invalidate the access token to cause a token refresh in order to 33 // test the call to the UAA. 34 helpers.SetConfig(func(config *configv3.Config) { 35 config.ConfigFile.AccessToken = helpers.ExpiredAccessToken() 36 }) 37 38 var envMap map[string]string 39 if env != "" { 40 if string(env[0]) == "/" { 41 env = filepath.Join(tmpDir, env) 42 } 43 envMap = map[string]string{"CF_TRACE": env} 44 } 45 46 command := []string{"run-task", "app", "--command", "echo"} 47 48 if flag { 49 command = append(command, "-v") 50 } 51 52 if configTrace != "" { 53 if string(configTrace[0]) == "/" { 54 configTrace = filepath.Join(tmpDir, configTrace) 55 } 56 session := helpers.CF("config", "--trace", configTrace) 57 Eventually(session).Should(Exit(0)) 58 } 59 60 session := helpers.CFWithEnv(envMap, command...) 61 62 Eventually(session).Should(Say("REQUEST:")) 63 Eventually(session).Should(Say("POST /oauth/token")) 64 Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS)) 65 Eventually(session).Should(Say(`\[PRIVATE DATA HIDDEN\]`)) //This is required to test the previous line. If it fails, the previous matcher went too far. 66 Eventually(session).Should(Say("RESPONSE:")) 67 Eventually(session).Should(Say("REQUEST:")) 68 Eventually(session).Should(Say("GET /v3/apps")) 69 Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS)) 70 Eventually(session).Should(Say("RESPONSE:")) 71 Eventually(session).Should(Exit(1)) 72 }, 73 74 Entry("CF_TRACE true: enables verbose", "true", "", false), 75 Entry("CF_TRACE true, config trace false: enables verbose", "true", "false", false), 76 Entry("CF_TRACE true, config trace file path: enables verbose AND logging to file", "true", "/foo", false), 77 78 Entry("CF_TRACE false, '-v': enables verbose", "false", "", true), 79 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true), 80 81 Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true), 82 Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false), 83 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true), 84 85 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true), 86 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false), 87 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true), 88 ) 89 90 DescribeTable("displays verbose output to multiple files", 91 func(env string, configTrace string, flag bool, location []string) { 92 tmpDir, err := ioutil.TempDir("", "") 93 defer os.RemoveAll(tmpDir) 94 Expect(err).NotTo(HaveOccurred()) 95 96 helpers.SetupCF(ReadOnlyOrg, ReadOnlySpace) 97 98 // Invalidate the access token to cause a token refresh in order to 99 // test the call to the UAA. 100 helpers.SetConfig(func(config *configv3.Config) { 101 config.ConfigFile.AccessToken = helpers.ExpiredAccessToken() 102 }) 103 104 var envMap map[string]string 105 if env != "" { 106 if string(env[0]) == "/" { 107 env = filepath.Join(tmpDir, env) 108 } 109 envMap = map[string]string{"CF_TRACE": env} 110 } 111 112 command := []string{"run-task", "app", "--command", "echo"} 113 114 if flag { 115 command = append(command, "-v") 116 } 117 118 if configTrace != "" { 119 if string(configTrace[0]) == "/" { 120 configTrace = filepath.Join(tmpDir, configTrace) 121 } 122 session := helpers.CF("config", "--trace", configTrace) 123 Eventually(session).Should(Exit(0)) 124 } 125 126 session := helpers.CFWithEnv(envMap, command...) 127 Eventually(session).Should(Exit(1)) 128 129 for _, filePath := range location { 130 contents, err := ioutil.ReadFile(tmpDir + filePath) 131 Expect(err).ToNot(HaveOccurred()) 132 133 Expect(string(contents)).To(MatchRegexp("REQUEST:")) 134 Expect(string(contents)).To(MatchRegexp("RESPONSE:")) 135 Expect(string(contents)).NotTo(MatchRegexp("HTTP REQUEST:")) 136 Expect(string(contents)).NotTo(MatchRegexp("HTTP RESPONSE:")) 137 Expect(string(contents)).To(MatchRegexp("GET /v3/apps")) 138 Expect(string(contents)).To(MatchRegexp("POST /oauth/token")) 139 140 stat, err := os.Stat(tmpDir + filePath) 141 Expect(err).ToNot(HaveOccurred()) 142 143 if runtime.GOOS == "windows" { 144 Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String())) 145 } else { 146 Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String())) 147 } 148 } 149 }, 150 151 Entry("CF_TRACE true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}), 152 153 Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}), 154 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}), 155 156 Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}), 157 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}), 158 159 Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}), 160 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}), 161 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}), 162 Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}), 163 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}), 164 ) 165 166 Describe("Log cache", func() { 167 var orgName string 168 169 BeforeEach(func() { 170 orgName = helpers.NewOrgName() 171 spaceName := helpers.NewSpaceName() 172 173 helpers.SetupCF(orgName, spaceName) 174 }) 175 176 AfterEach(func() { 177 Eventually(helpers.CF("config", "--trace", "false")).Should(Exit(0)) 178 helpers.QuickDeleteOrg(orgName) 179 }) 180 181 DescribeTable("displays verbose output to terminal", 182 func(env string, configTrace string, flag bool) { 183 tmpDir, err := ioutil.TempDir("", "") 184 defer os.RemoveAll(tmpDir) 185 Expect(err).NotTo(HaveOccurred()) 186 187 appName := helpers.PrefixedRandomName("app") 188 189 helpers.WithHelloWorldApp(func(appDir string) { 190 Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 191 }) 192 193 var envMap map[string]string 194 if env != "" { 195 if string(env[0]) == "/" { 196 env = filepath.Join(tmpDir, env) 197 } 198 envMap = map[string]string{"CF_TRACE": env} 199 } 200 201 command := []string{"logs", appName} 202 203 if flag { 204 command = append(command, "-v") 205 } 206 207 if configTrace != "" { 208 if string(configTrace[0]) == "/" { 209 configTrace = filepath.Join(tmpDir, configTrace) 210 } 211 session := helpers.CF("config", "--trace", configTrace) 212 Eventually(session).Should(Exit(0)) 213 } 214 215 session := helpers.CFWithEnv(envMap, command...) 216 217 Eventually(session).Should(Say("REQUEST:")) 218 Eventually(session).Should(Say(`GET /\s+`)) 219 Eventually(session).Should(Say(`GET /api/v1/read/.*\?\w+`)) 220 Eventually(session).Should(Say(`Host: log-cache\.`)) 221 Eventually(session).Should(Say(`Authorization: \[PRIVATE DATA HIDDEN\]`)) 222 Eventually(session.Kill()).Should(Exit()) 223 }, 224 225 Entry("CF_TRACE true: enables verbose", "true", "", false), 226 Entry("CF_TRACE true, config trace false: enables verbose", "true", "false", false), 227 Entry("CF_TRACE true, config trace file path: enables verbose AND logging to file", "true", "/foo", false), 228 229 Entry("CF_TRACE false, '-v': enables verbose", "false", "", true), 230 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true), 231 232 Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true), 233 Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false), 234 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true), 235 236 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true), 237 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false), 238 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true), 239 ) 240 241 DescribeTable("displays verbose output to multiple files", 242 func(env string, configTrace string, location []string) { 243 tmpDir, err := ioutil.TempDir("", "") 244 defer os.RemoveAll(tmpDir) 245 Expect(err).NotTo(HaveOccurred()) 246 247 appName := helpers.PrefixedRandomName("app") 248 249 helpers.WithHelloWorldApp(func(appDir string) { 250 Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 251 }) 252 253 var envMap map[string]string 254 if env != "" { 255 if string(env[0]) == "/" { 256 env = filepath.Join(tmpDir, env) 257 } 258 envMap = map[string]string{"CF_TRACE": env} 259 } 260 261 if configTrace != "" { 262 if strings.HasPrefix(configTrace, "/") { 263 configTrace = filepath.Join(tmpDir, configTrace) 264 } 265 session := helpers.CF("config", "--trace", configTrace) 266 Eventually(session).Should(Exit(0)) 267 } 268 269 session := helpers.CFWithEnv(envMap, "logs", "-v", appName) 270 Eventually(session).Should(Say("RESPONSE:")) 271 Eventually(session).Should(Say("GET /api/v1/info HTTP/1.1")) 272 Eventually(session).Should(Say("GET /api/v1/read/")) 273 session.Kill() 274 Eventually(session).Should(Exit()) 275 276 for _, filePath := range location { 277 contents, err := ioutil.ReadFile(tmpDir + filePath) 278 Expect(err).ToNot(HaveOccurred()) 279 Expect(string(contents)).To(MatchRegexp("REQUEST:")) 280 Expect(string(contents)).To(MatchRegexp("RESPONSE:")) 281 Expect(string(contents)).NotTo(MatchRegexp("HTTP REQUEST:")) 282 Expect(string(contents)).NotTo(MatchRegexp("HTTP RESPONSE:")) 283 Expect(string(contents)).To(MatchRegexp(`GET /\s+`)) 284 Expect(string(contents)).To(MatchRegexp(`Host: log-cache\.`)) 285 Expect(string(contents)).To(MatchRegexp(`Authorization: \[PRIVATE DATA HIDDEN\]`)) 286 287 stat, err := os.Stat(tmpDir + filePath) 288 Expect(err).ToNot(HaveOccurred()) 289 290 if runtime.GOOS == "windows" { 291 Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String())) 292 } else { 293 Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String())) 294 } 295 } 296 }, 297 298 Entry("CF_TRACE true, config trace file path: enables verbose AND logging to file", "true", "/foo", []string{"/foo"}), 299 300 Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", []string{"/foo"}), 301 Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", []string{"/foo"}), 302 303 Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", []string{"/foo"}), 304 Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", []string{"/foo"}), 305 306 Entry("CF_TRACE filepath: enables logging to file", "/foo", "", []string{"/foo"}), 307 Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", []string{"/foo"}), 308 Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", []string{"/foo"}), 309 Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", []string{"/foo", "/bar"}), 310 Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", []string{"/foo", "/bar"}), 311 ) 312 }) 313 314 Describe("uaa", func() { 315 When("the user does not provide the -v flag, the CF_TRACE env var, or the --trace config option", func() { 316 It("should not log requests", func() { 317 tmpDir, err := ioutil.TempDir("", "") 318 defer os.RemoveAll(tmpDir) 319 Expect(err).NotTo(HaveOccurred()) 320 321 helpers.LoginCF() 322 323 username, password := helpers.GetCredentials() 324 command := []string{"auth", username, password} 325 326 session := helpers.CF(command...) 327 328 Eventually(session).Should(Exit(0)) 329 Expect(session).To(Say(`Authenticating...`)) 330 Expect(session).ToNot(Say(`POST /oauth/token`)) 331 }) 332 }) 333 334 When("the user provides the -v flag", func() { 335 It("should log requests and redact cookies", func() { 336 tmpDir, err := ioutil.TempDir("", "") 337 defer os.RemoveAll(tmpDir) 338 Expect(err).NotTo(HaveOccurred()) 339 340 helpers.LoginCF() 341 342 command := []string{"target", "-o", ReadOnlyOrg, "-v"} 343 344 session := helpers.CF(command...) 345 Eventually(session).Should(Exit(0)) 346 Expect(session).To(Say(`Set-Cookie: \[PRIVATE DATA HIDDEN\]`)) 347 }) 348 }) 349 }) 350 351 Describe("ssh", func() { 352 When("the user is not in verbose mode", func() { 353 It("should not log requests", func() { 354 tmpDir, err := ioutil.TempDir("", "") 355 defer os.RemoveAll(tmpDir) 356 Expect(err).NotTo(HaveOccurred()) 357 358 helpers.LoginCF() 359 360 command := []string{"ssh-code"} 361 362 session := helpers.CF(command...) 363 364 Eventually(session).Should(Exit(0)) 365 Expect(session).ToNot(Say(`GET`)) 366 }) 367 }) 368 369 When("the user is in verbose mode", func() { 370 It("should redact their one time ssh code", func() { 371 tmpDir, err := ioutil.TempDir("", "") 372 defer os.RemoveAll(tmpDir) 373 Expect(err).NotTo(HaveOccurred()) 374 375 helpers.LoginCF() 376 377 command := []string{"ssh-code", "-v"} 378 379 session := helpers.CF(command...) 380 381 Eventually(session).Should(Exit(0)) 382 Expect(session.Out.Contents()).ToNot(MatchRegexp(`[?&]code=[^\[].*$`)) 383 Expect(session.Out.Contents()).To(ContainSubstring("/login?code=[PRIVATE DATA HIDDEN]")) 384 }) 385 }) 386 }) 387 })