Exemplo n.º 1
0
// RunTop is the handler for 'scw top'
func RunTop(ctx CommandContext, args TopArgs) error {
	serverID := ctx.API.GetServerID(args.Server)
	command := "ps"
	server, err := ctx.API.GetServer(serverID)
	if err != nil {
		return fmt.Errorf("failed to get server information for %s: %v", serverID, err)
	}

	// Resolve gateway
	if args.Gateway == "" {
		args.Gateway = ctx.Getenv("SCW_GATEWAY")
	}
	var gateway string
	if args.Gateway == serverID || args.Gateway == args.Server {
		gateway = ""
	} else {
		gateway, err = api.ResolveGateway(ctx.API, args.Gateway)
		if err != nil {
			return fmt.Errorf("cannot resolve Gateway '%s': %v", args.Gateway, err)
		}
	}

	sshCommand := utils.NewSSHExecCmd(server.PublicAddress.IP, server.PrivateIP, true, []string{command}, gateway)
	logrus.Debugf("Executing: %s", sshCommand)
	out, err := exec.Command("ssh", sshCommand.Slice()[1:]...).CombinedOutput()
	fmt.Printf("%s", out)
	return err
}
Exemplo n.º 2
0
// RunKill is the handler for 'scw kill'
func RunKill(ctx CommandContext, args KillArgs) error {
	serverID := ctx.API.GetServerID(args.Server)
	command := "halt"
	server, err := ctx.API.GetServer(serverID)
	if err != nil {
		return fmt.Errorf("failed to get server information for %s: %v", serverID, err)
	}

	// Resolve gateway
	if args.Gateway == "" {
		args.Gateway = ctx.Getenv("SCW_GATEWAY")
	}
	var gateway string
	if args.Gateway == serverID || args.Gateway == args.Server {
		gateway = ""
	} else {
		gateway, err = api.ResolveGateway(ctx.API, args.Gateway)
		if err != nil {
			return fmt.Errorf("cannot resolve Gateway '%s': %v", args.Gateway, err)
		}
	}

	sshCommand := utils.NewSSHExecCmd(server.PublicAddress.IP, server.PrivateIP, true, []string{command}, gateway)

	logrus.Debugf("Executing: %s", sshCommand)

	spawn := exec.Command("ssh", sshCommand.Slice()[1:]...)
	spawn.Stdout = ctx.Stdout
	spawn.Stdin = ctx.Stdin
	spawn.Stderr = ctx.Stderr

	return spawn.Run()
}
Exemplo n.º 3
0
// TarFromSource creates a stream buffer with the tarballed content of the user source
func TarFromSource(ctx CommandContext, source string, gateway string) (*io.ReadCloser, error) {
	var tarOutputStream io.ReadCloser

	// source is a server address + path (scp-like uri)
	if strings.Contains(source, ":") {
		logrus.Debugf("Creating a tarball remotely and streaming it using SSH")
		serverParts := strings.Split(source, ":")
		if len(serverParts) != 2 {
			return nil, fmt.Errorf("invalid source uri, see 'scw cp -h' for usage")
		}

		serverID, err := ctx.API.GetServerID(serverParts[0])
		if err != nil {
			return nil, err
		}

		server, err := ctx.API.GetServer(serverID)
		if err != nil {
			return nil, err
		}

		dir, base := utils.PathToTARPathparts(serverParts[1])
		logrus.Debugf("Equivalent to 'scp root@%s:%s/%s ...'", server.PublicAddress.IP, dir, base)

		// remoteCommand is executed on the remote server
		// it streams a tarball raw content
		remoteCommand := []string{"tar"}
		remoteCommand = append(remoteCommand, "-C", dir)
		if ctx.Getenv("DEBUG") == "1" {
			remoteCommand = append(remoteCommand, "-v")
		}
		remoteCommand = append(remoteCommand, "-cf", "-")
		remoteCommand = append(remoteCommand, base)

		// Resolve gateway
		if gateway == "" {
			gateway = ctx.Getenv("SCW_GATEWAY")
		}

		if gateway == serverID || gateway == serverParts[0] {
			gateway = ""
		} else {
			gateway, err = api.ResolveGateway(ctx.API, gateway)
			if err != nil {
				return nil, fmt.Errorf("cannot resolve Gateway '%s': %v", gateway, err)
			}
		}

		// execCmd contains the ssh connection + the remoteCommand
		sshCommand := utils.NewSSHExecCmd(server.PublicAddress.IP, server.PrivateIP, false, remoteCommand, gateway)
		logrus.Debugf("Executing: %s", sshCommand)
		spawnSrc := exec.Command("ssh", sshCommand.Slice()[1:]...)

		tarOutputStream, err = spawnSrc.StdoutPipe()
		if err != nil {
			return nil, err
		}

		tarErrorStream, err := spawnSrc.StderrPipe()
		if err != nil {
			return nil, err
		}
		defer tarErrorStream.Close()
		io.Copy(ctx.Stderr, tarErrorStream)

		err = spawnSrc.Start()
		if err != nil {
			return nil, err
		}
		defer spawnSrc.Wait()

		return &tarOutputStream, nil
	}

	// source is stdin
	if source == "-" {
		logrus.Debugf("Streaming tarball from stdin")
		// FIXME: should be ctx.Stdin
		tarOutputStream = os.Stdin
		return &tarOutputStream, nil
	}

	// source is a path on localhost
	logrus.Debugf("Taring local path %s", source)
	path, err := filepath.Abs(source)
	if err != nil {
		return nil, err
	}
	path, err = filepath.EvalSymlinks(path)
	if err != nil {
		return nil, err
	}
	logrus.Debugf("Real local path is %s", path)

	dir, base := utils.PathToTARPathparts(path)

	tarOutputStream, err = archive.TarWithOptions(dir, &archive.TarOptions{
		Compression:  archive.Uncompressed,
		IncludeFiles: []string{base},
	})
	if err != nil {
		return nil, err
	}
	return &tarOutputStream, nil
}
Exemplo n.º 4
0
// UntarToDest writes to user destination the streamed tarball in input
func UntarToDest(ctx CommandContext, sourceStream *io.ReadCloser, destination string, gateway string) error {
	// destination is a server address + path (scp-like uri)
	if strings.Contains(destination, ":") {
		logrus.Debugf("Streaming using ssh and untaring remotely")
		serverParts := strings.Split(destination, ":")
		if len(serverParts) != 2 {
			return fmt.Errorf("invalid destination uri, see 'scw cp -h' for usage")
		}

		serverID, err := ctx.API.GetServerID(serverParts[0])
		if err != nil {
			return err
		}

		server, err := ctx.API.GetServer(serverID)
		if err != nil {
			return err
		}

		// remoteCommand is executed on the remote server
		// it streams a tarball raw content
		remoteCommand := []string{"tar"}
		remoteCommand = append(remoteCommand, "-C", serverParts[1])
		if ctx.Getenv("DEBUG") == "1" {
			remoteCommand = append(remoteCommand, "-v")
		}
		remoteCommand = append(remoteCommand, "-xf", "-")

		// Resolve gateway
		if gateway == "" {
			gateway = ctx.Getenv("SCW_GATEWAY")
		}
		if gateway == serverID || gateway == serverParts[0] {
			gateway = ""
		} else {
			gateway, err = api.ResolveGateway(ctx.API, gateway)
			if err != nil {
				return fmt.Errorf("cannot resolve Gateway '%s': %v", gateway, err)
			}
		}

		// execCmd contains the ssh connection + the remoteCommand
		sshCommand := utils.NewSSHExecCmd(server.PublicAddress.IP, server.PrivateIP, false, remoteCommand, gateway)
		logrus.Debugf("Executing: %s", sshCommand)
		spawnDst := exec.Command("ssh", sshCommand.Slice()[1:]...)

		untarInputStream, err := spawnDst.StdinPipe()
		if err != nil {
			return err
		}
		defer untarInputStream.Close()

		// spawnDst.Stderr = ctx.Stderr
		// spawnDst.Stdout = ctx.Stdout

		err = spawnDst.Start()
		if err != nil {
			return err
		}

		_, err = io.Copy(untarInputStream, *sourceStream)
		return err
	}

	// destination is stdout
	if destination == "-" { // stdout
		logrus.Debugf("Writing sourceStream(%v) to ctx.Stdout(%v)", sourceStream, ctx.Stdout)
		_, err := io.Copy(ctx.Stdout, *sourceStream)
		return err
	}

	// destination is a path on localhost
	logrus.Debugf("Untaring to local path: %s", destination)
	err := archive.Untar(*sourceStream, destination, &archive.TarOptions{NoLchown: true})
	return err
}