github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/integration/shared/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.InvalidAccessToken()
   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  
   229  				Eventually(session).Should(Say("REQUEST:"))
   230  				Eventually(session).Should(Say("GET /v3/apps"))
   231  				Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS))
   232  				Eventually(session).Should(Say("RESPONSE:"))
   233  				Eventually(session).Should(Say("REQUEST:"))
   234  				Eventually(session).Should(Say("POST /oauth/token"))
   235  				Eventually(session).Should(Say(`User-Agent: cf/[\w.+-]+ \(go\d+\.\d+(\.\d+)?; %s %s\)`, runtime.GOARCH, runtime.GOOS))
   236  				Eventually(session).Should(Say(`\[PRIVATE DATA HIDDEN\]`)) //This is required to test the previous line. If it fails, the previous matcher went too far.
   237  				Eventually(session).Should(Say("RESPONSE:"))
   238  				Eventually(session).Should(Exit(1))
   239  			},
   240  
   241  			Entry("CF_TRACE true: enables verbose", "true", "", false),
   242  			Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false),
   243  			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false),
   244  
   245  			Entry("CF_TRACE false, '-v': enables verbose", "false", "", true),
   246  			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true),
   247  
   248  			Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true),
   249  			Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false),
   250  			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true),
   251  
   252  			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true),
   253  			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false),
   254  			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true),
   255  		)
   256  
   257  		DescribeTable("displays verbose output to multiple files",
   258  			func(env string, configTrace string, flag bool, location []string) {
   259  				tmpDir, err := ioutil.TempDir("", "")
   260  				defer os.RemoveAll(tmpDir)
   261  				Expect(err).NotTo(HaveOccurred())
   262  
   263  				helpers.SetupCF(ReadOnlyOrg, ReadOnlySpace)
   264  
   265  				// Invalidate the access token to cause a token refresh in order to
   266  				// test the call to the UAA.
   267  				helpers.SetConfig(func(config *configv3.Config) {
   268  					config.ConfigFile.AccessToken = helpers.InvalidAccessToken()
   269  				})
   270  
   271  				var envMap map[string]string
   272  				if env != "" {
   273  					if string(env[0]) == "/" {
   274  						env = filepath.Join(tmpDir, env)
   275  					}
   276  					envMap = map[string]string{"CF_TRACE": env}
   277  				}
   278  
   279  				command := []string{"run-task", "app", "echo"}
   280  
   281  				if flag {
   282  					command = append(command, "-v")
   283  				}
   284  
   285  				if configTrace != "" {
   286  					if string(configTrace[0]) == "/" {
   287  						configTrace = filepath.Join(tmpDir, configTrace)
   288  					}
   289  					session := helpers.CF("config", "--trace", configTrace)
   290  					Eventually(session).Should(Exit(0))
   291  				}
   292  
   293  				session := helpers.CFWithEnv(envMap, command...)
   294  				Eventually(session).Should(Exit(1))
   295  
   296  				for _, filePath := range location {
   297  					contents, err := ioutil.ReadFile(tmpDir + filePath)
   298  					Expect(err).ToNot(HaveOccurred())
   299  
   300  					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
   301  					Expect(string(contents)).To(MatchRegexp("GET /v3/apps"))
   302  					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))
   303  					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
   304  					Expect(string(contents)).To(MatchRegexp("POST /oauth/token"))
   305  					Expect(string(contents)).To(MatchRegexp("RESPONSE:"))
   306  
   307  					stat, err := os.Stat(tmpDir + filePath)
   308  					Expect(err).ToNot(HaveOccurred())
   309  
   310  					if runtime.GOOS == "windows" {
   311  						Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String()))
   312  					} else {
   313  						Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String()))
   314  					}
   315  				}
   316  			},
   317  
   318  			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false, []string{"/foo"}),
   319  
   320  			Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", false, []string{"/foo"}),
   321  			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true, []string{"/foo"}),
   322  
   323  			Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", false, []string{"/foo"}),
   324  			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true, []string{"/foo"}),
   325  
   326  			Entry("CF_TRACE filepath: enables logging to file", "/foo", "", false, []string{"/foo"}),
   327  			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true, []string{"/foo"}),
   328  			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false, []string{"/foo"}),
   329  			Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", false, []string{"/foo", "/bar"}),
   330  			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true, []string{"/foo", "/bar"}),
   331  		)
   332  	})
   333  
   334  	Describe("NOAA", func() {
   335  		var orgName string
   336  
   337  		BeforeEach(func() {
   338  			orgName = helpers.NewOrgName()
   339  			spaceName := helpers.NewSpaceName()
   340  
   341  			helpers.SetupCF(orgName, spaceName)
   342  		})
   343  
   344  		AfterEach(func() {
   345  			Eventually(helpers.CF("config", "--trace", "false")).Should(Exit(0))
   346  			helpers.QuickDeleteOrg(orgName)
   347  		})
   348  
   349  		DescribeTable("displays verbose output to terminal",
   350  			func(env string, configTrace string, flag bool) {
   351  				tmpDir, err := ioutil.TempDir("", "")
   352  				defer os.RemoveAll(tmpDir)
   353  				Expect(err).NotTo(HaveOccurred())
   354  
   355  				appName := helpers.PrefixedRandomName("app")
   356  
   357  				helpers.WithHelloWorldApp(func(appDir string) {
   358  					Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   359  				})
   360  
   361  				var envMap map[string]string
   362  				if env != "" {
   363  					if string(env[0]) == "/" {
   364  						env = filepath.Join(tmpDir, env)
   365  					}
   366  					envMap = map[string]string{"CF_TRACE": env}
   367  				}
   368  
   369  				command := []string{"logs", appName}
   370  
   371  				if flag {
   372  					command = append(command, "-v")
   373  				}
   374  
   375  				if configTrace != "" {
   376  					if string(configTrace[0]) == "/" {
   377  						configTrace = filepath.Join(tmpDir, configTrace)
   378  					}
   379  					session := helpers.CF("config", "--trace", configTrace)
   380  					Eventually(session).Should(Exit(0))
   381  				}
   382  
   383  				session := helpers.CFWithEnv(envMap, command...)
   384  
   385  				Eventually(session).Should(Say("REQUEST:"))
   386  				Eventually(session).Should(Say("POST /oauth/token"))
   387  				Eventually(session).Should(Say(`\[PRIVATE DATA HIDDEN\]`))
   388  				Eventually(session).Should(Say("WEBSOCKET REQUEST:"))
   389  				Eventually(session).Should(Say(`Authorization: \[PRIVATE DATA HIDDEN\]`))
   390  				Eventually(session.Kill()).Should(Exit())
   391  			},
   392  
   393  			Entry("CF_TRACE true: enables verbose", "true", "", false),
   394  			Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false),
   395  			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false),
   396  
   397  			Entry("CF_TRACE false, '-v': enables verbose", "false", "", true),
   398  			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true),
   399  
   400  			Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true),
   401  			Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false),
   402  			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true),
   403  
   404  			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true),
   405  			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false),
   406  			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true),
   407  		)
   408  
   409  		DescribeTable("displays verbose output to multiple files",
   410  			func(env string, configTrace string, location []string) {
   411  				tmpDir, err := ioutil.TempDir("", "")
   412  				defer os.RemoveAll(tmpDir)
   413  				Expect(err).NotTo(HaveOccurred())
   414  
   415  				appName := helpers.PrefixedRandomName("app")
   416  
   417  				helpers.WithHelloWorldApp(func(appDir string) {
   418  					Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   419  				})
   420  
   421  				var envMap map[string]string
   422  				if env != "" {
   423  					if string(env[0]) == "/" {
   424  						env = filepath.Join(tmpDir, env)
   425  					}
   426  					envMap = map[string]string{"CF_TRACE": env}
   427  				}
   428  
   429  				if configTrace != "" {
   430  					if strings.HasPrefix(configTrace, "/") {
   431  						configTrace = filepath.Join(tmpDir, configTrace)
   432  					}
   433  					session := helpers.CF("config", "--trace", configTrace)
   434  					Eventually(session).Should(Exit(0))
   435  				}
   436  
   437  				session := helpers.CFWithEnv(envMap, "logs", "-v", appName)
   438  
   439  				Eventually(session).Should(Say("WEBSOCKET RESPONSE"))
   440  				Eventually(session.Kill()).Should(Exit())
   441  
   442  				for _, filePath := range location {
   443  					contents, err := ioutil.ReadFile(tmpDir + filePath)
   444  					Expect(err).ToNot(HaveOccurred())
   445  
   446  					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
   447  					Expect(string(contents)).To(MatchRegexp("POST /oauth/token"))
   448  					Expect(string(contents)).To(MatchRegexp(`\[PRIVATE DATA HIDDEN\]`))
   449  					Expect(string(contents)).To(MatchRegexp("WEBSOCKET REQUEST:"))
   450  					Expect(string(contents)).To(MatchRegexp(`Authorization: \[PRIVATE DATA HIDDEN\]`))
   451  
   452  					stat, err := os.Stat(tmpDir + filePath)
   453  					Expect(err).ToNot(HaveOccurred())
   454  
   455  					if runtime.GOOS == "windows" {
   456  						Expect(stat.Mode().String()).To(Equal(os.FileMode(0666).String()))
   457  					} else {
   458  						Expect(stat.Mode().String()).To(Equal(os.FileMode(0600).String()))
   459  					}
   460  				}
   461  			},
   462  
   463  			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", []string{"/foo"}),
   464  
   465  			Entry("CF_TRACE false, config trace file path: enables logging to file", "false", "/foo", []string{"/foo"}),
   466  			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", []string{"/foo"}),
   467  
   468  			Entry("CF_TRACE empty, config trace file path: enables logging to file", "", "/foo", []string{"/foo"}),
   469  			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", []string{"/foo"}),
   470  
   471  			Entry("CF_TRACE filepath: enables logging to file", "/foo", "", []string{"/foo"}),
   472  			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", []string{"/foo"}),
   473  			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", []string{"/foo"}),
   474  			Entry("CF_TRACE filepath, config trace filepath: enables logging to file for BOTH paths", "/foo", "/bar", []string{"/foo", "/bar"}),
   475  			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", []string{"/foo", "/bar"}),
   476  		)
   477  	})
   478  
   479  	Describe("routing", func() {
   480  		BeforeEach(func() {
   481  			helpers.SkipIfNoRoutingAPI()
   482  		})
   483  
   484  		When("the user does not provide the -v flag, the CF_TRACE env var, or the --trace config option", func() {
   485  			It("should not log requests", func() {
   486  				tmpDir, err := ioutil.TempDir("", "")
   487  				defer os.RemoveAll(tmpDir)
   488  				Expect(err).NotTo(HaveOccurred())
   489  
   490  				helpers.LoginCF()
   491  				helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace)
   492  
   493  				command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"}
   494  
   495  				session := helpers.CF(command...)
   496  
   497  				Consistently(session).ShouldNot(Say(`GET /routing/v1`))
   498  				Eventually(session).Should(Exit(0))
   499  			})
   500  		})
   501  
   502  		DescribeTable("verbose logging to stdout",
   503  			func(cfTraceEnvVar string, configTraceValue string, vFlagSet bool) {
   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  				var envTraceFile string
   512  				if _, err := strconv.ParseBool(cfTraceEnvVar); err != nil && len(cfTraceEnvVar) > 0 {
   513  					cfTraceEnvVar = filepath.Join(tmpDir, cfTraceEnvVar)
   514  					envTraceFile = cfTraceEnvVar
   515  				}
   516  				envMap := map[string]string{"CF_TRACE": cfTraceEnvVar}
   517  
   518  				command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"}
   519  
   520  				if vFlagSet {
   521  					command = append(command, "-v")
   522  				}
   523  
   524  				var configTraceFile string
   525  				if configTraceValue != "" {
   526  					if _, err := strconv.ParseBool(configTraceValue); err != nil && len(configTraceValue) > 0 {
   527  						configTraceValue = filepath.Join(tmpDir, configTraceValue)
   528  						configTraceFile = configTraceValue
   529  					}
   530  					session := helpers.CF("config", "--trace", configTraceValue)
   531  					Eventually(session).Should(Exit(0))
   532  				}
   533  
   534  				session := helpers.CFWithEnv(envMap, command...)
   535  
   536  				Eventually(session).Should(Say(`GET /routing/v1/router_groups\?name=default-tcp`))
   537  				Eventually(session).Should(Exit(0))
   538  
   539  				if len(envTraceFile) > 0 {
   540  					assertLogsWrittenToFile(envTraceFile, "GET /routing/v1/router_groups?name=default-tcp")
   541  				}
   542  
   543  				if len(configTraceFile) > 0 {
   544  					assertLogsWrittenToFile(configTraceFile, "GET /routing/v1/router_groups?name=default-tcp")
   545  				}
   546  			},
   547  
   548  			Entry("CF_TRACE=true, enables verbose", "true", "", false),
   549  			Entry("CF_TRACE=true, config trace false: enables verbose", "true", "false", false),
   550  			Entry("CF_TRACE=true, config trace file path: enables verbose AND logging to file", "true", "/foo", false),
   551  
   552  			Entry("CF_TRACE=false, '-v': enables verbose", "false", "", true),
   553  			Entry("CF_TRACE=false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true),
   554  
   555  			Entry("CF_TRACE unset, '-v': enables verbose", "", "", true),
   556  			Entry("CF_TRACE unset, config trace true: enables verbose", "", "true", false),
   557  			Entry("CF_TRACE unset, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true),
   558  
   559  			Entry("CF_TRACE=filepath, '-v': enables logging to file", "/foo", "", true),
   560  			Entry("CF_TRACE=filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false),
   561  		)
   562  
   563  		DescribeTable("verbose logging to a file",
   564  			func(cfTraceEnvVar string, configTraceValue string, vFlagSet bool) {
   565  				tmpDir, err := ioutil.TempDir("", "")
   566  				defer os.RemoveAll(tmpDir)
   567  				Expect(err).NotTo(HaveOccurred())
   568  
   569  				helpers.LoginCF()
   570  				helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace)
   571  
   572  				var envMap map[string]string
   573  
   574  				var envTraceFile string
   575  				if cfTraceEnvVar != "" {
   576  					if _, err := strconv.ParseBool(cfTraceEnvVar); err != nil {
   577  						cfTraceEnvVar = filepath.Join(tmpDir, cfTraceEnvVar)
   578  						envTraceFile = cfTraceEnvVar
   579  					}
   580  					envMap = map[string]string{"CF_TRACE": cfTraceEnvVar}
   581  				}
   582  
   583  				var configTraceFile string
   584  				if configTraceValue != "" {
   585  					if _, err := strconv.ParseBool(configTraceValue); err != nil {
   586  						configTraceValue = filepath.Join(tmpDir, configTraceValue)
   587  						configTraceFile = configTraceValue
   588  					}
   589  					session := helpers.CF("config", "--trace", configTraceValue)
   590  					Eventually(session).Should(Exit(0))
   591  				}
   592  
   593  				command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"}
   594  
   595  				if vFlagSet {
   596  					command = append(command, "-v")
   597  				}
   598  
   599  				session := helpers.CFWithEnv(envMap, command...)
   600  				Eventually(session).Should(Exit(0))
   601  
   602  				if len(envTraceFile) > 0 {
   603  					assertLogsWrittenToFile(envTraceFile, "GET /routing/v1/router_groups?name=default-tcp")
   604  				}
   605  
   606  				if len(configTraceFile) > 0 {
   607  					assertLogsWrittenToFile(configTraceFile, "GET /routing/v1/router_groups?name=default-tcp")
   608  				}
   609  			},
   610  
   611  			Entry("CF_TRACE=false, config trace file path: enables logging to file", "false", "/foo", false),
   612  			Entry("CF_TRACE unset, config trace file path: enables logging to file", "", "/foo", false),
   613  			Entry("CF_TRACE=filepath: enables logging to file", "/foo", "", false),
   614  		)
   615  
   616  		When("the values of CF_TRACE and config.trace are two different filepaths", func() {
   617  			var (
   618  				configTraceFile, envTraceFile string
   619  				cfEnv                         map[string]string
   620  			)
   621  
   622  			BeforeEach(func() {
   623  				helpers.LoginCF()
   624  				helpers.TargetOrgAndSpace(ReadOnlyOrg, ReadOnlySpace)
   625  
   626  				tmpDir, err := ioutil.TempDir("", "")
   627  				defer os.RemoveAll(tmpDir)
   628  				Expect(err).NotTo(HaveOccurred())
   629  
   630  				configTraceFile = filepath.Join(tmpDir, "/foo")
   631  				session := helpers.CF("config", "--trace", configTraceFile)
   632  				Eventually(session).Should(Exit(0))
   633  
   634  				envTraceFile = filepath.Join(tmpDir, "/bar")
   635  				cfEnv = map[string]string{
   636  					"CF_TRACE": envTraceFile,
   637  				}
   638  			})
   639  
   640  			It("logs verbose output to both files", func() {
   641  				command := []string{"create-shared-domain", helpers.NewDomainName(), "--router-group", "default-tcp"}
   642  
   643  				session := helpers.CFWithEnv(cfEnv, command...)
   644  				Eventually(session).Should(Exit(0))
   645  
   646  				assertLogsWrittenToFile(envTraceFile, "GET /routing/v1/router_groups?name=default-tcp")
   647  				assertLogsWrittenToFile(configTraceFile, "GET /routing/v1/router_groups?name=default-tcp")
   648  
   649  				configStat, err := os.Stat(configTraceFile)
   650  				Expect(err).ToNot(HaveOccurred())
   651  
   652  				envStat, err := os.Stat(envTraceFile)
   653  				Expect(err).ToNot(HaveOccurred())
   654  
   655  				var fileMode os.FileMode
   656  				if runtime.GOOS == "windows" {
   657  					fileMode = os.FileMode(0666)
   658  				} else {
   659  					fileMode = os.FileMode(0600)
   660  				}
   661  
   662  				Expect(configStat.Mode().String()).To(Equal(fileMode.String()))
   663  				Expect(envStat.Mode().String()).To(Equal(fileMode.String()))
   664  			})
   665  		})
   666  	})
   667  })
   668  
   669  func assertLogsWrittenToFile(filepath string, expected string) {
   670  	contents, err := ioutil.ReadFile(filepath)
   671  	Expect(err).ToNot(HaveOccurred())
   672  	Expect(string(contents)).To(ContainSubstring(expected), "Logging to a file failed")
   673  }