github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/command/v3/v3_ssh_command.go (about) 1 package v3 2 3 import ( 4 "net/http" 5 6 "code.cloudfoundry.org/cli/actor/sharedaction" 7 "code.cloudfoundry.org/cli/actor/v3action" 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 10 "code.cloudfoundry.org/cli/command" 11 "code.cloudfoundry.org/cli/command/flag" 12 "code.cloudfoundry.org/cli/command/translatableerror" 13 "code.cloudfoundry.org/cli/command/v3/shared" 14 "code.cloudfoundry.org/cli/util/clissh" 15 ) 16 17 //go:generate counterfeiter . SSHActor 18 19 type SSHActor interface { 20 ExecuteSecureShell(sshClient sharedaction.SecureShellClient, sshOptions sharedaction.SSHOptions) error 21 } 22 23 //go:generate counterfeiter . V3SSHActor 24 25 type V3SSHActor interface { 26 CloudControllerAPIVersion() string 27 GetSecureShellConfigurationByApplicationNameSpaceProcessTypeAndIndex(appName string, spaceGUID string, processType string, processIndex uint) (v3action.SSHAuthentication, v3action.Warnings, error) 28 } 29 30 type V3SSHCommand struct { 31 RequiredArgs flag.AppName `positional-args:"yes"` 32 ProcessIndex uint `long:"app-instance-index" short:"i" default:"0" description:"App process instance index"` 33 Commands []string `long:"command" short:"c" description:"Command to run"` 34 DisablePseudoTTY bool `long:"disable-pseudo-tty" short:"T" description:"Disable pseudo-tty allocation"` 35 ForcePseudoTTY bool `long:"force-pseudo-tty" description:"Force pseudo-tty allocation"` 36 LocalPortForwardSpecs []flag.SSHPortForwarding `short:"L" description:"Local port forward specification"` 37 ProcessType string `long:"process" default:"web" description:"App process name"` 38 RequestPseudoTTY bool `long:"request-pseudo-tty" short:"t" description:"Request pseudo-tty allocation"` 39 SkipHostValidation bool `long:"skip-host-validation" short:"k" description:"Skip host key validation. Not recommended!"` 40 SkipRemoteExecution bool `long:"skip-remote-execution" short:"N" description:"Do not execute a remote command"` 41 42 usage interface{} `usage:"cf v3-ssh APP_NAME [--process PROCESS] [-i INDEX] [-c COMMAND]\n [-L [BIND_ADDRESS:]LOCAL_PORT:REMOTE_HOST:REMOTE_PORT]... [--skip-remote-execution]\n [--disable-pseudo-tty | --force-pseudo-tty | --request-pseudo-tty] [--skip-host-validation]"` 43 relatedCommands interface{} `related_commands:"allow-space-ssh, enable-ssh, space-ssh-allowed, ssh-code, ssh-enabled"` 44 allproxy interface{} `environmentName:"all_proxy" environmentDescription:"Specify a proxy server to enable proxying for all requests"` 45 46 UI command.UI 47 Config command.Config 48 SharedActor command.SharedActor 49 Actor V3SSHActor 50 SSHActor SSHActor 51 SSHClient *clissh.SecureShell 52 } 53 54 func (cmd *V3SSHCommand) Setup(config command.Config, ui command.UI) error { 55 cmd.UI = ui 56 cmd.Config = config 57 sharedActor := sharedaction.NewActor(config) 58 cmd.SharedActor = sharedActor 59 cmd.SSHActor = sharedActor 60 61 ccClient, uaaClient, err := shared.NewClients(config, ui, true) 62 if err != nil { 63 if v3Err, ok := err.(ccerror.V3UnexpectedResponseError); ok && v3Err.ResponseCode == http.StatusNotFound { 64 return translatableerror.MinimumAPIVersionNotMetError{MinimumVersion: ccversion.MinVersionV3} 65 } 66 67 return err 68 } 69 70 cmd.Actor = v3action.NewActor(ccClient, config, sharedActor, uaaClient) 71 72 cmd.SSHClient = clissh.NewDefaultSecureShell() 73 74 return nil 75 } 76 77 func (cmd V3SSHCommand) Execute(args []string) error { 78 cmd.UI.DisplayWarning(command.ExperimentalWarning) 79 80 err := command.MinimumAPIVersionCheck(cmd.Actor.CloudControllerAPIVersion(), ccversion.MinVersionV3) 81 if err != nil { 82 return err 83 } 84 85 err = cmd.SharedActor.CheckTarget(true, true) 86 if err != nil { 87 return err 88 } 89 90 ttyOption, err := cmd.EvaluateTTYOption() 91 if err != nil { 92 return err 93 } 94 95 var forwardSpecs []sharedaction.LocalPortForward 96 for _, spec := range cmd.LocalPortForwardSpecs { 97 forwardSpecs = append(forwardSpecs, sharedaction.LocalPortForward(spec)) 98 } 99 100 sshAuth, warnings, err := cmd.Actor.GetSecureShellConfigurationByApplicationNameSpaceProcessTypeAndIndex( 101 cmd.RequiredArgs.AppName, 102 cmd.Config.TargetedSpace().GUID, 103 cmd.ProcessType, 104 cmd.ProcessIndex, 105 ) 106 cmd.UI.DisplayWarnings(warnings) 107 if err != nil { 108 return err 109 } 110 111 err = cmd.SSHActor.ExecuteSecureShell( 112 cmd.SSHClient, 113 sharedaction.SSHOptions{ 114 Commands: cmd.Commands, 115 Endpoint: sshAuth.Endpoint, 116 HostKeyFingerprint: sshAuth.HostKeyFingerprint, 117 LocalPortForwardSpecs: forwardSpecs, 118 Passcode: sshAuth.Passcode, 119 SkipHostValidation: cmd.SkipHostValidation, 120 SkipRemoteExecution: cmd.SkipRemoteExecution, 121 TTYOption: ttyOption, 122 Username: sshAuth.Username, 123 }) 124 if err != nil { 125 return err 126 } 127 128 return nil 129 } 130 131 func (cmd V3SSHCommand) parseForwardSpecs() ([]sharedaction.LocalPortForward, error) { 132 return nil, nil 133 } 134 135 // EvaluateTTYOption determines which TTY options are mutually exclusive and 136 // returns an error accordingly. 137 func (cmd V3SSHCommand) EvaluateTTYOption() (sharedaction.TTYOption, error) { 138 var count int 139 140 option := sharedaction.RequestTTYAuto 141 if cmd.DisablePseudoTTY { 142 option = sharedaction.RequestTTYNo 143 count++ 144 } 145 if cmd.ForcePseudoTTY { 146 option = sharedaction.RequestTTYForce 147 count++ 148 } 149 if cmd.RequestPseudoTTY { 150 option = sharedaction.RequestTTYYes 151 count++ 152 } 153 154 if count > 1 { 155 return option, translatableerror.ArgumentCombinationError{Args: []string{ 156 "--disable-pseudo-tty", "-T", "--force-pseudo-tty", "--request-pseudo-tty", "-t", 157 }} 158 } 159 160 return option, nil 161 }