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