github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/integration/helpers/command.go (about)

     1  package helpers
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"os"
     7  	"os/exec"
     8  	"regexp"
     9  	"strings"
    10  
    11  	. "github.com/onsi/ginkgo"
    12  	. "github.com/onsi/gomega"
    13  	. "github.com/onsi/gomega/gexec"
    14  )
    15  
    16  const (
    17  	DebugCommandPrefix        = "\nCMD>"
    18  	DebugCommandPrefixWithDir = "\nCMD %s>"
    19  	DebugOutPrefix            = "OUT: "
    20  	DebugErrPrefix            = "ERR: "
    21  )
    22  
    23  var isPass = regexp.MustCompile("(?i)password|token")
    24  
    25  // CF runs a 'cf' command with given arguments.
    26  func CF(args ...string) *Session {
    27  	WriteCommand("", nil, args)
    28  	session, err := Start(
    29  		exec.Command("cf", args...),
    30  		NewPrefixedWriter(DebugOutPrefix, GinkgoWriter),
    31  		NewPrefixedWriter(DebugErrPrefix, GinkgoWriter))
    32  	Expect(err).NotTo(HaveOccurred())
    33  	return session
    34  }
    35  
    36  // CFEnv represents configuration for running a 'cf' command. It allows us to
    37  // run a 'cf' command with a custom working directory, specific environment
    38  // variables, and stdin.
    39  type CFEnv struct {
    40  	WorkingDirectory string
    41  	EnvVars          map[string]string
    42  	stdin            io.Reader
    43  }
    44  
    45  // CustomCF runs a 'cf' command with a custom environment and given arguments.
    46  func CustomCF(cfEnv CFEnv, args ...string) *Session {
    47  	command := exec.Command("cf", args...)
    48  	if cfEnv.stdin != nil {
    49  		command.Stdin = cfEnv.stdin
    50  	}
    51  	if cfEnv.WorkingDirectory != "" {
    52  		command.Dir = cfEnv.WorkingDirectory
    53  	}
    54  
    55  	if cfEnv.EnvVars != nil {
    56  		env := os.Environ()
    57  		for key, val := range cfEnv.EnvVars {
    58  			env = AddOrReplaceEnvironment(env, key, val)
    59  		}
    60  		command.Env = env
    61  	}
    62  
    63  	WriteCommand("", cfEnv.EnvVars, args)
    64  	session, err := Start(
    65  		command,
    66  		NewPrefixedWriter(DebugOutPrefix, GinkgoWriter),
    67  		NewPrefixedWriter(DebugErrPrefix, GinkgoWriter))
    68  	Expect(err).NotTo(HaveOccurred())
    69  	return session
    70  }
    71  
    72  // DebugCustomCF runs a 'cf' command with a custom environment and given
    73  // arguments, with CF_LOG_LEVEL set to 'debug'.
    74  func DebugCustomCF(cfEnv CFEnv, args ...string) *Session {
    75  	if cfEnv.EnvVars == nil {
    76  		cfEnv.EnvVars = map[string]string{}
    77  	}
    78  	cfEnv.EnvVars["CF_LOG_LEVEL"] = "debug"
    79  
    80  	return CustomCF(cfEnv, args...)
    81  }
    82  
    83  // CFWithStdin runs a 'cf' command with a custom stdin and given arguments.
    84  func CFWithStdin(stdin io.Reader, args ...string) *Session {
    85  	WriteCommand("", nil, args)
    86  	command := exec.Command("cf", args...)
    87  	command.Stdin = stdin
    88  	session, err := Start(
    89  		command,
    90  		NewPrefixedWriter(DebugOutPrefix, GinkgoWriter),
    91  		NewPrefixedWriter(DebugErrPrefix, GinkgoWriter))
    92  	Expect(err).NotTo(HaveOccurred())
    93  	return session
    94  }
    95  
    96  // CFWithEnv runs a 'cf' command with specified environment variables and given arguments.
    97  func CFWithEnv(envVars map[string]string, args ...string) *Session {
    98  	return CustomCF(CFEnv{EnvVars: envVars}, args...)
    99  }
   100  
   101  // WriteCommand prints the working directory, the environment variables, and
   102  // 'cf' with the given arguments. Environment variables that are passwords will
   103  // be redacted.
   104  func WriteCommand(workingDir string, env map[string]string, args []string) {
   105  	start := DebugCommandPrefix
   106  	if workingDir != "" {
   107  		start = fmt.Sprintf(DebugCommandPrefixWithDir, workingDir)
   108  	}
   109  
   110  	display := []string{
   111  		start,
   112  	}
   113  
   114  	for key, val := range env {
   115  		if isPass.MatchString(key) {
   116  			val = "*****"
   117  		}
   118  		display = append(display, fmt.Sprintf("%s=%s", key, val))
   119  	}
   120  
   121  	display = append(display, "cf")
   122  	display = append(display, args...)
   123  	GinkgoWriter.Write([]byte(strings.Join(append(display, "\n"), " ")))
   124  }