github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/cf/ssh/options/ssh_options.go (about) 1 package options 2 3 import ( 4 "fmt" 5 "strings" 6 7 "code.cloudfoundry.org/cli/cf/flags" 8 ) 9 10 type TTYRequest int 11 12 const ( 13 RequestTTYAuto TTYRequest = iota 14 RequestTTYNo 15 RequestTTYYes 16 RequestTTYForce 17 ) 18 19 type ForwardSpec struct { 20 ListenAddress string 21 ConnectAddress string 22 } 23 24 type SSHOptions struct { 25 AppName string 26 Command []string 27 Index uint 28 SkipHostValidation bool 29 SkipRemoteExecution bool 30 TerminalRequest TTYRequest 31 ForwardSpecs []ForwardSpec 32 } 33 34 func NewSSHOptions(fc flags.FlagContext) (*SSHOptions, error) { 35 sshOptions := &SSHOptions{} 36 37 sshOptions.AppName = fc.Args()[0] 38 sshOptions.Index = uint(fc.Int("i")) 39 sshOptions.SkipHostValidation = fc.Bool("k") 40 sshOptions.SkipRemoteExecution = fc.Bool("N") 41 sshOptions.Command = fc.StringSlice("c") 42 43 if fc.IsSet("L") { 44 for _, arg := range fc.StringSlice("L") { 45 forwardSpec, err := sshOptions.parseLocalForwardingSpec(arg) 46 if err != nil { 47 return sshOptions, err 48 } 49 sshOptions.ForwardSpecs = append(sshOptions.ForwardSpecs, *forwardSpec) 50 } 51 } 52 53 if fc.IsSet("t") && fc.Bool("t") { 54 sshOptions.TerminalRequest = RequestTTYYes 55 } 56 57 if fc.IsSet("tt") && fc.Bool("tt") { 58 sshOptions.TerminalRequest = RequestTTYForce 59 } 60 61 if fc.Bool("T") { 62 sshOptions.TerminalRequest = RequestTTYNo 63 } 64 65 return sshOptions, nil 66 } 67 68 func (o *SSHOptions) parseLocalForwardingSpec(arg string) (*ForwardSpec, error) { 69 arg = strings.TrimSpace(arg) 70 71 parts := []string{} 72 for remainder := arg; remainder != ""; { 73 part, r, err := tokenizeForward(remainder) 74 if err != nil { 75 return nil, err 76 } 77 78 parts = append(parts, part) 79 remainder = r 80 } 81 82 forwardSpec := &ForwardSpec{} 83 switch len(parts) { 84 case 4: 85 if parts[0] == "*" { 86 parts[0] = "" 87 } 88 forwardSpec.ListenAddress = fmt.Sprintf("%s:%s", parts[0], parts[1]) 89 forwardSpec.ConnectAddress = fmt.Sprintf("%s:%s", parts[2], parts[3]) 90 case 3: 91 forwardSpec.ListenAddress = fmt.Sprintf("localhost:%s", parts[0]) 92 forwardSpec.ConnectAddress = fmt.Sprintf("%s:%s", parts[1], parts[2]) 93 default: 94 return nil, fmt.Errorf("Unable to parse local forwarding argument: %q", arg) 95 } 96 97 return forwardSpec, nil 98 } 99 100 func tokenizeForward(arg string) (string, string, error) { 101 switch arg[0] { 102 case ':': 103 return "", arg[1:], nil 104 105 case '[': 106 parts := strings.SplitAfterN(arg, "]", 2) 107 if len(parts) != 2 { 108 return "", "", fmt.Errorf("Argument missing closing bracket: %q", arg) 109 } 110 111 if parts[1][0] == ':' { 112 return parts[0], parts[1][1:], nil 113 } 114 115 return "", "", fmt.Errorf("Unexpected token: %q", parts[1]) 116 117 default: 118 parts := strings.SplitN(arg, ":", 2) 119 if len(parts) < 2 { 120 return parts[0], "", nil 121 } 122 return parts[0], parts[1], nil 123 } 124 }