]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/configs/configload/getter.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / configs / configload / getter.go
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 }