github.com/scaleway/scaleway-cli@v1.11.1/pkg/commands/exec.go (about)

     1  // Copyright (C) 2015 Scaleway. All rights reserved.
     2  // Use of this source code is governed by a MIT-style
     3  // license that can be found in the LICENSE.md file.
     4  
     5  package commands
     6  
     7  import (
     8  	"fmt"
     9  	"time"
    10  
    11  	"github.com/Sirupsen/logrus"
    12  
    13  	"github.com/scaleway/scaleway-cli/pkg/api"
    14  	"github.com/scaleway/scaleway-cli/pkg/utils"
    15  )
    16  
    17  // ExecArgs are flags for the `RunExec` function
    18  type ExecArgs struct {
    19  	Timeout float64
    20  	Wait    bool
    21  	Gateway string
    22  	Server  string
    23  	Command []string
    24  	SSHUser string
    25  	SSHPort int
    26  }
    27  
    28  // RunExec is the handler for 'scw exec'
    29  func RunExec(ctx CommandContext, args ExecArgs) error {
    30  	var fingerprints []string
    31  
    32  	done := make(chan struct{})
    33  
    34  	serverID, err := ctx.API.GetServerID(args.Server)
    35  	if err != nil {
    36  		return err
    37  	}
    38  
    39  	go func() {
    40  		fingerprints = ctx.API.GetSSHFingerprintFromServer(serverID)
    41  		close(done)
    42  	}()
    43  	// Resolve gateway
    44  	if args.Gateway == "" {
    45  		args.Gateway = ctx.Getenv("SCW_GATEWAY")
    46  	}
    47  	var gateway string
    48  
    49  	if args.Gateway == serverID || args.Gateway == args.Server {
    50  		logrus.Debugf("The server and the gateway are the same host, using direct access to the server")
    51  		gateway = ""
    52  	} else {
    53  		gateway, err = api.ResolveGateway(ctx.API, args.Gateway)
    54  		if err != nil {
    55  			return fmt.Errorf("Cannot resolve Gateway '%s': %v", args.Gateway, err)
    56  		}
    57  		if gateway != "" {
    58  			logrus.Debugf("The server will be accessed using the gateway '%s' as a SSH relay", gateway)
    59  		}
    60  	}
    61  
    62  	var server *api.ScalewayServer
    63  	if args.Wait {
    64  		// --wait
    65  		logrus.Debugf("Waiting for server to be ready")
    66  		server, err = api.WaitForServerReady(ctx.API, serverID, gateway)
    67  		if err != nil {
    68  			return fmt.Errorf("Failed to wait for server to be ready, %v", err)
    69  		}
    70  	} else {
    71  		// no --wait
    72  		logrus.Debugf("scw won't wait for the server to be ready, if it is not, the command will fail")
    73  		server, err = ctx.API.GetServer(serverID)
    74  		if err != nil {
    75  			rerr := fmt.Errorf("Failed to get server information for %s: %v", serverID, err)
    76  			if err.Error() == `"`+serverID+`" not found` {
    77  				return fmt.Errorf("%v\nmaybe try to flush the cache with : scw _flush-cache", rerr)
    78  			}
    79  			return rerr
    80  		}
    81  	}
    82  
    83  	if server.PublicAddress.IP == "" && gateway == "" {
    84  		logrus.Warn(`Your host has no public IP address, you should use '--gateway', see 'scw help exec'`)
    85  	}
    86  
    87  	// --timeout
    88  	if args.Timeout > 0 {
    89  		logrus.Debugf("Setting up a global timeout of %d seconds", args.Timeout)
    90  		// FIXME: avoid use of log.Fatalf here
    91  		go func() {
    92  			time.Sleep(time.Duration(args.Timeout*1000) * time.Millisecond)
    93  			logrus.Fatalf("Operation timed out")
    94  		}()
    95  	}
    96  
    97  	<-done
    98  	if len(fingerprints) > 0 {
    99  		for i := range fingerprints {
   100  			fmt.Fprintf(ctx.Stdout, "%s\n", fingerprints[i])
   101  		}
   102  	}
   103  	logrus.Debugf("PublicDNS %s", serverID+api.URLPublicDNS)
   104  	logrus.Debugf("PrivateDNS %s", serverID+api.URLPrivateDNS)
   105  	if err = utils.SSHExec(server.PublicAddress.IP, server.PrivateIP, args.SSHUser, args.SSHPort, args.Command, !args.Wait, gateway); err != nil {
   106  		return fmt.Errorf("Failed to run the command: %v", err)
   107  	}
   108  
   109  	logrus.Debugf("Command successfully executed")
   110  	return nil
   111  }