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  }