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
|
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
// vespa-deploy command
// Author: arnej
package deploy
import (
"fmt"
"os"
"os/exec"
"strings"
"github.com/vespa-engine/vespa/client/go/internal/admin/trace"
)
// main entry point for vespa-deploy upload
func RunUpload(opts *Options, args []string) error {
output, err := doUpload(opts, args)
if err != nil {
return err
}
var result UploadResult
code, err := decodeResponse(output, &result)
if err != nil {
return err
}
if code != 200 {
return fmt.Errorf("Request failed. HTTP status code: %d\n%s", code, result.Message)
}
fmt.Println(result.Message)
writeSessionIdToFile(opts.Tenant, result.SessionID)
return nil
}
func doUpload(opts *Options, args []string) (result string, err error) {
sources := makeConfigsourceUrls(opts)
for idx, src := range sources {
if idx > 0 {
fmt.Println(err)
fmt.Println("Retrying with another config server")
}
result, err = uploadToConfigSource(opts, src, args)
if err == nil {
writeConfigsourceUrlUsed(src)
return
}
}
return
}
func uploadToConfigSource(opts *Options, src string, args []string) (string, error) {
if opts.From != "" {
return uploadFrom(opts, src)
}
if len(args) == 0 {
return uploadDirectory(opts, src, ".")
} else {
f, err := os.Open(args[0])
if err != nil {
return "", fmt.Errorf("Command failed. No such directory found: '%s'", args[0])
}
defer f.Close()
st, err := f.Stat()
if err != nil {
return "", err
}
if st.Mode().IsRegular() {
if !strings.HasSuffix(args[0], ".zip") {
return "", fmt.Errorf("Application must be a zip file, was '%s'", args[0])
}
return uploadFile(opts, src, f, args[0])
}
if st.Mode().IsDir() {
return uploadDirectory(opts, src, args[0])
}
return "", fmt.Errorf("Bad arg '%s' with FileMode %v", args[0], st.Mode())
}
}
func uploadFrom(opts *Options, src string) (string, error) {
url := src + pathPrefix(opts)
url = addUrlPropertyFromOption(url, opts.From, "from")
url = addUrlPropertyFromFlag(url, opts.Verbose, "verbose")
trace.Trace("Upload from URL", opts.From, "using", urlWithoutQuery(url))
output, err := curlPost(url, nil)
return output, err
}
func uploadFile(opts *Options, src string, f *os.File, fileName string) (string, error) {
url := src + pathPrefix(opts)
url = addUrlPropertyFromFlag(url, opts.Verbose, "verbose")
fmt.Printf("Uploading application '%s' using %s\n", fileName, urlWithoutQuery(url))
output, err := curlPostZip(url, f)
return output, err
}
func uploadDirectory(opts *Options, src string, dirName string) (string, error) {
url := src + pathPrefix(opts)
url = addUrlPropertyFromFlag(url, opts.Verbose, "verbose")
fmt.Printf("Uploading application '%s' using %s\n", dirName, urlWithoutQuery(url))
tarCmd := tarCommand(dirName)
pipe, err := tarCmd.StdoutPipe()
if err != nil {
return "", err
}
err = tarCmd.Start()
if err != nil {
return "", err
}
output, err := curlPost(url, pipe)
tarCmd.Wait()
return output, err
}
func tarCommand(dirName string) *exec.Cmd {
args := []string{
"-C", dirName,
"--dereference",
"--exclude=.[a-zA-Z0-9]*",
"--exclude=ext",
"-czf", "-",
".",
}
return exec.Command("tar", args...)
}
|