launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/cmd/juju/scp.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"errors"
     8  	"strings"
     9  
    10  	"launchpad.net/juju-core/cmd"
    11  	"launchpad.net/juju-core/utils/ssh"
    12  )
    13  
    14  // SCPCommand is responsible for launching a scp command to copy files to/from remote machine(s)
    15  type SCPCommand struct {
    16  	SSHCommon
    17  }
    18  
    19  const scpDoc = `
    20  Lauch an scp command to copy files. <to> and <from> are either local
    21  file paths or remote locations of the form <target>:<path>, where
    22  <target> can be either a machine id as listed by "juju status" in the
    23  "machines" section or a unit name as listed in the "services" section.
    24  
    25  Examples
    26  
    27  Copy a single file from machine 2 to the local machine:
    28  
    29      juju scp 2:/var/log/syslog .
    30  
    31  Recursively copy the directory /var/log/mongodb/ on the first mongodb
    32  server to the local directory remote-logs:
    33  
    34      juju scp -- -r mongodb/0:/var/log/mongodb/ remote-logs/
    35  
    36  Copy a local file to the second apache unit of the environment "testing":
    37  
    38      juju scp -e testing foo.txt apache2/1:
    39  `
    40  
    41  func (c *SCPCommand) Info() *cmd.Info {
    42  	return &cmd.Info{
    43  		Name:    "scp",
    44  		Args:    "[-- scp-option...] <from> <to>",
    45  		Purpose: "launch a scp command to copy files to/from remote machine(s)",
    46  		Doc:     scpDoc,
    47  	}
    48  }
    49  
    50  func (c *SCPCommand) Init(args []string) error {
    51  	switch len(args) {
    52  	case 0, 1:
    53  		return errors.New("at least two arguments required")
    54  	default:
    55  		c.Args = args
    56  	}
    57  	return nil
    58  }
    59  
    60  // Run resolves c.Target to a machine, or host of a unit and
    61  // forks ssh with c.Args, if provided.
    62  func (c *SCPCommand) Run(ctx *cmd.Context) error {
    63  	var err error
    64  	c.apiClient, err = c.initAPIClient()
    65  	if err != nil {
    66  		return err
    67  	}
    68  	defer c.apiClient.Close()
    69  
    70  	// translate arguments in the form 0:/somepath or service/0:/somepath into
    71  	// ubuntu@machine:/somepath so they can be presented to scp.
    72  	for i := range c.Args {
    73  		// BUG(dfc) This will not work for IPv6 addresses like 2001:db8::1:2:/somepath.
    74  		if v := strings.SplitN(c.Args[i], ":", 2); len(v) > 1 {
    75  			host, err := c.hostFromTarget(v[0])
    76  			if err != nil {
    77  				return err
    78  			}
    79  			c.Args[i] = "ubuntu@" + host + ":" + v[1]
    80  		}
    81  	}
    82  	return ssh.Copy(c.Args[0], c.Args[1], nil)
    83  }