From cf0cf62eb4e077afd768b56f0223c1b442b3dcac Mon Sep 17 00:00:00 2001 From: Quentin Perez Date: Wed, 25 Nov 2015 17:51:10 +0100 Subject: [PATCH 1/3] fix #239 --- pkg/cli/cmd_run.go | 5 ++++- pkg/commands/run.go | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/pkg/cli/cmd_run.go b/pkg/cli/cmd_run.go index e989ed4d92..abfd7dfbf6 100644 --- a/pkg/cli/cmd_run.go +++ b/pkg/cli/cmd_run.go @@ -33,9 +33,10 @@ var cmdRun = &Command{ func init() { cmdRun.Flag.StringVar(&runCreateName, []string{"-name"}, "", "Assign a name") cmdRun.Flag.StringVar(&runCreateBootscript, []string{"-bootscript"}, "", "Assign a bootscript") - cmdRun.Flag.StringVar(&runCreateEnv, []string{"e", "-env"}, "", "Provide metadata tags passed to initrd (i.e., boot=resue INITRD_DEBUG=1)") + cmdRun.Flag.StringVar(&runCreateEnv, []string{"e", "-env"}, "", "Provide metadata tags passed to initrd (i.e., boot=rescue INITRD_DEBUG=1)") cmdRun.Flag.StringVar(&runCreateVolume, []string{"v", "-volume"}, "", "Attach additional volume (i.e., 50G)") cmdRun.Flag.BoolVar(&runHelpFlag, []string{"h", "-help"}, false, "Print usage") + cmdRun.Flag.Int64Var(&runTimeout, []string{"T", "-timeout"}, 0, "Set timeout value to seconds") cmdRun.Flag.StringVar(&runIPAddress, []string{"-ip-address"}, "", "Assign an IP") cmdRun.Flag.BoolVar(&runAttachFlag, []string{"a", "-attach"}, false, "Attach to serial console") cmdRun.Flag.BoolVar(&runDetachFlag, []string{"d", "-detach"}, false, "Run server in background and print server ID") @@ -59,6 +60,7 @@ var runDetachFlag bool // -d, --detach flag var runGateway string // -g, --gateway flag var runTmpSSHKey bool // --tmp-ssh-key flag var runShowBoot bool // --show-boot flag +var runTimeout int64 // --timeout flag func runRun(cmd *Command, rawArgs []string) error { if runHelpFlag { @@ -101,6 +103,7 @@ func runRun(cmd *Command, rawArgs []string) error { TmpSSHKey: runTmpSSHKey, ShowBoot: runShowBoot, IP: runIPAddress, + Timeout: runTimeout, // FIXME: DynamicIPRequired // FIXME: Timeout } diff --git a/pkg/commands/run.go b/pkg/commands/run.go index f42ceecc6b..99b3f21638 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -10,6 +10,7 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/scaleway/scaleway-cli/pkg/api" "github.com/scaleway/scaleway-cli/pkg/config" @@ -32,6 +33,7 @@ type RunArgs struct { AutoRemove bool TmpSSHKey bool ShowBoot bool + Timeout int64 // DynamicIPRequired // Timeout } @@ -116,6 +118,19 @@ func Run(ctx CommandContext, args RunArgs) error { // Sync cache on disk ctx.API.Sync() + closeTimeout := make(chan struct{}) + + if args.Timeout > 0 { + go func() { + select { + case <-time.After(time.Duration(args.Timeout) * time.Second): + // FIXME: avoid use of fatalf + logrus.Fatalf("Operation timed out") + case <-closeTimeout: + break + } + }() + } if args.ShowBoot { // Attach to server serial logrus.Info("Attaching to server console ...") @@ -129,6 +144,7 @@ func Run(ctx CommandContext, args RunArgs) error { return err } sshConnection := <-notif + close(closeTimeout) gottycli.ExitLoop() <-done utils.Quiet(false) @@ -147,6 +163,7 @@ func Run(ctx CommandContext, args RunArgs) error { if err != nil { return fmt.Errorf("cannot attach to server serial: %v", err) } + close(closeTimeout) <-done gottycli.Close() } else { @@ -155,6 +172,7 @@ func Run(ctx CommandContext, args RunArgs) error { return err } sshConnection := <-notif + close(closeTimeout) if sshConnection.err != nil { return sshConnection.err } From 9ceed6c18baca44293f16f9f1db0504752efd060 Mon Sep 17 00:00:00 2001 From: Quentin Perez Date: Thu, 26 Nov 2015 16:45:33 +0100 Subject: [PATCH 2/3] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fffabcd1e..5c1875774f 100644 --- a/README.md +++ b/README.md @@ -677,13 +677,14 @@ Options: -a, --attach=false Attach to serial console --bootscript="" Assign a bootscript -d, --detach=false Run server in background and print server ID - -e, --env="" Provide metadata tags passed to initrd (i.e., boot=resue INITRD_DEBUG=1) + -e, --env="" Provide metadata tags passed to initrd (i.e., boot=rescue INITRD_DEBUG=1) -g, --gateway="" Use a SSH gateway -h, --help=false Print usage --ip-address="" Assign an IP --name="" Assign a name --rm=false Automatically remove the server when it exits --show-boot=false Allows to show the boot + -T, --timeout=0 Set timeout value to seconds --tmp-ssh-key=false Access your server without uploading your SSH key to your account -v, --volume="" Attach additional volume (i.e., 50G) @@ -1142,6 +1143,7 @@ $ scw inspect myserver | jq '.[0].public_ip.address' ### master (unreleased) +* Support of `scw run --timeout=X` ([#239](https://github.com/scaleway/scaleway-cli/issues/239)) * Check the "stopped" state for `scw run | exec -w`([#229](https://github.com/scaleway/scaleway-cli/issues/229)) View full [commits list](https://github.com/scaleway/scaleway-cli/compare/v1.6.0...master) From 83765abb49092736ed8ad4a70c5be40a629674c2 Mon Sep 17 00:00:00 2001 From: Quentin Perez Date: Fri, 27 Nov 2015 11:29:39 +0100 Subject: [PATCH 3/3] Remove fatalf into run.go file --- pkg/commands/run.go | 78 +++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 99b3f21638..e0eb600656 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -119,13 +119,13 @@ func Run(ctx CommandContext, args RunArgs) error { ctx.API.Sync() closeTimeout := make(chan struct{}) + timeoutExit := make(chan struct{}) if args.Timeout > 0 { go func() { select { case <-time.After(time.Duration(args.Timeout) * time.Second): - // FIXME: avoid use of fatalf - logrus.Fatalf("Operation timed out") + close(timeoutExit) case <-closeTimeout: break } @@ -136,59 +136,75 @@ func Run(ctx CommandContext, args RunArgs) error { logrus.Info("Attaching to server console ...") gottycli, done, err := utils.AttachToSerial(serverID, ctx.API.Token) if err != nil { + close(closeTimeout) return fmt.Errorf("cannot attach to server serial: %v", err) } utils.Quiet(true) notif, gateway, err := waitSSHConnection(ctx, args, serverID) if err != nil { + close(closeTimeout) + gottycli.ExitLoop() + <-done return err } - sshConnection := <-notif - close(closeTimeout) - gottycli.ExitLoop() - <-done - utils.Quiet(false) - if sshConnection.err != nil { - return sshConnection.err - } - server := sshConnection.server - logrus.Info("Connecting to server ...") - if err = utils.SSHExec(server.PublicAddress.IP, server.PrivateIP, []string{}, false, gateway); err != nil { - return fmt.Errorf("Connection to server failed: %v", err) + select { + case <-timeoutExit: + gottycli.ExitLoop() + <-done + utils.Quiet(false) + return fmt.Errorf("Operation timed out") + case sshConnection := <-notif: + close(closeTimeout) + gottycli.ExitLoop() + <-done + utils.Quiet(false) + if sshConnection.err != nil { + return sshConnection.err + } + server := sshConnection.server + logrus.Info("Connecting to server ...") + if err = utils.SSHExec(server.PublicAddress.IP, server.PrivateIP, []string{}, false, gateway); err != nil { + return fmt.Errorf("Connection to server failed: %v", err) + } } } else if args.Attach { // Attach to server serial logrus.Info("Attaching to server console ...") gottycli, done, err := utils.AttachToSerial(serverID, ctx.API.Token) + close(closeTimeout) if err != nil { return fmt.Errorf("cannot attach to server serial: %v", err) } - close(closeTimeout) <-done gottycli.Close() } else { notif, gateway, err := waitSSHConnection(ctx, args, serverID) if err != nil { + close(closeTimeout) return err } - sshConnection := <-notif - close(closeTimeout) - if sshConnection.err != nil { - return sshConnection.err - } - server := sshConnection.server - // exec -w SERVER COMMAND ARGS... - if len(args.Command) < 1 { - logrus.Info("Connecting to server ...") - if err = utils.SSHExec(server.PublicAddress.IP, server.PrivateIP, []string{}, false, gateway); err != nil { - return fmt.Errorf("Connection to server failed: %v", err) + select { + case <-timeoutExit: + return fmt.Errorf("Operation timed out") + case sshConnection := <-notif: + close(closeTimeout) + if sshConnection.err != nil { + return sshConnection.err } - } else { - logrus.Infof("Executing command: %s ...", args.Command) - if err = utils.SSHExec(server.PublicAddress.IP, server.PrivateIP, args.Command, false, gateway); err != nil { - return fmt.Errorf("command execution failed: %v", err) + server := sshConnection.server + // exec -w SERVER COMMAND ARGS... + if len(args.Command) < 1 { + logrus.Info("Connecting to server ...") + if err = utils.SSHExec(server.PublicAddress.IP, server.PrivateIP, []string{}, false, gateway); err != nil { + return fmt.Errorf("Connection to server failed: %v", err) + } + } else { + logrus.Infof("Executing command: %s ...", args.Command) + if err = utils.SSHExec(server.PublicAddress.IP, server.PrivateIP, args.Command, false, gateway); err != nil { + return fmt.Errorf("command execution failed: %v", err) + } + logrus.Info("Command successfuly executed") } - logrus.Info("Command successfuly executed") } } return nil