github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/cmd/juju/commands/scp.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package commands 5 6 import ( 7 "fmt" 8 "net" 9 "strings" 10 11 "github.com/juju/cmd" 12 "github.com/juju/utils/ssh" 13 14 "github.com/juju/juju/cmd/modelcmd" 15 ) 16 17 var usageSCPSummary = ` 18 Transfers files to/from a Juju machine.`[1:] 19 20 var usageSCPDetails = ` 21 The usage is for transferring files from the client to a Juju machine. To 22 do the reverse: 23 juju scp [options] [<user>@]<target>:<file> <path> 24 and use quotes when multiple files are involved. 25 The machine is identified by the <target> argument which is either a 'unit 26 name' or a 'machine id'. Both are obtained in the output from `[1:] + "`juju \nstatus`" + `: unit name in the [Units] section and machine id in the [Machines] 27 section. 28 If 'user' is specified then the connection is made to that user account; 29 otherwise, the 'ubuntu' account is used. 30 'file' can be single or multiple files or directories. For directories, 31 you must use the scp option of '-r'. 32 Options specific to scp can be inserted between 'scp' and '[options]' with 33 '-- <scp-options>'. Refer to the scp(1) man page for an explanation of 34 those options. 35 36 Examples: 37 Copy file /var/log/syslog from machine 2 to the client's current working 38 directory: 39 40 juju scp 2:/var/log/syslog . 41 42 Copy directory /var/log/mongodb, recursively, from a mongodb unit 43 to the client's local directory remote-logs: 44 45 juju scp -- -r mongodb/0:/var/log/mongodb/ remote-logs 46 47 Copy file foo.txt, in verbose mode, from the client's current working 48 directory to an apache2 unit of model "mymodel": 49 50 juju scp -- -v -m mymodel foo.txt apache2/1: 51 52 Copy multiple files from the client's current working directory to machine 53 2: 54 55 juju scp file1 file2 2: 56 57 Copy multiple files from the bob user account on machine 3 to the client's 58 current working directory: 59 60 juju scp bob@3:'file1 file2' . 61 62 See also: 63 ssh` 64 65 func newSCPCommand() cmd.Command { 66 return modelcmd.Wrap(&scpCommand{}) 67 } 68 69 // scpCommand is responsible for launching a scp command to copy files to/from remote machine(s) 70 type scpCommand struct { 71 SSHCommon 72 } 73 74 func (c *scpCommand) Info() *cmd.Info { 75 return &cmd.Info{ 76 Name: "scp", 77 Args: "<file> [<user>@]<target>:[<path>]", 78 Purpose: usageSCPSummary, 79 Doc: usageSCPDetails, 80 } 81 } 82 83 func (c *scpCommand) Init(args []string) error { 84 if len(args) < 2 { 85 return fmt.Errorf("at least two arguments required") 86 } 87 c.Args = args 88 return nil 89 } 90 91 // expandArgs takes a list of arguments and looks for ones in the form of 92 // 0:some/path or service/0:some/path, and translates them into 93 // ubuntu@machine:some/path so they can be passed as arguments to scp, and pass 94 // the rest verbatim on to scp 95 func expandArgs(args []string, userHostFromTarget func(string) (string, string, error)) ([]string, error) { 96 outArgs := make([]string, len(args)) 97 for i, arg := range args { 98 v := strings.SplitN(arg, ":", 2) 99 if strings.HasPrefix(arg, "-") || len(v) <= 1 { 100 // Can't be an interesting target, so just pass it along 101 outArgs[i] = arg 102 continue 103 } 104 user, host, err := userHostFromTarget(v[0]) 105 if err != nil { 106 return nil, err 107 } 108 outArgs[i] = user + "@" + net.JoinHostPort(host, v[1]) 109 } 110 return outArgs, nil 111 } 112 113 // Run resolves c.Target to a machine, or host of a unit and 114 // forks ssh with c.Args, if provided. 115 func (c *scpCommand) Run(ctx *cmd.Context) error { 116 var err error 117 c.apiClient, err = c.initAPIClient() 118 if err != nil { 119 return err 120 } 121 defer c.apiClient.Close() 122 123 options, err := c.getSSHOptions(false) 124 if err != nil { 125 return err 126 } 127 args, err := expandArgs(c.Args, c.userHostFromTarget) 128 if err != nil { 129 return err 130 } 131 return ssh.Copy(args, options) 132 }