diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/configs/configload/getter.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/configs/configload/getter.go | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/configs/configload/getter.go b/vendor/github.com/hashicorp/terraform/configs/configload/getter.go new file mode 100644 index 0000000..4a3dace --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/configs/configload/getter.go | |||
@@ -0,0 +1,150 @@ | |||
1 | package configload | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "log" | ||
6 | "os" | ||
7 | "path/filepath" | ||
8 | |||
9 | cleanhttp "github.com/hashicorp/go-cleanhttp" | ||
10 | getter "github.com/hashicorp/go-getter" | ||
11 | ) | ||
12 | |||
13 | // We configure our own go-getter detector and getter sets here, because | ||
14 | // the set of sources we support is part of Terraform's documentation and | ||
15 | // so we don't want any new sources introduced in go-getter to sneak in here | ||
16 | // and work even though they aren't documented. This also insulates us from | ||
17 | // any meddling that might be done by other go-getter callers linked into our | ||
18 | // executable. | ||
19 | |||
20 | var goGetterDetectors = []getter.Detector{ | ||
21 | new(getter.GitHubDetector), | ||
22 | new(getter.BitBucketDetector), | ||
23 | new(getter.S3Detector), | ||
24 | new(getter.FileDetector), | ||
25 | } | ||
26 | |||
27 | var goGetterNoDetectors = []getter.Detector{} | ||
28 | |||
29 | var goGetterDecompressors = map[string]getter.Decompressor{ | ||
30 | "bz2": new(getter.Bzip2Decompressor), | ||
31 | "gz": new(getter.GzipDecompressor), | ||
32 | "xz": new(getter.XzDecompressor), | ||
33 | "zip": new(getter.ZipDecompressor), | ||
34 | |||
35 | "tar.bz2": new(getter.TarBzip2Decompressor), | ||
36 | "tar.tbz2": new(getter.TarBzip2Decompressor), | ||
37 | |||
38 | "tar.gz": new(getter.TarGzipDecompressor), | ||
39 | "tgz": new(getter.TarGzipDecompressor), | ||
40 | |||
41 | "tar.xz": new(getter.TarXzDecompressor), | ||
42 | "txz": new(getter.TarXzDecompressor), | ||
43 | } | ||
44 | |||
45 | var goGetterGetters = map[string]getter.Getter{ | ||
46 | "file": new(getter.FileGetter), | ||
47 | "git": new(getter.GitGetter), | ||
48 | "hg": new(getter.HgGetter), | ||
49 | "s3": new(getter.S3Getter), | ||
50 | "http": getterHTTPGetter, | ||
51 | "https": getterHTTPGetter, | ||
52 | } | ||
53 | |||
54 | var getterHTTPClient = cleanhttp.DefaultClient() | ||
55 | |||
56 | var getterHTTPGetter = &getter.HttpGetter{ | ||
57 | Client: getterHTTPClient, | ||
58 | Netrc: true, | ||
59 | } | ||
60 | |||
61 | // A reusingGetter is a helper for the module installer that remembers | ||
62 | // the final resolved addresses of all of the sources it has already been | ||
63 | // asked to install, and will copy from a prior installation directory if | ||
64 | // it has the same resolved source address. | ||
65 | // | ||
66 | // The keys in a reusingGetter are resolved and trimmed source addresses | ||
67 | // (with a scheme always present, and without any "subdir" component), | ||
68 | // and the values are the paths where each source was previously installed. | ||
69 | type reusingGetter map[string]string | ||
70 | |||
71 | // getWithGoGetter retrieves the package referenced in the given address | ||
72 | // into the installation path and then returns the full path to any subdir | ||
73 | // indicated in the address. | ||
74 | // | ||
75 | // The errors returned by this function are those surfaced by the underlying | ||
76 | // go-getter library, which have very inconsistent quality as | ||
77 | // end-user-actionable error messages. At this time we do not have any | ||
78 | // reasonable way to improve these error messages at this layer because | ||
79 | // the underlying errors are not separatelyr recognizable. | ||
80 | func (g reusingGetter) getWithGoGetter(instPath, addr string) (string, error) { | ||
81 | packageAddr, subDir := splitAddrSubdir(addr) | ||
82 | |||
83 | log.Printf("[DEBUG] will download %q to %s", packageAddr, instPath) | ||
84 | |||
85 | realAddr, err := getter.Detect(packageAddr, instPath, getter.Detectors) | ||
86 | if err != nil { | ||
87 | return "", err | ||
88 | } | ||
89 | |||
90 | var realSubDir string | ||
91 | realAddr, realSubDir = splitAddrSubdir(realAddr) | ||
92 | if realSubDir != "" { | ||
93 | subDir = filepath.Join(realSubDir, subDir) | ||
94 | } | ||
95 | |||
96 | if realAddr != packageAddr { | ||
97 | log.Printf("[TRACE] go-getter detectors rewrote %q to %q", packageAddr, realAddr) | ||
98 | } | ||
99 | |||
100 | if prevDir, exists := g[realAddr]; exists { | ||
101 | log.Printf("[TRACE] copying previous install %s to %s", prevDir, instPath) | ||
102 | err := os.Mkdir(instPath, os.ModePerm) | ||
103 | if err != nil { | ||
104 | return "", fmt.Errorf("failed to create directory %s: %s", instPath, err) | ||
105 | } | ||
106 | err = copyDir(instPath, prevDir) | ||
107 | if err != nil { | ||
108 | return "", fmt.Errorf("failed to copy from %s to %s: %s", prevDir, instPath, err) | ||
109 | } | ||
110 | } else { | ||
111 | log.Printf("[TRACE] fetching %q to %q", realAddr, instPath) | ||
112 | client := getter.Client{ | ||
113 | Src: realAddr, | ||
114 | Dst: instPath, | ||
115 | Pwd: instPath, | ||
116 | |||
117 | Mode: getter.ClientModeDir, | ||
118 | |||
119 | Detectors: goGetterNoDetectors, // we already did detection above | ||
120 | Decompressors: goGetterDecompressors, | ||
121 | Getters: goGetterGetters, | ||
122 | } | ||
123 | err = client.Get() | ||
124 | if err != nil { | ||
125 | return "", err | ||
126 | } | ||
127 | // Remember where we installed this so we might reuse this directory | ||
128 | // on subsequent calls to avoid re-downloading. | ||
129 | g[realAddr] = instPath | ||
130 | } | ||
131 | |||
132 | // Our subDir string can contain wildcards until this point, so that | ||
133 | // e.g. a subDir of * can expand to one top-level directory in a .tar.gz | ||
134 | // archive. Now that we've expanded the archive successfully we must | ||
135 | // resolve that into a concrete path. | ||
136 | var finalDir string | ||
137 | if subDir != "" { | ||
138 | finalDir, err = getter.SubdirGlob(instPath, subDir) | ||
139 | log.Printf("[TRACE] expanded %q to %q", subDir, finalDir) | ||
140 | if err != nil { | ||
141 | return "", err | ||
142 | } | ||
143 | } else { | ||
144 | finalDir = instPath | ||
145 | } | ||
146 | |||
147 | // If we got this far then we have apparently succeeded in downloading | ||
148 | // the requested object! | ||
149 | return filepath.Clean(finalDir), nil | ||
150 | } | ||