Skip to content
This repository was archived by the owner on Jun 11, 2021. It is now read-only.

Commit 41d8457

Browse files
committed
Initial attempt at implementing Terraform / go-getter logic for install
1 parent 5b4be86 commit 41d8457

File tree

1,067 files changed

+580022
-17
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,067 files changed

+580022
-17
lines changed

Gopkg.lock

Lines changed: 336 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@
5353
name = "github.com/otiai10/copy"
5454
version = "v1.0.1"
5555

56+
[[constraint]]
57+
name = "github.com/hashicorp/go-getter"
58+
version = "v1.3.0"
59+
60+
[[constraint]]
61+
name = "github.com/hashicorp/go-cleanhttp"
62+
version = "v0.5.1"
63+
5664
[prune]
5765
go-tests = true
5866
unused-packages = true

cmd/install.go

Lines changed: 108 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,58 @@ import (
3535
jww "github.com/spf13/jwalterweatherman"
3636
"gopkg.in/src-d/go-git.v4"
3737
"gopkg.in/src-d/go-git.v4/plumbing"
38+
39+
cleanhttp "github.com/hashicorp/go-cleanhttp"
40+
getter "github.com/hashicorp/go-getter"
3841
)
3942

43+
// HEAVILY inpired by Terraform's internal getter / module_install code:
44+
// https://github.com/hashicorp/terraform/blob/master/internal/initwd/getter.go
45+
// https://github.com/hashicorp/terraform/blob/master/internal/initwd/module_install.go
46+
47+
var goGetterDetectors = []getter.Detector{
48+
new(getter.GitHubDetector),
49+
new(getter.BitBucketDetector),
50+
new(getter.GCSDetector),
51+
new(getter.S3Detector),
52+
new(getter.FileDetector),
53+
}
54+
55+
var goGetterNoDetectors = []getter.Detector{}
56+
57+
var goGetterDecompressors = map[string]getter.Decompressor{
58+
"bz2": new(getter.Bzip2Decompressor),
59+
"gz": new(getter.GzipDecompressor),
60+
"xz": new(getter.XzDecompressor),
61+
"zip": new(getter.ZipDecompressor),
62+
63+
"tar.bz2": new(getter.TarBzip2Decompressor),
64+
"tar.tbz2": new(getter.TarBzip2Decompressor),
65+
66+
"tar.gz": new(getter.TarGzipDecompressor),
67+
"tgz": new(getter.TarGzipDecompressor),
68+
69+
"tar.xz": new(getter.TarXzDecompressor),
70+
"txz": new(getter.TarXzDecompressor),
71+
}
72+
73+
var goGetterGetters = map[string]getter.Getter{
74+
"file": new(getter.FileGetter),
75+
"gcs": new(getter.GCSGetter),
76+
"git": new(getter.GitGetter),
77+
"hg": new(getter.HgGetter),
78+
"s3": new(getter.S3Getter),
79+
"http": getterHTTPGetter,
80+
"https": getterHTTPGetter,
81+
}
82+
83+
var getterHTTPClient = cleanhttp.DefaultClient()
84+
85+
var getterHTTPGetter = &getter.HttpGetter{
86+
Client: getterHTTPClient,
87+
Netrc: true,
88+
}
89+
4090
var registryBaseURL = "https://registry.terraform.io/v1/modules"
4191
var githubDownloadURLRe = regexp.MustCompile(`https://[^/]+/repos/([^/]+)/([^/]+)/tarball/([^/]+)/.*`)
4292

@@ -68,24 +118,27 @@ func init() {
68118
func getModule(moduleName string, moduleMeta module, wg *sync.WaitGroup) {
69119
defer wg.Done()
70120

71-
moduleSource := moduleMeta.Source
121+
moduleSource, modulePath := splitAddrSubdir(moduleMeta.Source)
122+
72123
moduleVersion := "master"
73124
if len(moduleMeta.Version) > 0 {
74125
moduleVersion = moduleMeta.Version
75126
}
76-
modulePath := moduleMeta.Path
127+
128+
if len(moduleMeta.Path) > 0 {
129+
modulePath = moduleMeta.Path
130+
}
77131

78132
directory := path.Join(VendorDir, moduleName)
79133

80134
switch {
81-
case strings.HasPrefix(moduleSource, "./") || strings.HasPrefix(
82-
moduleSource, "../") || strings.HasPrefix(moduleSource, "/"):
135+
case isLocalSourceAddr(moduleSource):
83136
copyFile(moduleName, moduleSource, directory)
84-
case validRegistry(moduleSource):
137+
case isRegistrySourceAddr(moduleSource):
85138
source, version := getRegistrySource(moduleName, moduleSource, moduleVersion)
86139
gitCheckout(moduleName, source, version, directory)
87-
case IContains(moduleSource, "git"):
88-
gitCheckout(moduleName, moduleSource, moduleVersion, directory)
140+
default:
141+
getWithGoGetter(moduleName, moduleSource, moduleVersion, directory)
89142
}
90143

91144
// If we have a path specified, let's extract it (move and copy stuff).
@@ -100,10 +153,18 @@ func getModule(moduleName string, moduleMeta module, wg *sync.WaitGroup) {
100153
CheckIfError(moduleName, err)
101154
os.RemoveAll(tmpDirectory)
102155
}
103-
// Cleanup .git directoriy
156+
// Cleanup .git directory
104157
os.RemoveAll(path.Join(directory, ".git"))
105158
}
106159

160+
func isRegistrySourceAddr(addr string) bool {
161+
nameRegex := "[0-9A-Za-z](?:[0-9A-Za-z-_]{0,62}[0-9A-Za-z])?"
162+
providerRegex := "[0-9a-z]{1,64}"
163+
registryRegex := regexp.MustCompile(
164+
fmt.Sprintf("^(%s)\\/(%s)\\/(%s)(?:\\/\\/(.*))?$", nameRegex, nameRegex, providerRegex))
165+
return registryRegex.MatchString(addr)
166+
}
167+
107168
func getRegistrySource(name string, source string, version string) (string, string) {
108169
jww.INFO.Printf("[%s] Looking up %s version %s in Terraform registry", name, source, version)
109170
if version == "master" {
@@ -145,12 +206,21 @@ func getRegistrySource(name string, source string, version string) (string, stri
145206
return "", "" // Never reacbhes here
146207
}
147208

148-
func validRegistry(source string) bool {
149-
nameRegex := "[0-9A-Za-z](?:[0-9A-Za-z-_]{0,62}[0-9A-Za-z])?"
150-
providerRegex := "[0-9a-z]{1,64}"
151-
registryRegex := regexp.MustCompile(
152-
fmt.Sprintf("^(%s)\\/(%s)\\/(%s)(?:\\/\\/(.*))?$", nameRegex, nameRegex, providerRegex))
153-
return registryRegex.MatchString(source)
209+
// Handle local modules from relative paths
210+
var localSourcePrefixes = []string{
211+
"./",
212+
"../",
213+
".\\",
214+
"..\\",
215+
}
216+
217+
func isLocalSourceAddr(addr string) bool {
218+
for _, prefix := range localSourcePrefixes {
219+
if strings.HasPrefix(addr, prefix) {
220+
return true
221+
}
222+
}
223+
return false
154224
}
155225

156226
func copyFile(name string, src string, dst string) {
@@ -181,3 +251,27 @@ func gitCheckout(name string, repo string, version string, directory string) {
181251
})
182252
CheckIfError(name, err)
183253
}
254+
255+
func getWithGoGetter(name string, source string, version string, directory string) {
256+
jww.INFO.Printf("[%s] Fetching %s from %s", name, version, source)
257+
258+
client := getter.Client{
259+
Src: source,
260+
Dst: directory,
261+
Pwd: directory,
262+
263+
Mode: getter.ClientModeDir,
264+
265+
Detectors: goGetterNoDetectors, // we already did detection above
266+
Decompressors: goGetterDecompressors,
267+
Getters: goGetterGetters,
268+
}
269+
err := client.Get()
270+
CheckIfError(name, err)
271+
}
272+
273+
// The subDir portion will be returned as empty if no subdir separator
274+
// ("//") is present in the address.
275+
func splitAddrSubdir(addr string) (packageAddr, subDir string) {
276+
return getter.SourceDirSubdir(addr)
277+
}

vendor/cloud.google.com/go/LICENSE

Lines changed: 202 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)