github.com/arunkumar7540/cli@v6.45.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  	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("REQUEST:"))
   388  				Eventually(session).Should(Say("GET /v2/info"))
   389  				Eventually(session).Should(Say("WEBSOCKET REQUEST:"))
   390  				Eventually(session).Should(Say(`Authorization: \[PRIVATE DATA HIDDEN\]`))
   391  				Eventually(session.Kill()).Should(Exit())
   392  			},
   393  
   394  			Entry("CF_TRACE true: enables verbose", "true", "", false),
   395  			Entry("CF_Trace true, config trace false: enables verbose", "true", "false", false),
   396  			Entry("CF_Trace true, config trace file path: enables verbose AND logging to file", "true", "/foo", false),
   397  
   398  			Entry("CF_TRACE false, '-v': enables verbose", "false", "", true),
   399  			Entry("CF_TRACE false, config trace file path, '-v': enables verbose AND logging to file", "false", "/foo", true),
   400  
   401  			Entry("CF_TRACE empty:, '-v': enables verbose", "", "", true),
   402  			Entry("CF_TRACE empty, config trace true: enables verbose", "", "true", false),
   403  			Entry("CF_TRACE empty, config trace file path, '-v': enables verbose AND logging to file", "", "/foo", true),
   404  
   405  			Entry("CF_TRACE filepath, '-v': enables logging to file", "/foo", "", true),
   406  			Entry("CF_TRACE filepath, config trace true: enables verbose AND logging to file", "/foo", "true", false),
   407  			Entry("CF_TRACE filepath, config trace filepath, '-v': enables verbose AND logging to file for BOTH paths", "/foo", "/bar", true),
   408  		)
   409  
   410  		DescribeTable("displays verbose output to multiple files",
   411  			func(env string, configTrace string, location []string) {
   412  				tmpDir, err := ioutil.TempDir("", "")
   413  				defer os.RemoveAll(tmpDir)
   414  				Expect(err).NotTo(HaveOccurred())
   415  
   416  				appName := helpers.PrefixedRandomName("app")
   417  
   418  				helpers.WithHelloWorldApp(func(appDir string) {
   419  					Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   420  				})
   421  
   422  				var envMap map[string]string
   423  				if env != "" {
   424  					if string(env[0]) == "/" {
   425  						env = filepath.Join(tmpDir, env)
   426  					}
   427  					envMap = map[string]string{"CF_TRACE": env}
   428  				}
   429  
   430  				if configTrace != "" {
   431  					if strings.HasPrefix(configTrace, "/") {
   432  						configTrace = filepath.Join(tmpDir, configTrace)
   433  					}
   434  					session := helpers.CF("config", "--trace", configTrace)
   435  					Eventually(session).Should(Exit(0))
   436  				}
   437  
   438  				session := helpers.CFWithEnv(envMap, "logs", "-v", appName)
   439  
   440  				Eventually(session).Should(Say("WEBSOCKET RESPONSE"))
   441  				Eventually(session.Kill()).Should(Exit())
   442  
   443  				for _, filePath := range location {
   444  					contents, err := ioutil.ReadFile(tmpDir + filePath)
   445  					Expect(err).ToNot(HaveOccurred())
   446  
   447  					Expect(string(contents)).To(MatchRegexp("REQUEST:"))
   448  					Expect(string(contents)).To(MatchRegexp("GET /v2/info"))
   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  }