forked from pkallberg/cx
/
upload.go
140 lines (112 loc) · 3.57 KB
/
upload.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package main
import (
"fmt"
"os"
"runtime"
"github.com/cloud66/cloud66"
"github.com/cloud66/cli"
)
var cmdUpload = &Command{
Run: runUpload,
Build: buildBasicCommand,
Name: "upload",
Flags: []cli.Flag{
cli.StringFlag{
Name: "server",
Usage: "server to upload to",
},
},
NeedsStack: true,
Short: "copies a file from your local computer to the remote server",
Long: `This command will copy a file from your local computer to the remote server.
This command will upload the files to the '/tmp' directory by default.
To copy the file to a specific directory in the remote server,
specify the target directory location in the command line.
This will open the firewall for SSH from your IP address temporaritly (20 minutes), downloads the keys if you don't have them
and starts a SSH session.
You need to have the right access permissions to use this command.
You can use either the server name (ie lion) or the server IP (ie. 123.123.123.123) or the server role (ie. web)
with thie command.
If a role is specified the command will connect to the first server with that role.
Names are case insensitive and will work with the starting characters as well.
This command is only supported on Linux and OS X.
Examples:
$ cx upload -s mystack --server lion /path/to/source/file
$ cx upload -s mystack --server lion /path/to/source/file /path/to/target/directory
$ cx upload -s mystack --server 52.65.34.98 /path/to/source/file
$ cx upload -s mystack --server web /path/to/source/file /path/to/target/directory
`,
}
func runUpload(c *cli.Context) {
if runtime.GOOS == "windows" {
printFatal("Not supported on Windows")
os.Exit(2)
}
stack := mustStack(c)
// args start after stack name
// and check if user specified target directory
var targetDirectory string = ""
if len(c.Args()) < 1 {
cli.ShowCommandHelp(c, "upload")
os.Exit(2)
} else if len(c.Args()) == 2 {
targetDirectory = c.Args()[1]
}
// get the server
serverName := c.String("server")
// get the file path
filePath := c.Args()[0]
servers, err := client.Servers(stack.Uid)
if err != nil {
printFatal(err.Error())
}
server, err := findServer(servers, serverName)
if err != nil {
printError("server not found, please ensure correct server is specified in command.")
os.Exit(2)
}
if server == nil {
printFatal("Server '" + serverName + "' not found")
}
fmt.Printf("Server: %s\n", server.Name)
if targetDirectory == "" {
err = sshToServerToUpload(*server, filePath)
} else {
err = sshToServerToUpload(*server, filePath, targetDirectory)
}
if err != nil {
printFatal(err.Error())
}
}
func sshToServerToUpload(server cloud66.Server, filePath string, targetDirectory ...string) error {
// default target directory
var defaultDir string = "/tmp"
var targetDir string = defaultDir
// if target directory specified
if len(targetDirectory) > 0 {
targetDir = targetDirectory[0]
}
sshFile, err := prepareLocalSshKey(server)
must(err)
// open the firewall
var timeToOpen = 2
fmt.Printf("Opening access to %s...\n", server.Address)
genericRes, err := client.LeaseSync(server.StackUid, nil, &timeToOpen, nil, &server.Uid)
must(err)
if genericRes.Status != true {
printFatal("Unable to open server lease")
}
fmt.Printf("Connecting to %s (%s)...\n", server.Name, server.Address)
return startProgram("scp", []string{
"-i", sshFile,
"-r",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "CheckHostIP=no",
"-o", "StrictHostKeyChecking=no",
"-o", "LogLevel=QUIET",
"-o", "IdentitiesOnly=yes",
"-P", "22",
filePath,
server.UserName + "@" + server.Address + ":" + targetDir,
})
}