aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/go-getter
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-getter')
-rw-r--r--vendor/github.com/hashicorp/go-getter/LICENSE354
-rw-r--r--vendor/github.com/hashicorp/go-getter/README.md253
-rw-r--r--vendor/github.com/hashicorp/go-getter/appveyor.yml16
-rw-r--r--vendor/github.com/hashicorp/go-getter/client.go335
-rw-r--r--vendor/github.com/hashicorp/go-getter/client_mode.go24
-rw-r--r--vendor/github.com/hashicorp/go-getter/copy_dir.go78
-rw-r--r--vendor/github.com/hashicorp/go-getter/decompress.go29
-rw-r--r--vendor/github.com/hashicorp/go-getter/decompress_bzip2.go45
-rw-r--r--vendor/github.com/hashicorp/go-getter/decompress_gzip.go49
-rw-r--r--vendor/github.com/hashicorp/go-getter/decompress_tbz2.go95
-rw-r--r--vendor/github.com/hashicorp/go-getter/decompress_testing.go134
-rw-r--r--vendor/github.com/hashicorp/go-getter/decompress_tgz.go99
-rw-r--r--vendor/github.com/hashicorp/go-getter/decompress_zip.go96
-rw-r--r--vendor/github.com/hashicorp/go-getter/detect.go97
-rw-r--r--vendor/github.com/hashicorp/go-getter/detect_bitbucket.go66
-rw-r--r--vendor/github.com/hashicorp/go-getter/detect_file.go67
-rw-r--r--vendor/github.com/hashicorp/go-getter/detect_github.go73
-rw-r--r--vendor/github.com/hashicorp/go-getter/detect_s3.go61
-rw-r--r--vendor/github.com/hashicorp/go-getter/folder_storage.go65
-rw-r--r--vendor/github.com/hashicorp/go-getter/get.go139
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_file.go32
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_file_unix.go103
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_file_windows.go120
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_git.go225
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_hg.go131
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_http.go219
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_mock.go52
-rw-r--r--vendor/github.com/hashicorp/go-getter/get_s3.go243
-rw-r--r--vendor/github.com/hashicorp/go-getter/helper/url/url.go14
-rw-r--r--vendor/github.com/hashicorp/go-getter/helper/url/url_unix.go11
-rw-r--r--vendor/github.com/hashicorp/go-getter/helper/url/url_windows.go40
-rw-r--r--vendor/github.com/hashicorp/go-getter/netrc.go67
-rw-r--r--vendor/github.com/hashicorp/go-getter/source.go36
-rw-r--r--vendor/github.com/hashicorp/go-getter/storage.go13
34 files changed, 3481 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-getter/LICENSE b/vendor/github.com/hashicorp/go-getter/LICENSE
new file mode 100644
index 0000000..c33dcc7
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/LICENSE
@@ -0,0 +1,354 @@
1Mozilla Public License, version 2.0
2
31. Definitions
4
51.1. “Contributor”
6
7 means each individual or legal entity that creates, contributes to the
8 creation of, or owns Covered Software.
9
101.2. “Contributor Version”
11
12 means the combination of the Contributions of others (if any) used by a
13 Contributor and that particular Contributor’s Contribution.
14
151.3. “Contribution”
16
17 means Covered Software of a particular Contributor.
18
191.4. “Covered Software”
20
21 means Source Code Form to which the initial Contributor has attached the
22 notice in Exhibit A, the Executable Form of such Source Code Form, and
23 Modifications of such Source Code Form, in each case including portions
24 thereof.
25
261.5. “Incompatible With Secondary Licenses”
27 means
28
29 a. that the initial Contributor has attached the notice described in
30 Exhibit B to the Covered Software; or
31
32 b. that the Covered Software was made available under the terms of version
33 1.1 or earlier of the License, but not also under the terms of a
34 Secondary License.
35
361.6. “Executable Form”
37
38 means any form of the work other than Source Code Form.
39
401.7. “Larger Work”
41
42 means a work that combines Covered Software with other material, in a separate
43 file or files, that is not Covered Software.
44
451.8. “License”
46
47 means this document.
48
491.9. “Licensable”
50
51 means having the right to grant, to the maximum extent possible, whether at the
52 time of the initial grant or subsequently, any and all of the rights conveyed by
53 this License.
54
551.10. “Modifications”
56
57 means any of the following:
58
59 a. any file in Source Code Form that results from an addition to, deletion
60 from, or modification of the contents of Covered Software; or
61
62 b. any new file in Source Code Form that contains any Covered Software.
63
641.11. “Patent Claims” of a Contributor
65
66 means any patent claim(s), including without limitation, method, process,
67 and apparatus claims, in any patent Licensable by such Contributor that
68 would be infringed, but for the grant of the License, by the making,
69 using, selling, offering for sale, having made, import, or transfer of
70 either its Contributions or its Contributor Version.
71
721.12. “Secondary License”
73
74 means either the GNU General Public License, Version 2.0, the GNU Lesser
75 General Public License, Version 2.1, the GNU Affero General Public
76 License, Version 3.0, or any later versions of those licenses.
77
781.13. “Source Code Form”
79
80 means the form of the work preferred for making modifications.
81
821.14. “You” (or “Your”)
83
84 means an individual or a legal entity exercising rights under this
85 License. For legal entities, “You” includes any entity that controls, is
86 controlled by, or is under common control with You. For purposes of this
87 definition, “control” means (a) the power, direct or indirect, to cause
88 the direction or management of such entity, whether by contract or
89 otherwise, or (b) ownership of more than fifty percent (50%) of the
90 outstanding shares or beneficial ownership of such entity.
91
92
932. License Grants and Conditions
94
952.1. Grants
96
97 Each Contributor hereby grants You a world-wide, royalty-free,
98 non-exclusive license:
99
100 a. under intellectual property rights (other than patent or trademark)
101 Licensable by such Contributor to use, reproduce, make available,
102 modify, display, perform, distribute, and otherwise exploit its
103 Contributions, either on an unmodified basis, with Modifications, or as
104 part of a Larger Work; and
105
106 b. under Patent Claims of such Contributor to make, use, sell, offer for
107 sale, have made, import, and otherwise transfer either its Contributions
108 or its Contributor Version.
109
1102.2. Effective Date
111
112 The licenses granted in Section 2.1 with respect to any Contribution become
113 effective for each Contribution on the date the Contributor first distributes
114 such Contribution.
115
1162.3. Limitations on Grant Scope
117
118 The licenses granted in this Section 2 are the only rights granted under this
119 License. No additional rights or licenses will be implied from the distribution
120 or licensing of Covered Software under this License. Notwithstanding Section
121 2.1(b) above, no patent license is granted by a Contributor:
122
123 a. for any code that a Contributor has removed from Covered Software; or
124
125 b. for infringements caused by: (i) Your and any other third party’s
126 modifications of Covered Software, or (ii) the combination of its
127 Contributions with other software (except as part of its Contributor
128 Version); or
129
130 c. under Patent Claims infringed by Covered Software in the absence of its
131 Contributions.
132
133 This License does not grant any rights in the trademarks, service marks, or
134 logos of any Contributor (except as may be necessary to comply with the
135 notice requirements in Section 3.4).
136
1372.4. Subsequent Licenses
138
139 No Contributor makes additional grants as a result of Your choice to
140 distribute the Covered Software under a subsequent version of this License
141 (see Section 10.2) or under the terms of a Secondary License (if permitted
142 under the terms of Section 3.3).
143
1442.5. Representation
145
146 Each Contributor represents that the Contributor believes its Contributions
147 are its original creation(s) or it has sufficient rights to grant the
148 rights to its Contributions conveyed by this License.
149
1502.6. Fair Use
151
152 This License is not intended to limit any rights You have under applicable
153 copyright doctrines of fair use, fair dealing, or other equivalents.
154
1552.7. Conditions
156
157 Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
158 Section 2.1.
159
160
1613. Responsibilities
162
1633.1. Distribution of Source Form
164
165 All distribution of Covered Software in Source Code Form, including any
166 Modifications that You create or to which You contribute, must be under the
167 terms of this License. You must inform recipients that the Source Code Form
168 of the Covered Software is governed by the terms of this License, and how
169 they can obtain a copy of this License. You may not attempt to alter or
170 restrict the recipients’ rights in the Source Code Form.
171
1723.2. Distribution of Executable Form
173
174 If You distribute Covered Software in Executable Form then:
175
176 a. such Covered Software must also be made available in Source Code Form,
177 as described in Section 3.1, and You must inform recipients of the
178 Executable Form how they can obtain a copy of such Source Code Form by
179 reasonable means in a timely manner, at a charge no more than the cost
180 of distribution to the recipient; and
181
182 b. You may distribute such Executable Form under the terms of this License,
183 or sublicense it under different terms, provided that the license for
184 the Executable Form does not attempt to limit or alter the recipients’
185 rights in the Source Code Form under this License.
186
1873.3. Distribution of a Larger Work
188
189 You may create and distribute a Larger Work under terms of Your choice,
190 provided that You also comply with the requirements of this License for the
191 Covered Software. If the Larger Work is a combination of Covered Software
192 with a work governed by one or more Secondary Licenses, and the Covered
193 Software is not Incompatible With Secondary Licenses, this License permits
194 You to additionally distribute such Covered Software under the terms of
195 such Secondary License(s), so that the recipient of the Larger Work may, at
196 their option, further distribute the Covered Software under the terms of
197 either this License or such Secondary License(s).
198
1993.4. Notices
200
201 You may not remove or alter the substance of any license notices (including
202 copyright notices, patent notices, disclaimers of warranty, or limitations
203 of liability) contained within the Source Code Form of the Covered
204 Software, except that You may alter any license notices to the extent
205 required to remedy known factual inaccuracies.
206
2073.5. Application of Additional Terms
208
209 You may choose to offer, and to charge a fee for, warranty, support,
210 indemnity or liability obligations to one or more recipients of Covered
211 Software. However, You may do so only on Your own behalf, and not on behalf
212 of any Contributor. You must make it absolutely clear that any such
213 warranty, support, indemnity, or liability obligation is offered by You
214 alone, and You hereby agree to indemnify every Contributor for any
215 liability incurred by such Contributor as a result of warranty, support,
216 indemnity or liability terms You offer. You may include additional
217 disclaimers of warranty and limitations of liability specific to any
218 jurisdiction.
219
2204. Inability to Comply Due to Statute or Regulation
221
222 If it is impossible for You to comply with any of the terms of this License
223 with respect to some or all of the Covered Software due to statute, judicial
224 order, or regulation then You must: (a) comply with the terms of this License
225 to the maximum extent possible; and (b) describe the limitations and the code
226 they affect. Such description must be placed in a text file included with all
227 distributions of the Covered Software under this License. Except to the
228 extent prohibited by statute or regulation, such description must be
229 sufficiently detailed for a recipient of ordinary skill to be able to
230 understand it.
231
2325. Termination
233
2345.1. The rights granted under this License will terminate automatically if You
235 fail to comply with any of its terms. However, if You become compliant,
236 then the rights granted under this License from a particular Contributor
237 are reinstated (a) provisionally, unless and until such Contributor
238 explicitly and finally terminates Your grants, and (b) on an ongoing basis,
239 if such Contributor fails to notify You of the non-compliance by some
240 reasonable means prior to 60 days after You have come back into compliance.
241 Moreover, Your grants from a particular Contributor are reinstated on an
242 ongoing basis if such Contributor notifies You of the non-compliance by
243 some reasonable means, this is the first time You have received notice of
244 non-compliance with this License from such Contributor, and You become
245 compliant prior to 30 days after Your receipt of the notice.
246
2475.2. If You initiate litigation against any entity by asserting a patent
248 infringement claim (excluding declaratory judgment actions, counter-claims,
249 and cross-claims) alleging that a Contributor Version directly or
250 indirectly infringes any patent, then the rights granted to You by any and
251 all Contributors for the Covered Software under Section 2.1 of this License
252 shall terminate.
253
2545.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
255 license agreements (excluding distributors and resellers) which have been
256 validly granted by You or Your distributors under this License prior to
257 termination shall survive termination.
258
2596. Disclaimer of Warranty
260
261 Covered Software is provided under this License on an “as is” basis, without
262 warranty of any kind, either expressed, implied, or statutory, including,
263 without limitation, warranties that the Covered Software is free of defects,
264 merchantable, fit for a particular purpose or non-infringing. The entire
265 risk as to the quality and performance of the Covered Software is with You.
266 Should any Covered Software prove defective in any respect, You (not any
267 Contributor) assume the cost of any necessary servicing, repair, or
268 correction. This disclaimer of warranty constitutes an essential part of this
269 License. No use of any Covered Software is authorized under this License
270 except under this disclaimer.
271
2727. Limitation of Liability
273
274 Under no circumstances and under no legal theory, whether tort (including
275 negligence), contract, or otherwise, shall any Contributor, or anyone who
276 distributes Covered Software as permitted above, be liable to You for any
277 direct, indirect, special, incidental, or consequential damages of any
278 character including, without limitation, damages for lost profits, loss of
279 goodwill, work stoppage, computer failure or malfunction, or any and all
280 other commercial damages or losses, even if such party shall have been
281 informed of the possibility of such damages. This limitation of liability
282 shall not apply to liability for death or personal injury resulting from such
283 party’s negligence to the extent applicable law prohibits such limitation.
284 Some jurisdictions do not allow the exclusion or limitation of incidental or
285 consequential damages, so this exclusion and limitation may not apply to You.
286
2878. Litigation
288
289 Any litigation relating to this License may be brought only in the courts of
290 a jurisdiction where the defendant maintains its principal place of business
291 and such litigation shall be governed by laws of that jurisdiction, without
292 reference to its conflict-of-law provisions. Nothing in this Section shall
293 prevent a party’s ability to bring cross-claims or counter-claims.
294
2959. Miscellaneous
296
297 This License represents the complete agreement concerning the subject matter
298 hereof. If any provision of this License is held to be unenforceable, such
299 provision shall be reformed only to the extent necessary to make it
300 enforceable. Any law or regulation which provides that the language of a
301 contract shall be construed against the drafter shall not be used to construe
302 this License against a Contributor.
303
304
30510. Versions of the License
306
30710.1. New Versions
308
309 Mozilla Foundation is the license steward. Except as provided in Section
310 10.3, no one other than the license steward has the right to modify or
311 publish new versions of this License. Each version will be given a
312 distinguishing version number.
313
31410.2. Effect of New Versions
315
316 You may distribute the Covered Software under the terms of the version of
317 the License under which You originally received the Covered Software, or
318 under the terms of any subsequent version published by the license
319 steward.
320
32110.3. Modified Versions
322
323 If you create software not governed by this License, and you want to
324 create a new license for such software, you may create and use a modified
325 version of this License if you rename the license and remove any
326 references to the name of the license steward (except to note that such
327 modified license differs from this License).
328
32910.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
330 If You choose to distribute Source Code Form that is Incompatible With
331 Secondary Licenses under the terms of this version of the License, the
332 notice described in Exhibit B of this License must be attached.
333
334Exhibit A - Source Code Form License Notice
335
336 This Source Code Form is subject to the
337 terms of the Mozilla Public License, v.
338 2.0. If a copy of the MPL was not
339 distributed with this file, You can
340 obtain one at
341 http://mozilla.org/MPL/2.0/.
342
343If it is not possible or desirable to put the notice in a particular file, then
344You may include the notice in a location (such as a LICENSE file in a relevant
345directory) where a recipient would be likely to look for such a notice.
346
347You may add additional accurate notices of copyright ownership.
348
349Exhibit B - “Incompatible With Secondary Licenses” Notice
350
351 This Source Code Form is “Incompatible
352 With Secondary Licenses”, as defined by
353 the Mozilla Public License, v. 2.0.
354
diff --git a/vendor/github.com/hashicorp/go-getter/README.md b/vendor/github.com/hashicorp/go-getter/README.md
new file mode 100644
index 0000000..4a0b6a6
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/README.md
@@ -0,0 +1,253 @@
1# go-getter
2
3[![Build Status](http://img.shields.io/travis/hashicorp/go-getter.svg?style=flat-square)][travis]
4[![Build status](https://ci.appveyor.com/api/projects/status/ulq3qr43n62croyq/branch/master?svg=true)][appveyor]
5[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs]
6
7[travis]: http://travis-ci.org/hashicorp/go-getter
8[godocs]: http://godoc.org/github.com/hashicorp/go-getter
9[appveyor]: https://ci.appveyor.com/project/hashicorp/go-getter/branch/master
10
11go-getter is a library for Go (golang) for downloading files or directories
12from various sources using a URL as the primary form of input.
13
14The power of this library is being flexible in being able to download
15from a number of different sources (file paths, Git, HTTP, Mercurial, etc.)
16using a single string as input. This removes the burden of knowing how to
17download from a variety of sources from the implementer.
18
19The concept of a _detector_ automatically turns invalid URLs into proper
20URLs. For example: "github.com/hashicorp/go-getter" would turn into a
21Git URL. Or "./foo" would turn into a file URL. These are extensible.
22
23This library is used by [Terraform](https://terraform.io) for
24downloading modules, [Otto](https://ottoproject.io) for dependencies and
25Appfile imports, and [Nomad](https://nomadproject.io) for downloading
26binaries.
27
28## Installation and Usage
29
30Package documentation can be found on
31[GoDoc](http://godoc.org/github.com/hashicorp/go-getter).
32
33Installation can be done with a normal `go get`:
34
35```
36$ go get github.com/hashicorp/go-getter
37```
38
39go-getter also has a command you can use to test URL strings:
40
41```
42$ go install github.com/hashicorp/go-getter/cmd/go-getter
43...
44
45$ go-getter github.com/foo/bar ./foo
46...
47```
48
49The command is useful for verifying URL structures.
50
51## URL Format
52
53go-getter uses a single string URL as input to download from a variety of
54protocols. go-getter has various "tricks" with this URL to do certain things.
55This section documents the URL format.
56
57### Supported Protocols and Detectors
58
59**Protocols** are used to download files/directories using a specific
60mechanism. Example protocols are Git and HTTP.
61
62**Detectors** are used to transform a valid or invalid URL into another
63URL if it matches a certain pattern. Example: "github.com/user/repo" is
64automatically transformed into a fully valid Git URL. This allows go-getter
65to be very user friendly.
66
67go-getter out of the box supports the following protocols. Additional protocols
68can be augmented at runtime by implementing the `Getter` interface.
69
70 * Local files
71 * Git
72 * Mercurial
73 * HTTP
74 * Amazon S3
75
76In addition to the above protocols, go-getter has what are called "detectors."
77These take a URL and attempt to automatically choose the best protocol for
78it, which might involve even changing the protocol. The following detection
79is built-in by default:
80
81 * File paths such as "./foo" are automatically changed to absolute
82 file URLs.
83 * GitHub URLs, such as "github.com/mitchellh/vagrant" are automatically
84 changed to Git protocol over HTTP.
85 * BitBucket URLs, such as "bitbucket.org/mitchellh/vagrant" are automatically
86 changed to a Git or mercurial protocol using the BitBucket API.
87
88### Forced Protocol
89
90In some cases, the protocol to use is ambiguous depending on the source
91URL. For example, "http://github.com/mitchellh/vagrant.git" could reference
92an HTTP URL or a Git URL. Forced protocol syntax is used to disambiguate this
93URL.
94
95Forced protocol can be done by prefixing the URL with the protocol followed
96by double colons. For example: `git::http://github.com/mitchellh/vagrant.git`
97would download the given HTTP URL using the Git protocol.
98
99Forced protocols will also override any detectors.
100
101In the absense of a forced protocol, detectors may be run on the URL, transforming
102the protocol anyways. The above example would've used the Git protocol either
103way since the Git detector would've detected it was a GitHub URL.
104
105### Protocol-Specific Options
106
107Each protocol can support protocol-specific options to configure that
108protocol. For example, the `git` protocol supports specifying a `ref`
109query parameter that tells it what ref to checkout for that Git
110repository.
111
112The options are specified as query parameters on the URL (or URL-like string)
113given to go-getter. Using the Git example above, the URL below is a valid
114input to go-getter:
115
116 github.com/hashicorp/go-getter?ref=abcd1234
117
118The protocol-specific options are documented below the URL format
119section. But because they are part of the URL, we point it out here so
120you know they exist.
121
122### Checksumming
123
124For file downloads of any protocol, go-getter can automatically verify
125a checksum for you. Note that checksumming only works for downloading files,
126not directories, but checksumming will work for any protocol.
127
128To checksum a file, append a `checksum` query parameter to the URL.
129The paramter value should be in the format of `type:value`, where
130type is "md5", "sha1", "sha256", or "sha512". The "value" should be
131the actual checksum value. go-getter will parse out this query parameter
132automatically and use it to verify the checksum. An example URL
133is shown below:
134
135```
136./foo.txt?checksum=md5:b7d96c89d09d9e204f5fedc4d5d55b21
137```
138
139The checksum query parameter is never sent to the backend protocol
140implementation. It is used at a higher level by go-getter itself.
141
142### Unarchiving
143
144go-getter will automatically unarchive files into a file or directory
145based on the extension of the file being requested (over any protocol).
146This works for both file and directory downloads.
147
148go-getter looks for an `archive` query parameter to specify the format of
149the archive. If this isn't specified, go-getter will use the extension of
150the path to see if it appears archived. Unarchiving can be explicitly
151disabled by setting the `archive` query parameter to `false`.
152
153The following archive formats are supported:
154
155 * `tar.gz` and `tgz`
156 * `tar.bz2` and `tbz2`
157 * `zip`
158 * `gz`
159 * `bz2`
160
161For example, an example URL is shown below:
162
163```
164./foo.zip
165```
166
167This will automatically be inferred to be a ZIP file and will be extracted.
168You can also be explicit about the archive type:
169
170```
171./some/other/path?archive=zip
172```
173
174And finally, you can disable archiving completely:
175
176```
177./some/path?archive=false
178```
179
180You can combine unarchiving with the other features of go-getter such
181as checksumming. The special `archive` query parameter will be removed
182from the URL before going to the final protocol downloader.
183
184## Protocol-Specific Options
185
186This section documents the protocol-specific options that can be specified
187for go-getter. These options should be appended to the input as normal query
188parameters. Depending on the usage of go-getter, applications may provide
189alternate ways of inputting options. For example, [Nomad](https://www.nomadproject.io)
190provides a nice options block for specifying options rather than in the URL.
191
192## General (All Protocols)
193
194The options below are available to all protocols:
195
196 * `archive` - The archive format to use to unarchive this file, or "" (empty
197 string) to disable unarchiving. For more details, see the complete section
198 on archive support above.
199
200 * `checksum` - Checksum to verify the downloaded file or archive. See
201 the entire section on checksumming above for format and more details.
202
203### Local Files (`file`)
204
205None
206
207### Git (`git`)
208
209 * `ref` - The Git ref to checkout. This is a ref, so it can point to
210 a commit SHA, a branch name, etc. If it is a named ref such as a branch
211 name, go-getter will update it to the latest on each get.
212
213 * `sshkey` - An SSH private key to use during clones. The provided key must
214 be a base64-encoded string. For example, to generate a suitable `sshkey`
215 from a private key file on disk, you would run `base64 -w0 <file>`.
216
217 **Note**: Git 2.3+ is required to use this feature.
218
219### Mercurial (`hg`)
220
221 * `rev` - The Mercurial revision to checkout.
222
223### HTTP (`http`)
224
225None
226
227### S3 (`s3`)
228
229S3 takes various access configurations in the URL. Note that it will also
230read these from standard AWS environment variables if they're set. If
231the query parameters are present, these take priority.
232
233 * `aws_access_key_id` - AWS access key.
234 * `aws_access_key_secret` - AWS access key secret.
235 * `aws_access_token` - AWS access token if this is being used.
236
237#### Using IAM Instance Profiles with S3
238
239If you use go-getter and want to use an EC2 IAM Instance Profile to avoid
240using credentials, then just omit these and the profile, if available will
241be used automatically.
242
243#### S3 Bucket Examples
244
245S3 has several addressing schemes used to reference your bucket. These are
246listed here: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro
247
248Some examples for these addressing schemes:
249- s3::https://s3.amazonaws.com/bucket/foo
250- s3::https://s3-eu-west-1.amazonaws.com/bucket/foo
251- bucket.s3.amazonaws.com/foo
252- bucket.s3-eu-west-1.amazonaws.com/foo/bar
253
diff --git a/vendor/github.com/hashicorp/go-getter/appveyor.yml b/vendor/github.com/hashicorp/go-getter/appveyor.yml
new file mode 100644
index 0000000..159dad4
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/appveyor.yml
@@ -0,0 +1,16 @@
1version: "build-{branch}-{build}"
2image: Visual Studio 2015
3clone_folder: c:\gopath\github.com\hashicorp\go-getter
4environment:
5 GOPATH: c:\gopath
6install:
7- cmd: >-
8 echo %Path%
9
10 go version
11
12 go env
13
14 go get -d -v -t ./...
15build_script:
16- cmd: go test -v ./...
diff --git a/vendor/github.com/hashicorp/go-getter/client.go b/vendor/github.com/hashicorp/go-getter/client.go
new file mode 100644
index 0000000..876812a
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/client.go
@@ -0,0 +1,335 @@
1package getter
2
3import (
4 "bytes"
5 "crypto/md5"
6 "crypto/sha1"
7 "crypto/sha256"
8 "crypto/sha512"
9 "encoding/hex"
10 "fmt"
11 "hash"
12 "io"
13 "io/ioutil"
14 "os"
15 "path/filepath"
16 "strconv"
17 "strings"
18
19 urlhelper "github.com/hashicorp/go-getter/helper/url"
20)
21
22// Client is a client for downloading things.
23//
24// Top-level functions such as Get are shortcuts for interacting with a client.
25// Using a client directly allows more fine-grained control over how downloading
26// is done, as well as customizing the protocols supported.
27type Client struct {
28 // Src is the source URL to get.
29 //
30 // Dst is the path to save the downloaded thing as. If Dir is set to
31 // true, then this should be a directory. If the directory doesn't exist,
32 // it will be created for you.
33 //
34 // Pwd is the working directory for detection. If this isn't set, some
35 // detection may fail. Client will not default pwd to the current
36 // working directory for security reasons.
37 Src string
38 Dst string
39 Pwd string
40
41 // Mode is the method of download the client will use. See ClientMode
42 // for documentation.
43 Mode ClientMode
44
45 // Detectors is the list of detectors that are tried on the source.
46 // If this is nil, then the default Detectors will be used.
47 Detectors []Detector
48
49 // Decompressors is the map of decompressors supported by this client.
50 // If this is nil, then the default value is the Decompressors global.
51 Decompressors map[string]Decompressor
52
53 // Getters is the map of protocols supported by this client. If this
54 // is nil, then the default Getters variable will be used.
55 Getters map[string]Getter
56
57 // Dir, if true, tells the Client it is downloading a directory (versus
58 // a single file). This distinction is necessary since filenames and
59 // directory names follow the same format so disambiguating is impossible
60 // without knowing ahead of time.
61 //
62 // WARNING: deprecated. If Mode is set, that will take precedence.
63 Dir bool
64}
65
66// Get downloads the configured source to the destination.
67func (c *Client) Get() error {
68 // Store this locally since there are cases we swap this
69 mode := c.Mode
70 if mode == ClientModeInvalid {
71 if c.Dir {
72 mode = ClientModeDir
73 } else {
74 mode = ClientModeFile
75 }
76 }
77
78 // Default decompressor value
79 decompressors := c.Decompressors
80 if decompressors == nil {
81 decompressors = Decompressors
82 }
83
84 // Detect the URL. This is safe if it is already detected.
85 detectors := c.Detectors
86 if detectors == nil {
87 detectors = Detectors
88 }
89 src, err := Detect(c.Src, c.Pwd, detectors)
90 if err != nil {
91 return err
92 }
93
94 // Determine if we have a forced protocol, i.e. "git::http://..."
95 force, src := getForcedGetter(src)
96
97 // If there is a subdir component, then we download the root separately
98 // and then copy over the proper subdir.
99 var realDst string
100 dst := c.Dst
101 src, subDir := SourceDirSubdir(src)
102 if subDir != "" {
103 tmpDir, err := ioutil.TempDir("", "tf")
104 if err != nil {
105 return err
106 }
107 if err := os.RemoveAll(tmpDir); err != nil {
108 return err
109 }
110 defer os.RemoveAll(tmpDir)
111
112 realDst = dst
113 dst = tmpDir
114 }
115
116 u, err := urlhelper.Parse(src)
117 if err != nil {
118 return err
119 }
120 if force == "" {
121 force = u.Scheme
122 }
123
124 getters := c.Getters
125 if getters == nil {
126 getters = Getters
127 }
128
129 g, ok := getters[force]
130 if !ok {
131 return fmt.Errorf(
132 "download not supported for scheme '%s'", force)
133 }
134
135 // We have magic query parameters that we use to signal different features
136 q := u.Query()
137
138 // Determine if we have an archive type
139 archiveV := q.Get("archive")
140 if archiveV != "" {
141 // Delete the paramter since it is a magic parameter we don't
142 // want to pass on to the Getter
143 q.Del("archive")
144 u.RawQuery = q.Encode()
145
146 // If we can parse the value as a bool and it is false, then
147 // set the archive to "-" which should never map to a decompressor
148 if b, err := strconv.ParseBool(archiveV); err == nil && !b {
149 archiveV = "-"
150 }
151 }
152 if archiveV == "" {
153 // We don't appear to... but is it part of the filename?
154 matchingLen := 0
155 for k, _ := range decompressors {
156 if strings.HasSuffix(u.Path, "."+k) && len(k) > matchingLen {
157 archiveV = k
158 matchingLen = len(k)
159 }
160 }
161 }
162
163 // If we have a decompressor, then we need to change the destination
164 // to download to a temporary path. We unarchive this into the final,
165 // real path.
166 var decompressDst string
167 var decompressDir bool
168 decompressor := decompressors[archiveV]
169 if decompressor != nil {
170 // Create a temporary directory to store our archive. We delete
171 // this at the end of everything.
172 td, err := ioutil.TempDir("", "getter")
173 if err != nil {
174 return fmt.Errorf(
175 "Error creating temporary directory for archive: %s", err)
176 }
177 defer os.RemoveAll(td)
178
179 // Swap the download directory to be our temporary path and
180 // store the old values.
181 decompressDst = dst
182 decompressDir = mode != ClientModeFile
183 dst = filepath.Join(td, "archive")
184 mode = ClientModeFile
185 }
186
187 // Determine if we have a checksum
188 var checksumHash hash.Hash
189 var checksumValue []byte
190 if v := q.Get("checksum"); v != "" {
191 // Delete the query parameter if we have it.
192 q.Del("checksum")
193 u.RawQuery = q.Encode()
194
195 // Determine the checksum hash type
196 checksumType := ""
197 idx := strings.Index(v, ":")
198 if idx > -1 {
199 checksumType = v[:idx]
200 }
201 switch checksumType {
202 case "md5":
203 checksumHash = md5.New()
204 case "sha1":
205 checksumHash = sha1.New()
206 case "sha256":
207 checksumHash = sha256.New()
208 case "sha512":
209 checksumHash = sha512.New()
210 default:
211 return fmt.Errorf(
212 "unsupported checksum type: %s", checksumType)
213 }
214
215 // Get the remainder of the value and parse it into bytes
216 b, err := hex.DecodeString(v[idx+1:])
217 if err != nil {
218 return fmt.Errorf("invalid checksum: %s", err)
219 }
220
221 // Set our value
222 checksumValue = b
223 }
224
225 if mode == ClientModeAny {
226 // Ask the getter which client mode to use
227 mode, err = g.ClientMode(u)
228 if err != nil {
229 return err
230 }
231
232 // Destination is the base name of the URL path in "any" mode when
233 // a file source is detected.
234 if mode == ClientModeFile {
235 dst = filepath.Join(dst, filepath.Base(u.Path))
236 }
237 }
238
239 // If we're not downloading a directory, then just download the file
240 // and return.
241 if mode == ClientModeFile {
242 err := g.GetFile(dst, u)
243 if err != nil {
244 return err
245 }
246
247 if checksumHash != nil {
248 if err := checksum(dst, checksumHash, checksumValue); err != nil {
249 return err
250 }
251 }
252
253 if decompressor != nil {
254 // We have a decompressor, so decompress the current destination
255 // into the final destination with the proper mode.
256 err := decompressor.Decompress(decompressDst, dst, decompressDir)
257 if err != nil {
258 return err
259 }
260
261 // Swap the information back
262 dst = decompressDst
263 if decompressDir {
264 mode = ClientModeAny
265 } else {
266 mode = ClientModeFile
267 }
268 }
269
270 // We check the dir value again because it can be switched back
271 // if we were unarchiving. If we're still only Get-ing a file, then
272 // we're done.
273 if mode == ClientModeFile {
274 return nil
275 }
276 }
277
278 // If we're at this point we're either downloading a directory or we've
279 // downloaded and unarchived a directory and we're just checking subdir.
280 // In the case we have a decompressor we don't Get because it was Get
281 // above.
282 if decompressor == nil {
283 // If we're getting a directory, then this is an error. You cannot
284 // checksum a directory. TODO: test
285 if checksumHash != nil {
286 return fmt.Errorf(
287 "checksum cannot be specified for directory download")
288 }
289
290 // We're downloading a directory, which might require a bit more work
291 // if we're specifying a subdir.
292 err := g.Get(dst, u)
293 if err != nil {
294 err = fmt.Errorf("error downloading '%s': %s", src, err)
295 return err
296 }
297 }
298
299 // If we have a subdir, copy that over
300 if subDir != "" {
301 if err := os.RemoveAll(realDst); err != nil {
302 return err
303 }
304 if err := os.MkdirAll(realDst, 0755); err != nil {
305 return err
306 }
307
308 return copyDir(realDst, filepath.Join(dst, subDir), false)
309 }
310
311 return nil
312}
313
314// checksum is a simple method to compute the checksum of a source file
315// and compare it to the given expected value.
316func checksum(source string, h hash.Hash, v []byte) error {
317 f, err := os.Open(source)
318 if err != nil {
319 return fmt.Errorf("Failed to open file for checksum: %s", err)
320 }
321 defer f.Close()
322
323 if _, err := io.Copy(h, f); err != nil {
324 return fmt.Errorf("Failed to hash: %s", err)
325 }
326
327 if actual := h.Sum(nil); !bytes.Equal(actual, v) {
328 return fmt.Errorf(
329 "Checksums did not match.\nExpected: %s\nGot: %s",
330 hex.EncodeToString(v),
331 hex.EncodeToString(actual))
332 }
333
334 return nil
335}
diff --git a/vendor/github.com/hashicorp/go-getter/client_mode.go b/vendor/github.com/hashicorp/go-getter/client_mode.go
new file mode 100644
index 0000000..7f02509
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/client_mode.go
@@ -0,0 +1,24 @@
1package getter
2
3// ClientMode is the mode that the client operates in.
4type ClientMode uint
5
6const (
7 ClientModeInvalid ClientMode = iota
8
9 // ClientModeAny downloads anything it can. In this mode, dst must
10 // be a directory. If src is a file, it is saved into the directory
11 // with the basename of the URL. If src is a directory or archive,
12 // it is unpacked directly into dst.
13 ClientModeAny
14
15 // ClientModeFile downloads a single file. In this mode, dst must
16 // be a file path (doesn't have to exist). src must point to a single
17 // file. It is saved as dst.
18 ClientModeFile
19
20 // ClientModeDir downloads a directory. In this mode, dst must be
21 // a directory path (doesn't have to exist). src must point to an
22 // archive or directory (such as in s3).
23 ClientModeDir
24)
diff --git a/vendor/github.com/hashicorp/go-getter/copy_dir.go b/vendor/github.com/hashicorp/go-getter/copy_dir.go
new file mode 100644
index 0000000..2f58e8a
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/copy_dir.go
@@ -0,0 +1,78 @@
1package getter
2
3import (
4 "io"
5 "os"
6 "path/filepath"
7 "strings"
8)
9
10// copyDir copies the src directory contents into dst. Both directories
11// should already exist.
12//
13// If ignoreDot is set to true, then dot-prefixed files/folders are ignored.
14func copyDir(dst string, src string, ignoreDot bool) error {
15 src, err := filepath.EvalSymlinks(src)
16 if err != nil {
17 return err
18 }
19
20 walkFn := func(path string, info os.FileInfo, err error) error {
21 if err != nil {
22 return err
23 }
24 if path == src {
25 return nil
26 }
27
28 if ignoreDot && strings.HasPrefix(filepath.Base(path), ".") {
29 // Skip any dot files
30 if info.IsDir() {
31 return filepath.SkipDir
32 } else {
33 return nil
34 }
35 }
36
37 // The "path" has the src prefixed to it. We need to join our
38 // destination with the path without the src on it.
39 dstPath := filepath.Join(dst, path[len(src):])
40
41 // If we have a directory, make that subdirectory, then continue
42 // the walk.
43 if info.IsDir() {
44 if path == filepath.Join(src, dst) {
45 // dst is in src; don't walk it.
46 return nil
47 }
48
49 if err := os.MkdirAll(dstPath, 0755); err != nil {
50 return err
51 }
52
53 return nil
54 }
55
56 // If we have a file, copy the contents.
57 srcF, err := os.Open(path)
58 if err != nil {
59 return err
60 }
61 defer srcF.Close()
62
63 dstF, err := os.Create(dstPath)
64 if err != nil {
65 return err
66 }
67 defer dstF.Close()
68
69 if _, err := io.Copy(dstF, srcF); err != nil {
70 return err
71 }
72
73 // Chmod it
74 return os.Chmod(dstPath, info.Mode())
75 }
76
77 return filepath.Walk(src, walkFn)
78}
diff --git a/vendor/github.com/hashicorp/go-getter/decompress.go b/vendor/github.com/hashicorp/go-getter/decompress.go
new file mode 100644
index 0000000..d18174c
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/decompress.go
@@ -0,0 +1,29 @@
1package getter
2
3// Decompressor defines the interface that must be implemented to add
4// support for decompressing a type.
5type Decompressor interface {
6 // Decompress should decompress src to dst. dir specifies whether dst
7 // is a directory or single file. src is guaranteed to be a single file
8 // that exists. dst is not guaranteed to exist already.
9 Decompress(dst, src string, dir bool) error
10}
11
12// Decompressors is the mapping of extension to the Decompressor implementation
13// that will decompress that extension/type.
14var Decompressors map[string]Decompressor
15
16func init() {
17 tbzDecompressor := new(TarBzip2Decompressor)
18 tgzDecompressor := new(TarGzipDecompressor)
19
20 Decompressors = map[string]Decompressor{
21 "bz2": new(Bzip2Decompressor),
22 "gz": new(GzipDecompressor),
23 "tar.bz2": tbzDecompressor,
24 "tar.gz": tgzDecompressor,
25 "tbz2": tbzDecompressor,
26 "tgz": tgzDecompressor,
27 "zip": new(ZipDecompressor),
28 }
29}
diff --git a/vendor/github.com/hashicorp/go-getter/decompress_bzip2.go b/vendor/github.com/hashicorp/go-getter/decompress_bzip2.go
new file mode 100644
index 0000000..339f4cf
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/decompress_bzip2.go
@@ -0,0 +1,45 @@
1package getter
2
3import (
4 "compress/bzip2"
5 "fmt"
6 "io"
7 "os"
8 "path/filepath"
9)
10
11// Bzip2Decompressor is an implementation of Decompressor that can
12// decompress bz2 files.
13type Bzip2Decompressor struct{}
14
15func (d *Bzip2Decompressor) Decompress(dst, src string, dir bool) error {
16 // Directory isn't supported at all
17 if dir {
18 return fmt.Errorf("bzip2-compressed files can only unarchive to a single file")
19 }
20
21 // If we're going into a directory we should make that first
22 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
23 return err
24 }
25
26 // File first
27 f, err := os.Open(src)
28 if err != nil {
29 return err
30 }
31 defer f.Close()
32
33 // Bzip2 compression is second
34 bzipR := bzip2.NewReader(f)
35
36 // Copy it out
37 dstF, err := os.Create(dst)
38 if err != nil {
39 return err
40 }
41 defer dstF.Close()
42
43 _, err = io.Copy(dstF, bzipR)
44 return err
45}
diff --git a/vendor/github.com/hashicorp/go-getter/decompress_gzip.go b/vendor/github.com/hashicorp/go-getter/decompress_gzip.go
new file mode 100644
index 0000000..2001054
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/decompress_gzip.go
@@ -0,0 +1,49 @@
1package getter
2
3import (
4 "compress/gzip"
5 "fmt"
6 "io"
7 "os"
8 "path/filepath"
9)
10
11// GzipDecompressor is an implementation of Decompressor that can
12// decompress bz2 files.
13type GzipDecompressor struct{}
14
15func (d *GzipDecompressor) Decompress(dst, src string, dir bool) error {
16 // Directory isn't supported at all
17 if dir {
18 return fmt.Errorf("gzip-compressed files can only unarchive to a single file")
19 }
20
21 // If we're going into a directory we should make that first
22 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
23 return err
24 }
25
26 // File first
27 f, err := os.Open(src)
28 if err != nil {
29 return err
30 }
31 defer f.Close()
32
33 // gzip compression is second
34 gzipR, err := gzip.NewReader(f)
35 if err != nil {
36 return err
37 }
38 defer gzipR.Close()
39
40 // Copy it out
41 dstF, err := os.Create(dst)
42 if err != nil {
43 return err
44 }
45 defer dstF.Close()
46
47 _, err = io.Copy(dstF, gzipR)
48 return err
49}
diff --git a/vendor/github.com/hashicorp/go-getter/decompress_tbz2.go b/vendor/github.com/hashicorp/go-getter/decompress_tbz2.go
new file mode 100644
index 0000000..c46ed44
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/decompress_tbz2.go
@@ -0,0 +1,95 @@
1package getter
2
3import (
4 "archive/tar"
5 "compress/bzip2"
6 "fmt"
7 "io"
8 "os"
9 "path/filepath"
10)
11
12// TarBzip2Decompressor is an implementation of Decompressor that can
13// decompress tar.bz2 files.
14type TarBzip2Decompressor struct{}
15
16func (d *TarBzip2Decompressor) Decompress(dst, src string, dir bool) error {
17 // If we're going into a directory we should make that first
18 mkdir := dst
19 if !dir {
20 mkdir = filepath.Dir(dst)
21 }
22 if err := os.MkdirAll(mkdir, 0755); err != nil {
23 return err
24 }
25
26 // File first
27 f, err := os.Open(src)
28 if err != nil {
29 return err
30 }
31 defer f.Close()
32
33 // Bzip2 compression is second
34 bzipR := bzip2.NewReader(f)
35
36 // Once bzip decompressed we have a tar format
37 tarR := tar.NewReader(bzipR)
38 done := false
39 for {
40 hdr, err := tarR.Next()
41 if err == io.EOF {
42 if !done {
43 // Empty archive
44 return fmt.Errorf("empty archive: %s", src)
45 }
46
47 return nil
48 }
49 if err != nil {
50 return err
51 }
52
53 path := dst
54 if dir {
55 path = filepath.Join(path, hdr.Name)
56 }
57
58 if hdr.FileInfo().IsDir() {
59 if dir {
60 return fmt.Errorf("expected a single file: %s", src)
61 }
62
63 // A directory, just make the directory and continue unarchiving...
64 if err := os.MkdirAll(path, 0755); err != nil {
65 return err
66 }
67
68 continue
69 }
70
71 // We have a file. If we already decoded, then it is an error
72 if !dir && done {
73 return fmt.Errorf("expected a single file, got multiple: %s", src)
74 }
75
76 // Mark that we're done so future in single file mode errors
77 done = true
78
79 // Open the file for writing
80 dstF, err := os.Create(path)
81 if err != nil {
82 return err
83 }
84 _, err = io.Copy(dstF, tarR)
85 dstF.Close()
86 if err != nil {
87 return err
88 }
89
90 // Chmod the file
91 if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil {
92 return err
93 }
94 }
95}
diff --git a/vendor/github.com/hashicorp/go-getter/decompress_testing.go b/vendor/github.com/hashicorp/go-getter/decompress_testing.go
new file mode 100644
index 0000000..686d6c2
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/decompress_testing.go
@@ -0,0 +1,134 @@
1package getter
2
3import (
4 "crypto/md5"
5 "encoding/hex"
6 "io"
7 "io/ioutil"
8 "os"
9 "path/filepath"
10 "reflect"
11 "runtime"
12 "sort"
13 "strings"
14 "testing"
15)
16
17// TestDecompressCase is a single test case for testing decompressors
18type TestDecompressCase struct {
19 Input string // Input is the complete path to the input file
20 Dir bool // Dir is whether or not we're testing directory mode
21 Err bool // Err is whether we expect an error or not
22 DirList []string // DirList is the list of files for Dir mode
23 FileMD5 string // FileMD5 is the expected MD5 for a single file
24}
25
26// TestDecompressor is a helper function for testing generic decompressors.
27func TestDecompressor(t *testing.T, d Decompressor, cases []TestDecompressCase) {
28 for _, tc := range cases {
29 t.Logf("Testing: %s", tc.Input)
30
31 // Temporary dir to store stuff
32 td, err := ioutil.TempDir("", "getter")
33 if err != nil {
34 t.Fatalf("err: %s", err)
35 }
36
37 // Destination is always joining result so that we have a new path
38 dst := filepath.Join(td, "subdir", "result")
39
40 // We use a function so defers work
41 func() {
42 defer os.RemoveAll(td)
43
44 // Decompress
45 err := d.Decompress(dst, tc.Input, tc.Dir)
46 if (err != nil) != tc.Err {
47 t.Fatalf("err %s: %s", tc.Input, err)
48 }
49 if tc.Err {
50 return
51 }
52
53 // If it isn't a directory, then check for a single file
54 if !tc.Dir {
55 fi, err := os.Stat(dst)
56 if err != nil {
57 t.Fatalf("err %s: %s", tc.Input, err)
58 }
59 if fi.IsDir() {
60 t.Fatalf("err %s: expected file, got directory", tc.Input)
61 }
62 if tc.FileMD5 != "" {
63 actual := testMD5(t, dst)
64 expected := tc.FileMD5
65 if actual != expected {
66 t.Fatalf("err %s: expected MD5 %s, got %s", tc.Input, expected, actual)
67 }
68 }
69
70 return
71 }
72
73 // Convert expected for windows
74 expected := tc.DirList
75 if runtime.GOOS == "windows" {
76 for i, v := range expected {
77 expected[i] = strings.Replace(v, "/", "\\", -1)
78 }
79 }
80
81 // Directory, check for the correct contents
82 actual := testListDir(t, dst)
83 if !reflect.DeepEqual(actual, expected) {
84 t.Fatalf("bad %s\n\n%#v\n\n%#v", tc.Input, actual, expected)
85 }
86 }()
87 }
88}
89
90func testListDir(t *testing.T, path string) []string {
91 var result []string
92 err := filepath.Walk(path, func(sub string, info os.FileInfo, err error) error {
93 if err != nil {
94 return err
95 }
96
97 sub = strings.TrimPrefix(sub, path)
98 if sub == "" {
99 return nil
100 }
101 sub = sub[1:] // Trim the leading path sep.
102
103 // If it is a dir, add trailing sep
104 if info.IsDir() {
105 sub += "/"
106 }
107
108 result = append(result, sub)
109 return nil
110 })
111 if err != nil {
112 t.Fatalf("err: %s", err)
113 }
114
115 sort.Strings(result)
116 return result
117}
118
119func testMD5(t *testing.T, path string) string {
120 f, err := os.Open(path)
121 if err != nil {
122 t.Fatalf("err: %s", err)
123 }
124 defer f.Close()
125
126 h := md5.New()
127 _, err = io.Copy(h, f)
128 if err != nil {
129 t.Fatalf("err: %s", err)
130 }
131
132 result := h.Sum(nil)
133 return hex.EncodeToString(result)
134}
diff --git a/vendor/github.com/hashicorp/go-getter/decompress_tgz.go b/vendor/github.com/hashicorp/go-getter/decompress_tgz.go
new file mode 100644
index 0000000..e8b1c31
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/decompress_tgz.go
@@ -0,0 +1,99 @@
1package getter
2
3import (
4 "archive/tar"
5 "compress/gzip"
6 "fmt"
7 "io"
8 "os"
9 "path/filepath"
10)
11
12// TarGzipDecompressor is an implementation of Decompressor that can
13// decompress tar.gzip files.
14type TarGzipDecompressor struct{}
15
16func (d *TarGzipDecompressor) Decompress(dst, src string, dir bool) error {
17 // If we're going into a directory we should make that first
18 mkdir := dst
19 if !dir {
20 mkdir = filepath.Dir(dst)
21 }
22 if err := os.MkdirAll(mkdir, 0755); err != nil {
23 return err
24 }
25
26 // File first
27 f, err := os.Open(src)
28 if err != nil {
29 return err
30 }
31 defer f.Close()
32
33 // Gzip compression is second
34 gzipR, err := gzip.NewReader(f)
35 if err != nil {
36 return fmt.Errorf("Error opening a gzip reader for %s: %s", src, err)
37 }
38 defer gzipR.Close()
39
40 // Once gzip decompressed we have a tar format
41 tarR := tar.NewReader(gzipR)
42 done := false
43 for {
44 hdr, err := tarR.Next()
45 if err == io.EOF {
46 if !done {
47 // Empty archive
48 return fmt.Errorf("empty archive: %s", src)
49 }
50
51 return nil
52 }
53 if err != nil {
54 return err
55 }
56
57 path := dst
58 if dir {
59 path = filepath.Join(path, hdr.Name)
60 }
61
62 if hdr.FileInfo().IsDir() {
63 if !dir {
64 return fmt.Errorf("expected a single file: %s", src)
65 }
66
67 // A directory, just make the directory and continue unarchiving...
68 if err := os.MkdirAll(path, 0755); err != nil {
69 return err
70 }
71
72 continue
73 }
74
75 // We have a file. If we already decoded, then it is an error
76 if !dir && done {
77 return fmt.Errorf("expected a single file, got multiple: %s", src)
78 }
79
80 // Mark that we're done so future in single file mode errors
81 done = true
82
83 // Open the file for writing
84 dstF, err := os.Create(path)
85 if err != nil {
86 return err
87 }
88 _, err = io.Copy(dstF, tarR)
89 dstF.Close()
90 if err != nil {
91 return err
92 }
93
94 // Chmod the file
95 if err := os.Chmod(path, hdr.FileInfo().Mode()); err != nil {
96 return err
97 }
98 }
99}
diff --git a/vendor/github.com/hashicorp/go-getter/decompress_zip.go b/vendor/github.com/hashicorp/go-getter/decompress_zip.go
new file mode 100644
index 0000000..a065c07
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/decompress_zip.go
@@ -0,0 +1,96 @@
1package getter
2
3import (
4 "archive/zip"
5 "fmt"
6 "io"
7 "os"
8 "path/filepath"
9)
10
11// ZipDecompressor is an implementation of Decompressor that can
12// decompress tar.gzip files.
13type ZipDecompressor struct{}
14
15func (d *ZipDecompressor) Decompress(dst, src string, dir bool) error {
16 // If we're going into a directory we should make that first
17 mkdir := dst
18 if !dir {
19 mkdir = filepath.Dir(dst)
20 }
21 if err := os.MkdirAll(mkdir, 0755); err != nil {
22 return err
23 }
24
25 // Open the zip
26 zipR, err := zip.OpenReader(src)
27 if err != nil {
28 return err
29 }
30 defer zipR.Close()
31
32 // Check the zip integrity
33 if len(zipR.File) == 0 {
34 // Empty archive
35 return fmt.Errorf("empty archive: %s", src)
36 }
37 if !dir && len(zipR.File) > 1 {
38 return fmt.Errorf("expected a single file: %s", src)
39 }
40
41 // Go through and unarchive
42 for _, f := range zipR.File {
43 path := dst
44 if dir {
45 path = filepath.Join(path, f.Name)
46 }
47
48 if f.FileInfo().IsDir() {
49 if !dir {
50 return fmt.Errorf("expected a single file: %s", src)
51 }
52
53 // A directory, just make the directory and continue unarchiving...
54 if err := os.MkdirAll(path, 0755); err != nil {
55 return err
56 }
57
58 continue
59 }
60
61 // Create the enclosing directories if we must. ZIP files aren't
62 // required to contain entries for just the directories so this
63 // can happen.
64 if dir {
65 if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
66 return err
67 }
68 }
69
70 // Open the file for reading
71 srcF, err := f.Open()
72 if err != nil {
73 return err
74 }
75
76 // Open the file for writing
77 dstF, err := os.Create(path)
78 if err != nil {
79 srcF.Close()
80 return err
81 }
82 _, err = io.Copy(dstF, srcF)
83 srcF.Close()
84 dstF.Close()
85 if err != nil {
86 return err
87 }
88
89 // Chmod the file
90 if err := os.Chmod(path, f.Mode()); err != nil {
91 return err
92 }
93 }
94
95 return nil
96}
diff --git a/vendor/github.com/hashicorp/go-getter/detect.go b/vendor/github.com/hashicorp/go-getter/detect.go
new file mode 100644
index 0000000..481b737
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/detect.go
@@ -0,0 +1,97 @@
1package getter
2
3import (
4 "fmt"
5 "path/filepath"
6
7 "github.com/hashicorp/go-getter/helper/url"
8)
9
10// Detector defines the interface that an invalid URL or a URL with a blank
11// scheme is passed through in order to determine if its shorthand for
12// something else well-known.
13type Detector interface {
14 // Detect will detect whether the string matches a known pattern to
15 // turn it into a proper URL.
16 Detect(string, string) (string, bool, error)
17}
18
19// Detectors is the list of detectors that are tried on an invalid URL.
20// This is also the order they're tried (index 0 is first).
21var Detectors []Detector
22
23func init() {
24 Detectors = []Detector{
25 new(GitHubDetector),
26 new(BitBucketDetector),
27 new(S3Detector),
28 new(FileDetector),
29 }
30}
31
32// Detect turns a source string into another source string if it is
33// detected to be of a known pattern.
34//
35// The third parameter should be the list of detectors to use in the
36// order to try them. If you don't want to configure this, just use
37// the global Detectors variable.
38//
39// This is safe to be called with an already valid source string: Detect
40// will just return it.
41func Detect(src string, pwd string, ds []Detector) (string, error) {
42 getForce, getSrc := getForcedGetter(src)
43
44 // Separate out the subdir if there is one, we don't pass that to detect
45 getSrc, subDir := SourceDirSubdir(getSrc)
46
47 u, err := url.Parse(getSrc)
48 if err == nil && u.Scheme != "" {
49 // Valid URL
50 return src, nil
51 }
52
53 for _, d := range ds {
54 result, ok, err := d.Detect(getSrc, pwd)
55 if err != nil {
56 return "", err
57 }
58 if !ok {
59 continue
60 }
61
62 var detectForce string
63 detectForce, result = getForcedGetter(result)
64 result, detectSubdir := SourceDirSubdir(result)
65
66 // If we have a subdir from the detection, then prepend it to our
67 // requested subdir.
68 if detectSubdir != "" {
69 if subDir != "" {
70 subDir = filepath.Join(detectSubdir, subDir)
71 } else {
72 subDir = detectSubdir
73 }
74 }
75 if subDir != "" {
76 u, err := url.Parse(result)
77 if err != nil {
78 return "", fmt.Errorf("Error parsing URL: %s", err)
79 }
80 u.Path += "//" + subDir
81 result = u.String()
82 }
83
84 // Preserve the forced getter if it exists. We try to use the
85 // original set force first, followed by any force set by the
86 // detector.
87 if getForce != "" {
88 result = fmt.Sprintf("%s::%s", getForce, result)
89 } else if detectForce != "" {
90 result = fmt.Sprintf("%s::%s", detectForce, result)
91 }
92
93 return result, nil
94 }
95
96 return "", fmt.Errorf("invalid source string: %s", src)
97}
diff --git a/vendor/github.com/hashicorp/go-getter/detect_bitbucket.go b/vendor/github.com/hashicorp/go-getter/detect_bitbucket.go
new file mode 100644
index 0000000..a183a17
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/detect_bitbucket.go
@@ -0,0 +1,66 @@
1package getter
2
3import (
4 "encoding/json"
5 "fmt"
6 "net/http"
7 "net/url"
8 "strings"
9)
10
11// BitBucketDetector implements Detector to detect BitBucket URLs and turn
12// them into URLs that the Git or Hg Getter can understand.
13type BitBucketDetector struct{}
14
15func (d *BitBucketDetector) Detect(src, _ string) (string, bool, error) {
16 if len(src) == 0 {
17 return "", false, nil
18 }
19
20 if strings.HasPrefix(src, "bitbucket.org/") {
21 return d.detectHTTP(src)
22 }
23
24 return "", false, nil
25}
26
27func (d *BitBucketDetector) detectHTTP(src string) (string, bool, error) {
28 u, err := url.Parse("https://" + src)
29 if err != nil {
30 return "", true, fmt.Errorf("error parsing BitBucket URL: %s", err)
31 }
32
33 // We need to get info on this BitBucket repository to determine whether
34 // it is Git or Hg.
35 var info struct {
36 SCM string `json:"scm"`
37 }
38 infoUrl := "https://api.bitbucket.org/1.0/repositories" + u.Path
39 resp, err := http.Get(infoUrl)
40 if err != nil {
41 return "", true, fmt.Errorf("error looking up BitBucket URL: %s", err)
42 }
43 if resp.StatusCode == 403 {
44 // A private repo
45 return "", true, fmt.Errorf(
46 "shorthand BitBucket URL can't be used for private repos, " +
47 "please use a full URL")
48 }
49 dec := json.NewDecoder(resp.Body)
50 if err := dec.Decode(&info); err != nil {
51 return "", true, fmt.Errorf("error looking up BitBucket URL: %s", err)
52 }
53
54 switch info.SCM {
55 case "git":
56 if !strings.HasSuffix(u.Path, ".git") {
57 u.Path += ".git"
58 }
59
60 return "git::" + u.String(), true, nil
61 case "hg":
62 return "hg::" + u.String(), true, nil
63 default:
64 return "", true, fmt.Errorf("unknown BitBucket SCM type: %s", info.SCM)
65 }
66}
diff --git a/vendor/github.com/hashicorp/go-getter/detect_file.go b/vendor/github.com/hashicorp/go-getter/detect_file.go
new file mode 100644
index 0000000..756ea43
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/detect_file.go
@@ -0,0 +1,67 @@
1package getter
2
3import (
4 "fmt"
5 "os"
6 "path/filepath"
7 "runtime"
8)
9
10// FileDetector implements Detector to detect file paths.
11type FileDetector struct{}
12
13func (d *FileDetector) Detect(src, pwd string) (string, bool, error) {
14 if len(src) == 0 {
15 return "", false, nil
16 }
17
18 if !filepath.IsAbs(src) {
19 if pwd == "" {
20 return "", true, fmt.Errorf(
21 "relative paths require a module with a pwd")
22 }
23
24 // Stat the pwd to determine if its a symbolic link. If it is,
25 // then the pwd becomes the original directory. Otherwise,
26 // `filepath.Join` below does some weird stuff.
27 //
28 // We just ignore if the pwd doesn't exist. That error will be
29 // caught later when we try to use the URL.
30 if fi, err := os.Lstat(pwd); !os.IsNotExist(err) {
31 if err != nil {
32 return "", true, err
33 }
34 if fi.Mode()&os.ModeSymlink != 0 {
35 pwd, err = os.Readlink(pwd)
36 if err != nil {
37 return "", true, err
38 }
39
40 // The symlink itself might be a relative path, so we have to
41 // resolve this to have a correctly rooted URL.
42 pwd, err = filepath.Abs(pwd)
43 if err != nil {
44 return "", true, err
45 }
46 }
47 }
48
49 src = filepath.Join(pwd, src)
50 }
51
52 return fmtFileURL(src), true, nil
53}
54
55func fmtFileURL(path string) string {
56 if runtime.GOOS == "windows" {
57 // Make sure we're using "/" on Windows. URLs are "/"-based.
58 path = filepath.ToSlash(path)
59 return fmt.Sprintf("file://%s", path)
60 }
61
62 // Make sure that we don't start with "/" since we add that below.
63 if path[0] == '/' {
64 path = path[1:]
65 }
66 return fmt.Sprintf("file:///%s", path)
67}
diff --git a/vendor/github.com/hashicorp/go-getter/detect_github.go b/vendor/github.com/hashicorp/go-getter/detect_github.go
new file mode 100644
index 0000000..c084ad9
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/detect_github.go
@@ -0,0 +1,73 @@
1package getter
2
3import (
4 "fmt"
5 "net/url"
6 "strings"
7)
8
9// GitHubDetector implements Detector to detect GitHub URLs and turn
10// them into URLs that the Git Getter can understand.
11type GitHubDetector struct{}
12
13func (d *GitHubDetector) Detect(src, _ string) (string, bool, error) {
14 if len(src) == 0 {
15 return "", false, nil
16 }
17
18 if strings.HasPrefix(src, "github.com/") {
19 return d.detectHTTP(src)
20 } else if strings.HasPrefix(src, "git@github.com:") {
21 return d.detectSSH(src)
22 }
23
24 return "", false, nil
25}
26
27func (d *GitHubDetector) detectHTTP(src string) (string, bool, error) {
28 parts := strings.Split(src, "/")
29 if len(parts) < 3 {
30 return "", false, fmt.Errorf(
31 "GitHub URLs should be github.com/username/repo")
32 }
33
34 urlStr := fmt.Sprintf("https://%s", strings.Join(parts[:3], "/"))
35 url, err := url.Parse(urlStr)
36 if err != nil {
37 return "", true, fmt.Errorf("error parsing GitHub URL: %s", err)
38 }
39
40 if !strings.HasSuffix(url.Path, ".git") {
41 url.Path += ".git"
42 }
43
44 if len(parts) > 3 {
45 url.Path += "//" + strings.Join(parts[3:], "/")
46 }
47
48 return "git::" + url.String(), true, nil
49}
50
51func (d *GitHubDetector) detectSSH(src string) (string, bool, error) {
52 idx := strings.Index(src, ":")
53 qidx := strings.Index(src, "?")
54 if qidx == -1 {
55 qidx = len(src)
56 }
57
58 var u url.URL
59 u.Scheme = "ssh"
60 u.User = url.User("git")
61 u.Host = "github.com"
62 u.Path = src[idx+1 : qidx]
63 if qidx < len(src) {
64 q, err := url.ParseQuery(src[qidx+1:])
65 if err != nil {
66 return "", true, fmt.Errorf("error parsing GitHub SSH URL: %s", err)
67 }
68
69 u.RawQuery = q.Encode()
70 }
71
72 return "git::" + u.String(), true, nil
73}
diff --git a/vendor/github.com/hashicorp/go-getter/detect_s3.go b/vendor/github.com/hashicorp/go-getter/detect_s3.go
new file mode 100644
index 0000000..8e0f4a0
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/detect_s3.go
@@ -0,0 +1,61 @@
1package getter
2
3import (
4 "fmt"
5 "net/url"
6 "strings"
7)
8
9// S3Detector implements Detector to detect S3 URLs and turn
10// them into URLs that the S3 getter can understand.
11type S3Detector struct{}
12
13func (d *S3Detector) Detect(src, _ string) (string, bool, error) {
14 if len(src) == 0 {
15 return "", false, nil
16 }
17
18 if strings.Contains(src, ".amazonaws.com/") {
19 return d.detectHTTP(src)
20 }
21
22 return "", false, nil
23}
24
25func (d *S3Detector) detectHTTP(src string) (string, bool, error) {
26 parts := strings.Split(src, "/")
27 if len(parts) < 2 {
28 return "", false, fmt.Errorf(
29 "URL is not a valid S3 URL")
30 }
31
32 hostParts := strings.Split(parts[0], ".")
33 if len(hostParts) == 3 {
34 return d.detectPathStyle(hostParts[0], parts[1:])
35 } else if len(hostParts) == 4 {
36 return d.detectVhostStyle(hostParts[1], hostParts[0], parts[1:])
37 } else {
38 return "", false, fmt.Errorf(
39 "URL is not a valid S3 URL")
40 }
41}
42
43func (d *S3Detector) detectPathStyle(region string, parts []string) (string, bool, error) {
44 urlStr := fmt.Sprintf("https://%s.amazonaws.com/%s", region, strings.Join(parts, "/"))
45 url, err := url.Parse(urlStr)
46 if err != nil {
47 return "", false, fmt.Errorf("error parsing S3 URL: %s", err)
48 }
49
50 return "s3::" + url.String(), true, nil
51}
52
53func (d *S3Detector) detectVhostStyle(region, bucket string, parts []string) (string, bool, error) {
54 urlStr := fmt.Sprintf("https://%s.amazonaws.com/%s/%s", region, bucket, strings.Join(parts, "/"))
55 url, err := url.Parse(urlStr)
56 if err != nil {
57 return "", false, fmt.Errorf("error parsing S3 URL: %s", err)
58 }
59
60 return "s3::" + url.String(), true, nil
61}
diff --git a/vendor/github.com/hashicorp/go-getter/folder_storage.go b/vendor/github.com/hashicorp/go-getter/folder_storage.go
new file mode 100644
index 0000000..647ccf4
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/folder_storage.go
@@ -0,0 +1,65 @@
1package getter
2
3import (
4 "crypto/md5"
5 "encoding/hex"
6 "fmt"
7 "os"
8 "path/filepath"
9)
10
11// FolderStorage is an implementation of the Storage interface that manages
12// modules on the disk.
13type FolderStorage struct {
14 // StorageDir is the directory where the modules will be stored.
15 StorageDir string
16}
17
18// Dir implements Storage.Dir
19func (s *FolderStorage) Dir(key string) (d string, e bool, err error) {
20 d = s.dir(key)
21 _, err = os.Stat(d)
22 if err == nil {
23 // Directory exists
24 e = true
25 return
26 }
27 if os.IsNotExist(err) {
28 // Directory doesn't exist
29 d = ""
30 e = false
31 err = nil
32 return
33 }
34
35 // An error
36 d = ""
37 e = false
38 return
39}
40
41// Get implements Storage.Get
42func (s *FolderStorage) Get(key string, source string, update bool) error {
43 dir := s.dir(key)
44 if !update {
45 if _, err := os.Stat(dir); err == nil {
46 // If the directory already exists, then we're done since
47 // we're not updating.
48 return nil
49 } else if !os.IsNotExist(err) {
50 // If the error we got wasn't a file-not-exist error, then
51 // something went wrong and we should report it.
52 return fmt.Errorf("Error reading module directory: %s", err)
53 }
54 }
55
56 // Get the source. This always forces an update.
57 return Get(dir, source)
58}
59
60// dir returns the directory name internally that we'll use to map to
61// internally.
62func (s *FolderStorage) dir(key string) string {
63 sum := md5.Sum([]byte(key))
64 return filepath.Join(s.StorageDir, hex.EncodeToString(sum[:]))
65}
diff --git a/vendor/github.com/hashicorp/go-getter/get.go b/vendor/github.com/hashicorp/go-getter/get.go
new file mode 100644
index 0000000..c3236f5
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get.go
@@ -0,0 +1,139 @@
1// getter is a package for downloading files or directories from a variety of
2// protocols.
3//
4// getter is unique in its ability to download both directories and files.
5// It also detects certain source strings to be protocol-specific URLs. For
6// example, "github.com/hashicorp/go-getter" would turn into a Git URL and
7// use the Git protocol.
8//
9// Protocols and detectors are extensible.
10//
11// To get started, see Client.
12package getter
13
14import (
15 "bytes"
16 "fmt"
17 "net/url"
18 "os/exec"
19 "regexp"
20 "syscall"
21)
22
23// Getter defines the interface that schemes must implement to download
24// things.
25type Getter interface {
26 // Get downloads the given URL into the given directory. This always
27 // assumes that we're updating and gets the latest version that it can.
28 //
29 // The directory may already exist (if we're updating). If it is in a
30 // format that isn't understood, an error should be returned. Get shouldn't
31 // simply nuke the directory.
32 Get(string, *url.URL) error
33
34 // GetFile downloads the give URL into the given path. The URL must
35 // reference a single file. If possible, the Getter should check if
36 // the remote end contains the same file and no-op this operation.
37 GetFile(string, *url.URL) error
38
39 // ClientMode returns the mode based on the given URL. This is used to
40 // allow clients to let the getters decide which mode to use.
41 ClientMode(*url.URL) (ClientMode, error)
42}
43
44// Getters is the mapping of scheme to the Getter implementation that will
45// be used to get a dependency.
46var Getters map[string]Getter
47
48// forcedRegexp is the regular expression that finds forced getters. This
49// syntax is schema::url, example: git::https://foo.com
50var forcedRegexp = regexp.MustCompile(`^([A-Za-z0-9]+)::(.+)$`)
51
52func init() {
53 httpGetter := &HttpGetter{Netrc: true}
54
55 Getters = map[string]Getter{
56 "file": new(FileGetter),
57 "git": new(GitGetter),
58 "hg": new(HgGetter),
59 "s3": new(S3Getter),
60 "http": httpGetter,
61 "https": httpGetter,
62 }
63}
64
65// Get downloads the directory specified by src into the folder specified by
66// dst. If dst already exists, Get will attempt to update it.
67//
68// src is a URL, whereas dst is always just a file path to a folder. This
69// folder doesn't need to exist. It will be created if it doesn't exist.
70func Get(dst, src string) error {
71 return (&Client{
72 Src: src,
73 Dst: dst,
74 Dir: true,
75 Getters: Getters,
76 }).Get()
77}
78
79// GetAny downloads a URL into the given destination. Unlike Get or
80// GetFile, both directories and files are supported.
81//
82// dst must be a directory. If src is a file, it will be downloaded
83// into dst with the basename of the URL. If src is a directory or
84// archive, it will be unpacked directly into dst.
85func GetAny(dst, src string) error {
86 return (&Client{
87 Src: src,
88 Dst: dst,
89 Mode: ClientModeAny,
90 Getters: Getters,
91 }).Get()
92}
93
94// GetFile downloads the file specified by src into the path specified by
95// dst.
96func GetFile(dst, src string) error {
97 return (&Client{
98 Src: src,
99 Dst: dst,
100 Dir: false,
101 Getters: Getters,
102 }).Get()
103}
104
105// getRunCommand is a helper that will run a command and capture the output
106// in the case an error happens.
107func getRunCommand(cmd *exec.Cmd) error {
108 var buf bytes.Buffer
109 cmd.Stdout = &buf
110 cmd.Stderr = &buf
111 err := cmd.Run()
112 if err == nil {
113 return nil
114 }
115 if exiterr, ok := err.(*exec.ExitError); ok {
116 // The program has exited with an exit code != 0
117 if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
118 return fmt.Errorf(
119 "%s exited with %d: %s",
120 cmd.Path,
121 status.ExitStatus(),
122 buf.String())
123 }
124 }
125
126 return fmt.Errorf("error running %s: %s", cmd.Path, buf.String())
127}
128
129// getForcedGetter takes a source and returns the tuple of the forced
130// getter and the raw URL (without the force syntax).
131func getForcedGetter(src string) (string, string) {
132 var forced string
133 if ms := forcedRegexp.FindStringSubmatch(src); ms != nil {
134 forced = ms[1]
135 src = ms[2]
136 }
137
138 return forced, src
139}
diff --git a/vendor/github.com/hashicorp/go-getter/get_file.go b/vendor/github.com/hashicorp/go-getter/get_file.go
new file mode 100644
index 0000000..e5d2d61
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_file.go
@@ -0,0 +1,32 @@
1package getter
2
3import (
4 "net/url"
5 "os"
6)
7
8// FileGetter is a Getter implementation that will download a module from
9// a file scheme.
10type FileGetter struct {
11 // Copy, if set to true, will copy data instead of using a symlink
12 Copy bool
13}
14
15func (g *FileGetter) ClientMode(u *url.URL) (ClientMode, error) {
16 path := u.Path
17 if u.RawPath != "" {
18 path = u.RawPath
19 }
20
21 fi, err := os.Stat(path)
22 if err != nil {
23 return 0, err
24 }
25
26 // Check if the source is a directory.
27 if fi.IsDir() {
28 return ClientModeDir, nil
29 }
30
31 return ClientModeFile, nil
32}
diff --git a/vendor/github.com/hashicorp/go-getter/get_file_unix.go b/vendor/github.com/hashicorp/go-getter/get_file_unix.go
new file mode 100644
index 0000000..c89a2d5
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_file_unix.go
@@ -0,0 +1,103 @@
1// +build !windows
2
3package getter
4
5import (
6 "fmt"
7 "io"
8 "net/url"
9 "os"
10 "path/filepath"
11)
12
13func (g *FileGetter) Get(dst string, u *url.URL) error {
14 path := u.Path
15 if u.RawPath != "" {
16 path = u.RawPath
17 }
18
19 // The source path must exist and be a directory to be usable.
20 if fi, err := os.Stat(path); err != nil {
21 return fmt.Errorf("source path error: %s", err)
22 } else if !fi.IsDir() {
23 return fmt.Errorf("source path must be a directory")
24 }
25
26 fi, err := os.Lstat(dst)
27 if err != nil && !os.IsNotExist(err) {
28 return err
29 }
30
31 // If the destination already exists, it must be a symlink
32 if err == nil {
33 mode := fi.Mode()
34 if mode&os.ModeSymlink == 0 {
35 return fmt.Errorf("destination exists and is not a symlink")
36 }
37
38 // Remove the destination
39 if err := os.Remove(dst); err != nil {
40 return err
41 }
42 }
43
44 // Create all the parent directories
45 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
46 return err
47 }
48
49 return os.Symlink(path, dst)
50}
51
52func (g *FileGetter) GetFile(dst string, u *url.URL) error {
53 path := u.Path
54 if u.RawPath != "" {
55 path = u.RawPath
56 }
57
58 // The source path must exist and be a file to be usable.
59 if fi, err := os.Stat(path); err != nil {
60 return fmt.Errorf("source path error: %s", err)
61 } else if fi.IsDir() {
62 return fmt.Errorf("source path must be a file")
63 }
64
65 _, err := os.Lstat(dst)
66 if err != nil && !os.IsNotExist(err) {
67 return err
68 }
69
70 // If the destination already exists, it must be a symlink
71 if err == nil {
72 // Remove the destination
73 if err := os.Remove(dst); err != nil {
74 return err
75 }
76 }
77
78 // Create all the parent directories
79 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
80 return err
81 }
82
83 // If we're not copying, just symlink and we're done
84 if !g.Copy {
85 return os.Symlink(path, dst)
86 }
87
88 // Copy
89 srcF, err := os.Open(path)
90 if err != nil {
91 return err
92 }
93 defer srcF.Close()
94
95 dstF, err := os.Create(dst)
96 if err != nil {
97 return err
98 }
99 defer dstF.Close()
100
101 _, err = io.Copy(dstF, srcF)
102 return err
103}
diff --git a/vendor/github.com/hashicorp/go-getter/get_file_windows.go b/vendor/github.com/hashicorp/go-getter/get_file_windows.go
new file mode 100644
index 0000000..f87ed0a
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_file_windows.go
@@ -0,0 +1,120 @@
1// +build windows
2
3package getter
4
5import (
6 "fmt"
7 "io"
8 "net/url"
9 "os"
10 "os/exec"
11 "path/filepath"
12 "strings"
13)
14
15func (g *FileGetter) Get(dst string, u *url.URL) error {
16 path := u.Path
17 if u.RawPath != "" {
18 path = u.RawPath
19 }
20
21 // The source path must exist and be a directory to be usable.
22 if fi, err := os.Stat(path); err != nil {
23 return fmt.Errorf("source path error: %s", err)
24 } else if !fi.IsDir() {
25 return fmt.Errorf("source path must be a directory")
26 }
27
28 fi, err := os.Lstat(dst)
29 if err != nil && !os.IsNotExist(err) {
30 return err
31 }
32
33 // If the destination already exists, it must be a symlink
34 if err == nil {
35 mode := fi.Mode()
36 if mode&os.ModeSymlink == 0 {
37 return fmt.Errorf("destination exists and is not a symlink")
38 }
39
40 // Remove the destination
41 if err := os.Remove(dst); err != nil {
42 return err
43 }
44 }
45
46 // Create all the parent directories
47 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
48 return err
49 }
50
51 sourcePath := toBackslash(path)
52
53 // Use mklink to create a junction point
54 output, err := exec.Command("cmd", "/c", "mklink", "/J", dst, sourcePath).CombinedOutput()
55 if err != nil {
56 return fmt.Errorf("failed to run mklink %v %v: %v %q", dst, sourcePath, err, output)
57 }
58
59 return nil
60}
61
62func (g *FileGetter) GetFile(dst string, u *url.URL) error {
63 path := u.Path
64 if u.RawPath != "" {
65 path = u.RawPath
66 }
67
68 // The source path must exist and be a directory to be usable.
69 if fi, err := os.Stat(path); err != nil {
70 return fmt.Errorf("source path error: %s", err)
71 } else if fi.IsDir() {
72 return fmt.Errorf("source path must be a file")
73 }
74
75 _, err := os.Lstat(dst)
76 if err != nil && !os.IsNotExist(err) {
77 return err
78 }
79
80 // If the destination already exists, it must be a symlink
81 if err == nil {
82 // Remove the destination
83 if err := os.Remove(dst); err != nil {
84 return err
85 }
86 }
87
88 // Create all the parent directories
89 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
90 return err
91 }
92
93 // If we're not copying, just symlink and we're done
94 if !g.Copy {
95 return os.Symlink(path, dst)
96 }
97
98 // Copy
99 srcF, err := os.Open(path)
100 if err != nil {
101 return err
102 }
103 defer srcF.Close()
104
105 dstF, err := os.Create(dst)
106 if err != nil {
107 return err
108 }
109 defer dstF.Close()
110
111 _, err = io.Copy(dstF, srcF)
112 return err
113}
114
115// toBackslash returns the result of replacing each slash character
116// in path with a backslash ('\') character. Multiple separators are
117// replaced by multiple backslashes.
118func toBackslash(path string) string {
119 return strings.Replace(path, "/", "\\", -1)
120}
diff --git a/vendor/github.com/hashicorp/go-getter/get_git.go b/vendor/github.com/hashicorp/go-getter/get_git.go
new file mode 100644
index 0000000..0728139
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_git.go
@@ -0,0 +1,225 @@
1package getter
2
3import (
4 "encoding/base64"
5 "fmt"
6 "io/ioutil"
7 "net/url"
8 "os"
9 "os/exec"
10 "path/filepath"
11 "strings"
12
13 urlhelper "github.com/hashicorp/go-getter/helper/url"
14 "github.com/hashicorp/go-version"
15)
16
17// GitGetter is a Getter implementation that will download a module from
18// a git repository.
19type GitGetter struct{}
20
21func (g *GitGetter) ClientMode(_ *url.URL) (ClientMode, error) {
22 return ClientModeDir, nil
23}
24
25func (g *GitGetter) Get(dst string, u *url.URL) error {
26 if _, err := exec.LookPath("git"); err != nil {
27 return fmt.Errorf("git must be available and on the PATH")
28 }
29
30 // Extract some query parameters we use
31 var ref, sshKey string
32 q := u.Query()
33 if len(q) > 0 {
34 ref = q.Get("ref")
35 q.Del("ref")
36
37 sshKey = q.Get("sshkey")
38 q.Del("sshkey")
39
40 // Copy the URL
41 var newU url.URL = *u
42 u = &newU
43 u.RawQuery = q.Encode()
44 }
45
46 var sshKeyFile string
47 if sshKey != "" {
48 // Check that the git version is sufficiently new.
49 if err := checkGitVersion("2.3"); err != nil {
50 return fmt.Errorf("Error using ssh key: %v", err)
51 }
52
53 // We have an SSH key - decode it.
54 raw, err := base64.StdEncoding.DecodeString(sshKey)
55 if err != nil {
56 return err
57 }
58
59 // Create a temp file for the key and ensure it is removed.
60 fh, err := ioutil.TempFile("", "go-getter")
61 if err != nil {
62 return err
63 }
64 sshKeyFile = fh.Name()
65 defer os.Remove(sshKeyFile)
66
67 // Set the permissions prior to writing the key material.
68 if err := os.Chmod(sshKeyFile, 0600); err != nil {
69 return err
70 }
71
72 // Write the raw key into the temp file.
73 _, err = fh.Write(raw)
74 fh.Close()
75 if err != nil {
76 return err
77 }
78 }
79
80 // Clone or update the repository
81 _, err := os.Stat(dst)
82 if err != nil && !os.IsNotExist(err) {
83 return err
84 }
85 if err == nil {
86 err = g.update(dst, sshKeyFile, ref)
87 } else {
88 err = g.clone(dst, sshKeyFile, u)
89 }
90 if err != nil {
91 return err
92 }
93
94 // Next: check out the proper tag/branch if it is specified, and checkout
95 if ref != "" {
96 if err := g.checkout(dst, ref); err != nil {
97 return err
98 }
99 }
100
101 // Lastly, download any/all submodules.
102 return g.fetchSubmodules(dst, sshKeyFile)
103}
104
105// GetFile for Git doesn't support updating at this time. It will download
106// the file every time.
107func (g *GitGetter) GetFile(dst string, u *url.URL) error {
108 td, err := ioutil.TempDir("", "getter-git")
109 if err != nil {
110 return err
111 }
112 if err := os.RemoveAll(td); err != nil {
113 return err
114 }
115
116 // Get the filename, and strip the filename from the URL so we can
117 // just get the repository directly.
118 filename := filepath.Base(u.Path)
119 u.Path = filepath.Dir(u.Path)
120
121 // Get the full repository
122 if err := g.Get(td, u); err != nil {
123 return err
124 }
125
126 // Copy the single file
127 u, err = urlhelper.Parse(fmtFileURL(filepath.Join(td, filename)))
128 if err != nil {
129 return err
130 }
131
132 fg := &FileGetter{Copy: true}
133 return fg.GetFile(dst, u)
134}
135
136func (g *GitGetter) checkout(dst string, ref string) error {
137 cmd := exec.Command("git", "checkout", ref)
138 cmd.Dir = dst
139 return getRunCommand(cmd)
140}
141
142func (g *GitGetter) clone(dst, sshKeyFile string, u *url.URL) error {
143 cmd := exec.Command("git", "clone", u.String(), dst)
144 setupGitEnv(cmd, sshKeyFile)
145 return getRunCommand(cmd)
146}
147
148func (g *GitGetter) update(dst, sshKeyFile, ref string) error {
149 // Determine if we're a branch. If we're NOT a branch, then we just
150 // switch to master prior to checking out
151 cmd := exec.Command("git", "show-ref", "-q", "--verify", "refs/heads/"+ref)
152 cmd.Dir = dst
153
154 if getRunCommand(cmd) != nil {
155 // Not a branch, switch to master. This will also catch non-existent
156 // branches, in which case we want to switch to master and then
157 // checkout the proper branch later.
158 ref = "master"
159 }
160
161 // We have to be on a branch to pull
162 if err := g.checkout(dst, ref); err != nil {
163 return err
164 }
165
166 cmd = exec.Command("git", "pull", "--ff-only")
167 cmd.Dir = dst
168 setupGitEnv(cmd, sshKeyFile)
169 return getRunCommand(cmd)
170}
171
172// fetchSubmodules downloads any configured submodules recursively.
173func (g *GitGetter) fetchSubmodules(dst, sshKeyFile string) error {
174 cmd := exec.Command("git", "submodule", "update", "--init", "--recursive")
175 cmd.Dir = dst
176 setupGitEnv(cmd, sshKeyFile)
177 return getRunCommand(cmd)
178}
179
180// setupGitEnv sets up the environment for the given command. This is used to
181// pass configuration data to git and ssh and enables advanced cloning methods.
182func setupGitEnv(cmd *exec.Cmd, sshKeyFile string) {
183 var sshOpts []string
184
185 if sshKeyFile != "" {
186 // We have an SSH key temp file configured, tell ssh about this.
187 sshOpts = append(sshOpts, "-i", sshKeyFile)
188 }
189
190 cmd.Env = append(os.Environ(),
191 // Set the ssh command to use for clones.
192 "GIT_SSH_COMMAND=ssh "+strings.Join(sshOpts, " "),
193 )
194}
195
196// checkGitVersion is used to check the version of git installed on the system
197// against a known minimum version. Returns an error if the installed version
198// is older than the given minimum.
199func checkGitVersion(min string) error {
200 want, err := version.NewVersion(min)
201 if err != nil {
202 return err
203 }
204
205 out, err := exec.Command("git", "version").Output()
206 if err != nil {
207 return err
208 }
209
210 fields := strings.Fields(string(out))
211 if len(fields) != 3 {
212 return fmt.Errorf("Unexpected 'git version' output: %q", string(out))
213 }
214
215 have, err := version.NewVersion(fields[2])
216 if err != nil {
217 return err
218 }
219
220 if have.LessThan(want) {
221 return fmt.Errorf("Required git version = %s, have %s", want, have)
222 }
223
224 return nil
225}
diff --git a/vendor/github.com/hashicorp/go-getter/get_hg.go b/vendor/github.com/hashicorp/go-getter/get_hg.go
new file mode 100644
index 0000000..820bdd4
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_hg.go
@@ -0,0 +1,131 @@
1package getter
2
3import (
4 "fmt"
5 "io/ioutil"
6 "net/url"
7 "os"
8 "os/exec"
9 "path/filepath"
10 "runtime"
11
12 urlhelper "github.com/hashicorp/go-getter/helper/url"
13)
14
15// HgGetter is a Getter implementation that will download a module from
16// a Mercurial repository.
17type HgGetter struct{}
18
19func (g *HgGetter) ClientMode(_ *url.URL) (ClientMode, error) {
20 return ClientModeDir, nil
21}
22
23func (g *HgGetter) Get(dst string, u *url.URL) error {
24 if _, err := exec.LookPath("hg"); err != nil {
25 return fmt.Errorf("hg must be available and on the PATH")
26 }
27
28 newURL, err := urlhelper.Parse(u.String())
29 if err != nil {
30 return err
31 }
32 if fixWindowsDrivePath(newURL) {
33 // See valid file path form on http://www.selenic.com/hg/help/urls
34 newURL.Path = fmt.Sprintf("/%s", newURL.Path)
35 }
36
37 // Extract some query parameters we use
38 var rev string
39 q := newURL.Query()
40 if len(q) > 0 {
41 rev = q.Get("rev")
42 q.Del("rev")
43
44 newURL.RawQuery = q.Encode()
45 }
46
47 _, err = os.Stat(dst)
48 if err != nil && !os.IsNotExist(err) {
49 return err
50 }
51 if err != nil {
52 if err := g.clone(dst, newURL); err != nil {
53 return err
54 }
55 }
56
57 if err := g.pull(dst, newURL); err != nil {
58 return err
59 }
60
61 return g.update(dst, newURL, rev)
62}
63
64// GetFile for Hg doesn't support updating at this time. It will download
65// the file every time.
66func (g *HgGetter) GetFile(dst string, u *url.URL) error {
67 td, err := ioutil.TempDir("", "getter-hg")
68 if err != nil {
69 return err
70 }
71 if err := os.RemoveAll(td); err != nil {
72 return err
73 }
74
75 // Get the filename, and strip the filename from the URL so we can
76 // just get the repository directly.
77 filename := filepath.Base(u.Path)
78 u.Path = filepath.ToSlash(filepath.Dir(u.Path))
79
80 // If we're on Windows, we need to set the host to "localhost" for hg
81 if runtime.GOOS == "windows" {
82 u.Host = "localhost"
83 }
84
85 // Get the full repository
86 if err := g.Get(td, u); err != nil {
87 return err
88 }
89
90 // Copy the single file
91 u, err = urlhelper.Parse(fmtFileURL(filepath.Join(td, filename)))
92 if err != nil {
93 return err
94 }
95
96 fg := &FileGetter{Copy: true}
97 return fg.GetFile(dst, u)
98}
99
100func (g *HgGetter) clone(dst string, u *url.URL) error {
101 cmd := exec.Command("hg", "clone", "-U", u.String(), dst)
102 return getRunCommand(cmd)
103}
104
105func (g *HgGetter) pull(dst string, u *url.URL) error {
106 cmd := exec.Command("hg", "pull")
107 cmd.Dir = dst
108 return getRunCommand(cmd)
109}
110
111func (g *HgGetter) update(dst string, u *url.URL, rev string) error {
112 args := []string{"update"}
113 if rev != "" {
114 args = append(args, rev)
115 }
116
117 cmd := exec.Command("hg", args...)
118 cmd.Dir = dst
119 return getRunCommand(cmd)
120}
121
122func fixWindowsDrivePath(u *url.URL) bool {
123 // hg assumes a file:/// prefix for Windows drive letter file paths.
124 // (e.g. file:///c:/foo/bar)
125 // If the URL Path does not begin with a '/' character, the resulting URL
126 // path will have a file:// prefix. (e.g. file://c:/foo/bar)
127 // See http://www.selenic.com/hg/help/urls and the examples listed in
128 // http://selenic.com/repo/hg-stable/file/1265a3a71d75/mercurial/util.py#l1936
129 return runtime.GOOS == "windows" && u.Scheme == "file" &&
130 len(u.Path) > 1 && u.Path[0] != '/' && u.Path[1] == ':'
131}
diff --git a/vendor/github.com/hashicorp/go-getter/get_http.go b/vendor/github.com/hashicorp/go-getter/get_http.go
new file mode 100644
index 0000000..3c02034
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_http.go
@@ -0,0 +1,219 @@
1package getter
2
3import (
4 "encoding/xml"
5 "fmt"
6 "io"
7 "io/ioutil"
8 "net/http"
9 "net/url"
10 "os"
11 "path/filepath"
12 "strings"
13)
14
15// HttpGetter is a Getter implementation that will download from an HTTP
16// endpoint.
17//
18// For file downloads, HTTP is used directly.
19//
20// The protocol for downloading a directory from an HTTP endpoing is as follows:
21//
22// An HTTP GET request is made to the URL with the additional GET parameter
23// "terraform-get=1". This lets you handle that scenario specially if you
24// wish. The response must be a 2xx.
25//
26// First, a header is looked for "X-Terraform-Get" which should contain
27// a source URL to download.
28//
29// If the header is not present, then a meta tag is searched for named
30// "terraform-get" and the content should be a source URL.
31//
32// The source URL, whether from the header or meta tag, must be a fully
33// formed URL. The shorthand syntax of "github.com/foo/bar" or relative
34// paths are not allowed.
35type HttpGetter struct {
36 // Netrc, if true, will lookup and use auth information found
37 // in the user's netrc file if available.
38 Netrc bool
39}
40
41func (g *HttpGetter) ClientMode(u *url.URL) (ClientMode, error) {
42 if strings.HasSuffix(u.Path, "/") {
43 return ClientModeDir, nil
44 }
45 return ClientModeFile, nil
46}
47
48func (g *HttpGetter) Get(dst string, u *url.URL) error {
49 // Copy the URL so we can modify it
50 var newU url.URL = *u
51 u = &newU
52
53 if g.Netrc {
54 // Add auth from netrc if we can
55 if err := addAuthFromNetrc(u); err != nil {
56 return err
57 }
58 }
59
60 // Add terraform-get to the parameter.
61 q := u.Query()
62 q.Add("terraform-get", "1")
63 u.RawQuery = q.Encode()
64
65 // Get the URL
66 resp, err := http.Get(u.String())
67 if err != nil {
68 return err
69 }
70 defer resp.Body.Close()
71 if resp.StatusCode < 200 || resp.StatusCode >= 300 {
72 return fmt.Errorf("bad response code: %d", resp.StatusCode)
73 }
74
75 // Extract the source URL
76 var source string
77 if v := resp.Header.Get("X-Terraform-Get"); v != "" {
78 source = v
79 } else {
80 source, err = g.parseMeta(resp.Body)
81 if err != nil {
82 return err
83 }
84 }
85 if source == "" {
86 return fmt.Errorf("no source URL was returned")
87 }
88
89 // If there is a subdir component, then we download the root separately
90 // into a temporary directory, then copy over the proper subdir.
91 source, subDir := SourceDirSubdir(source)
92 if subDir == "" {
93 return Get(dst, source)
94 }
95
96 // We have a subdir, time to jump some hoops
97 return g.getSubdir(dst, source, subDir)
98}
99
100func (g *HttpGetter) GetFile(dst string, u *url.URL) error {
101 resp, err := http.Get(u.String())
102 if err != nil {
103 return err
104 }
105 defer resp.Body.Close()
106 if resp.StatusCode != 200 {
107 return fmt.Errorf("bad response code: %d", resp.StatusCode)
108 }
109
110 // Create all the parent directories
111 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
112 return err
113 }
114
115 f, err := os.Create(dst)
116 if err != nil {
117 return err
118 }
119 defer f.Close()
120
121 _, err = io.Copy(f, resp.Body)
122 return err
123}
124
125// getSubdir downloads the source into the destination, but with
126// the proper subdir.
127func (g *HttpGetter) getSubdir(dst, source, subDir string) error {
128 // Create a temporary directory to store the full source
129 td, err := ioutil.TempDir("", "tf")
130 if err != nil {
131 return err
132 }
133 defer os.RemoveAll(td)
134
135 // Download that into the given directory
136 if err := Get(td, source); err != nil {
137 return err
138 }
139
140 // Make sure the subdir path actually exists
141 sourcePath := filepath.Join(td, subDir)
142 if _, err := os.Stat(sourcePath); err != nil {
143 return fmt.Errorf(
144 "Error downloading %s: %s", source, err)
145 }
146
147 // Copy the subdirectory into our actual destination.
148 if err := os.RemoveAll(dst); err != nil {
149 return err
150 }
151
152 // Make the final destination
153 if err := os.MkdirAll(dst, 0755); err != nil {
154 return err
155 }
156
157 return copyDir(dst, sourcePath, false)
158}
159
160// parseMeta looks for the first meta tag in the given reader that
161// will give us the source URL.
162func (g *HttpGetter) parseMeta(r io.Reader) (string, error) {
163 d := xml.NewDecoder(r)
164 d.CharsetReader = charsetReader
165 d.Strict = false
166 var err error
167 var t xml.Token
168 for {
169 t, err = d.Token()
170 if err != nil {
171 if err == io.EOF {
172 err = nil
173 }
174 return "", err
175 }
176 if e, ok := t.(xml.StartElement); ok && strings.EqualFold(e.Name.Local, "body") {
177 return "", nil
178 }
179 if e, ok := t.(xml.EndElement); ok && strings.EqualFold(e.Name.Local, "head") {
180 return "", nil
181 }
182 e, ok := t.(xml.StartElement)
183 if !ok || !strings.EqualFold(e.Name.Local, "meta") {
184 continue
185 }
186 if attrValue(e.Attr, "name") != "terraform-get" {
187 continue
188 }
189 if f := attrValue(e.Attr, "content"); f != "" {
190 return f, nil
191 }
192 }
193}
194
195// attrValue returns the attribute value for the case-insensitive key
196// `name', or the empty string if nothing is found.
197func attrValue(attrs []xml.Attr, name string) string {
198 for _, a := range attrs {
199 if strings.EqualFold(a.Name.Local, name) {
200 return a.Value
201 }
202 }
203 return ""
204}
205
206// charsetReader returns a reader for the given charset. Currently
207// it only supports UTF-8 and ASCII. Otherwise, it returns a meaningful
208// error which is printed by go get, so the user can find why the package
209// wasn't downloaded if the encoding is not supported. Note that, in
210// order to reduce potential errors, ASCII is treated as UTF-8 (i.e. characters
211// greater than 0x7f are not rejected).
212func charsetReader(charset string, input io.Reader) (io.Reader, error) {
213 switch strings.ToLower(charset) {
214 case "ascii":
215 return input, nil
216 default:
217 return nil, fmt.Errorf("can't decode XML document using charset %q", charset)
218 }
219}
diff --git a/vendor/github.com/hashicorp/go-getter/get_mock.go b/vendor/github.com/hashicorp/go-getter/get_mock.go
new file mode 100644
index 0000000..882e694
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_mock.go
@@ -0,0 +1,52 @@
1package getter
2
3import (
4 "net/url"
5)
6
7// MockGetter is an implementation of Getter that can be used for tests.
8type MockGetter struct {
9 // Proxy, if set, will be called after recording the calls below.
10 // If it isn't set, then the *Err values will be returned.
11 Proxy Getter
12
13 GetCalled bool
14 GetDst string
15 GetURL *url.URL
16 GetErr error
17
18 GetFileCalled bool
19 GetFileDst string
20 GetFileURL *url.URL
21 GetFileErr error
22}
23
24func (g *MockGetter) Get(dst string, u *url.URL) error {
25 g.GetCalled = true
26 g.GetDst = dst
27 g.GetURL = u
28
29 if g.Proxy != nil {
30 return g.Proxy.Get(dst, u)
31 }
32
33 return g.GetErr
34}
35
36func (g *MockGetter) GetFile(dst string, u *url.URL) error {
37 g.GetFileCalled = true
38 g.GetFileDst = dst
39 g.GetFileURL = u
40
41 if g.Proxy != nil {
42 return g.Proxy.GetFile(dst, u)
43 }
44 return g.GetFileErr
45}
46
47func (g *MockGetter) ClientMode(u *url.URL) (ClientMode, error) {
48 if l := len(u.Path); l > 0 && u.Path[l-1:] == "/" {
49 return ClientModeDir, nil
50 }
51 return ClientModeFile, nil
52}
diff --git a/vendor/github.com/hashicorp/go-getter/get_s3.go b/vendor/github.com/hashicorp/go-getter/get_s3.go
new file mode 100644
index 0000000..d3bffeb
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/get_s3.go
@@ -0,0 +1,243 @@
1package getter
2
3import (
4 "fmt"
5 "io"
6 "net/url"
7 "os"
8 "path/filepath"
9 "strings"
10
11 "github.com/aws/aws-sdk-go/aws"
12 "github.com/aws/aws-sdk-go/aws/credentials"
13 "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
14 "github.com/aws/aws-sdk-go/aws/ec2metadata"
15 "github.com/aws/aws-sdk-go/aws/session"
16 "github.com/aws/aws-sdk-go/service/s3"
17)
18
19// S3Getter is a Getter implementation that will download a module from
20// a S3 bucket.
21type S3Getter struct{}
22
23func (g *S3Getter) ClientMode(u *url.URL) (ClientMode, error) {
24 // Parse URL
25 region, bucket, path, _, creds, err := g.parseUrl(u)
26 if err != nil {
27 return 0, err
28 }
29
30 // Create client config
31 config := g.getAWSConfig(region, creds)
32 sess := session.New(config)
33 client := s3.New(sess)
34
35 // List the object(s) at the given prefix
36 req := &s3.ListObjectsInput{
37 Bucket: aws.String(bucket),
38 Prefix: aws.String(path),
39 }
40 resp, err := client.ListObjects(req)
41 if err != nil {
42 return 0, err
43 }
44
45 for _, o := range resp.Contents {
46 // Use file mode on exact match.
47 if *o.Key == path {
48 return ClientModeFile, nil
49 }
50
51 // Use dir mode if child keys are found.
52 if strings.HasPrefix(*o.Key, path+"/") {
53 return ClientModeDir, nil
54 }
55 }
56
57 // There was no match, so just return file mode. The download is going
58 // to fail but we will let S3 return the proper error later.
59 return ClientModeFile, nil
60}
61
62func (g *S3Getter) Get(dst string, u *url.URL) error {
63 // Parse URL
64 region, bucket, path, _, creds, err := g.parseUrl(u)
65 if err != nil {
66 return err
67 }
68
69 // Remove destination if it already exists
70 _, err = os.Stat(dst)
71 if err != nil && !os.IsNotExist(err) {
72 return err
73 }
74
75 if err == nil {
76 // Remove the destination
77 if err := os.RemoveAll(dst); err != nil {
78 return err
79 }
80 }
81
82 // Create all the parent directories
83 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
84 return err
85 }
86
87 config := g.getAWSConfig(region, creds)
88 sess := session.New(config)
89 client := s3.New(sess)
90
91 // List files in path, keep listing until no more objects are found
92 lastMarker := ""
93 hasMore := true
94 for hasMore {
95 req := &s3.ListObjectsInput{
96 Bucket: aws.String(bucket),
97 Prefix: aws.String(path),
98 }
99 if lastMarker != "" {
100 req.Marker = aws.String(lastMarker)
101 }
102
103 resp, err := client.ListObjects(req)
104 if err != nil {
105 return err
106 }
107
108 hasMore = aws.BoolValue(resp.IsTruncated)
109
110 // Get each object storing each file relative to the destination path
111 for _, object := range resp.Contents {
112 lastMarker = aws.StringValue(object.Key)
113 objPath := aws.StringValue(object.Key)
114
115 // If the key ends with a backslash assume it is a directory and ignore
116 if strings.HasSuffix(objPath, "/") {
117 continue
118 }
119
120 // Get the object destination path
121 objDst, err := filepath.Rel(path, objPath)
122 if err != nil {
123 return err
124 }
125 objDst = filepath.Join(dst, objDst)
126
127 if err := g.getObject(client, objDst, bucket, objPath, ""); err != nil {
128 return err
129 }
130 }
131 }
132
133 return nil
134}
135
136func (g *S3Getter) GetFile(dst string, u *url.URL) error {
137 region, bucket, path, version, creds, err := g.parseUrl(u)
138 if err != nil {
139 return err
140 }
141
142 config := g.getAWSConfig(region, creds)
143 sess := session.New(config)
144 client := s3.New(sess)
145 return g.getObject(client, dst, bucket, path, version)
146}
147
148func (g *S3Getter) getObject(client *s3.S3, dst, bucket, key, version string) error {
149 req := &s3.GetObjectInput{
150 Bucket: aws.String(bucket),
151 Key: aws.String(key),
152 }
153 if version != "" {
154 req.VersionId = aws.String(version)
155 }
156
157 resp, err := client.GetObject(req)
158 if err != nil {
159 return err
160 }
161
162 // Create all the parent directories
163 if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
164 return err
165 }
166
167 f, err := os.Create(dst)
168 if err != nil {
169 return err
170 }
171 defer f.Close()
172
173 _, err = io.Copy(f, resp.Body)
174 return err
175}
176
177func (g *S3Getter) getAWSConfig(region string, creds *credentials.Credentials) *aws.Config {
178 conf := &aws.Config{}
179 if creds == nil {
180 // Grab the metadata URL
181 metadataURL := os.Getenv("AWS_METADATA_URL")
182 if metadataURL == "" {
183 metadataURL = "http://169.254.169.254:80/latest"
184 }
185
186 creds = credentials.NewChainCredentials(
187 []credentials.Provider{
188 &credentials.EnvProvider{},
189 &credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
190 &ec2rolecreds.EC2RoleProvider{
191 Client: ec2metadata.New(session.New(&aws.Config{
192 Endpoint: aws.String(metadataURL),
193 })),
194 },
195 })
196 }
197
198 conf.Credentials = creds
199 if region != "" {
200 conf.Region = aws.String(region)
201 }
202
203 return conf
204}
205
206func (g *S3Getter) parseUrl(u *url.URL) (region, bucket, path, version string, creds *credentials.Credentials, err error) {
207 // Expected host style: s3.amazonaws.com. They always have 3 parts,
208 // although the first may differ if we're accessing a specific region.
209 hostParts := strings.Split(u.Host, ".")
210 if len(hostParts) != 3 {
211 err = fmt.Errorf("URL is not a valid S3 URL")
212 return
213 }
214
215 // Parse the region out of the first part of the host
216 region = strings.TrimPrefix(strings.TrimPrefix(hostParts[0], "s3-"), "s3")
217 if region == "" {
218 region = "us-east-1"
219 }
220
221 pathParts := strings.SplitN(u.Path, "/", 3)
222 if len(pathParts) != 3 {
223 err = fmt.Errorf("URL is not a valid S3 URL")
224 return
225 }
226
227 bucket = pathParts[1]
228 path = pathParts[2]
229 version = u.Query().Get("version")
230
231 _, hasAwsId := u.Query()["aws_access_key_id"]
232 _, hasAwsSecret := u.Query()["aws_access_key_secret"]
233 _, hasAwsToken := u.Query()["aws_access_token"]
234 if hasAwsId || hasAwsSecret || hasAwsToken {
235 creds = credentials.NewStaticCredentials(
236 u.Query().Get("aws_access_key_id"),
237 u.Query().Get("aws_access_key_secret"),
238 u.Query().Get("aws_access_token"),
239 )
240 }
241
242 return
243}
diff --git a/vendor/github.com/hashicorp/go-getter/helper/url/url.go b/vendor/github.com/hashicorp/go-getter/helper/url/url.go
new file mode 100644
index 0000000..02497c2
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/helper/url/url.go
@@ -0,0 +1,14 @@
1package url
2
3import (
4 "net/url"
5)
6
7// Parse parses rawURL into a URL structure.
8// The rawURL may be relative or absolute.
9//
10// Parse is a wrapper for the Go stdlib net/url Parse function, but returns
11// Windows "safe" URLs on Windows platforms.
12func Parse(rawURL string) (*url.URL, error) {
13 return parse(rawURL)
14}
diff --git a/vendor/github.com/hashicorp/go-getter/helper/url/url_unix.go b/vendor/github.com/hashicorp/go-getter/helper/url/url_unix.go
new file mode 100644
index 0000000..ed1352a
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/helper/url/url_unix.go
@@ -0,0 +1,11 @@
1// +build !windows
2
3package url
4
5import (
6 "net/url"
7)
8
9func parse(rawURL string) (*url.URL, error) {
10 return url.Parse(rawURL)
11}
diff --git a/vendor/github.com/hashicorp/go-getter/helper/url/url_windows.go b/vendor/github.com/hashicorp/go-getter/helper/url/url_windows.go
new file mode 100644
index 0000000..4655226
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/helper/url/url_windows.go
@@ -0,0 +1,40 @@
1package url
2
3import (
4 "fmt"
5 "net/url"
6 "path/filepath"
7 "strings"
8)
9
10func parse(rawURL string) (*url.URL, error) {
11 // Make sure we're using "/" since URLs are "/"-based.
12 rawURL = filepath.ToSlash(rawURL)
13
14 u, err := url.Parse(rawURL)
15 if err != nil {
16 return nil, err
17 }
18
19 if len(rawURL) > 1 && rawURL[1] == ':' {
20 // Assume we're dealing with a drive letter file path where the drive
21 // letter has been parsed into the URL Scheme, and the rest of the path
22 // has been parsed into the URL Path without the leading ':' character.
23 u.Path = fmt.Sprintf("%s:%s", string(rawURL[0]), u.Path)
24 u.Scheme = ""
25 }
26
27 if len(u.Host) > 1 && u.Host[1] == ':' && strings.HasPrefix(rawURL, "file://") {
28 // Assume we're dealing with a drive letter file path where the drive
29 // letter has been parsed into the URL Host.
30 u.Path = fmt.Sprintf("%s%s", u.Host, u.Path)
31 u.Host = ""
32 }
33
34 // Remove leading slash for absolute file paths.
35 if len(u.Path) > 2 && u.Path[0] == '/' && u.Path[2] == ':' {
36 u.Path = u.Path[1:]
37 }
38
39 return u, err
40}
diff --git a/vendor/github.com/hashicorp/go-getter/netrc.go b/vendor/github.com/hashicorp/go-getter/netrc.go
new file mode 100644
index 0000000..c7f6a3f
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/netrc.go
@@ -0,0 +1,67 @@
1package getter
2
3import (
4 "fmt"
5 "net/url"
6 "os"
7 "runtime"
8
9 "github.com/bgentry/go-netrc/netrc"
10 "github.com/mitchellh/go-homedir"
11)
12
13// addAuthFromNetrc adds auth information to the URL from the user's
14// netrc file if it can be found. This will only add the auth info
15// if the URL doesn't already have auth info specified and the
16// the username is blank.
17func addAuthFromNetrc(u *url.URL) error {
18 // If the URL already has auth information, do nothing
19 if u.User != nil && u.User.Username() != "" {
20 return nil
21 }
22
23 // Get the netrc file path
24 path := os.Getenv("NETRC")
25 if path == "" {
26 filename := ".netrc"
27 if runtime.GOOS == "windows" {
28 filename = "_netrc"
29 }
30
31 var err error
32 path, err = homedir.Expand("~/" + filename)
33 if err != nil {
34 return err
35 }
36 }
37
38 // If the file is not a file, then do nothing
39 if fi, err := os.Stat(path); err != nil {
40 // File doesn't exist, do nothing
41 if os.IsNotExist(err) {
42 return nil
43 }
44
45 // Some other error!
46 return err
47 } else if fi.IsDir() {
48 // File is directory, ignore
49 return nil
50 }
51
52 // Load up the netrc file
53 net, err := netrc.ParseFile(path)
54 if err != nil {
55 return fmt.Errorf("Error parsing netrc file at %q: %s", path, err)
56 }
57
58 machine := net.FindMachine(u.Host)
59 if machine == nil {
60 // Machine not found, no problem
61 return nil
62 }
63
64 // Set the user info
65 u.User = url.UserPassword(machine.Login, machine.Password)
66 return nil
67}
diff --git a/vendor/github.com/hashicorp/go-getter/source.go b/vendor/github.com/hashicorp/go-getter/source.go
new file mode 100644
index 0000000..4d5ee3c
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/source.go
@@ -0,0 +1,36 @@
1package getter
2
3import (
4 "strings"
5)
6
7// SourceDirSubdir takes a source and returns a tuple of the URL without
8// the subdir and the URL with the subdir.
9func SourceDirSubdir(src string) (string, string) {
10 // Calcaulate an offset to avoid accidentally marking the scheme
11 // as the dir.
12 var offset int
13 if idx := strings.Index(src, "://"); idx > -1 {
14 offset = idx + 3
15 }
16
17 // First see if we even have an explicit subdir
18 idx := strings.Index(src[offset:], "//")
19 if idx == -1 {
20 return src, ""
21 }
22
23 idx += offset
24 subdir := src[idx+2:]
25 src = src[:idx]
26
27 // Next, check if we have query parameters and push them onto the
28 // URL.
29 if idx = strings.Index(subdir, "?"); idx > -1 {
30 query := subdir[idx:]
31 subdir = subdir[:idx]
32 src += query
33 }
34
35 return src, subdir
36}
diff --git a/vendor/github.com/hashicorp/go-getter/storage.go b/vendor/github.com/hashicorp/go-getter/storage.go
new file mode 100644
index 0000000..2bc6b9e
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-getter/storage.go
@@ -0,0 +1,13 @@
1package getter
2
3// Storage is an interface that knows how to lookup downloaded directories
4// as well as download and update directories from their sources into the
5// proper location.
6type Storage interface {
7 // Dir returns the directory on local disk where the directory source
8 // can be loaded from.
9 Dir(string) (string, bool, error)
10
11 // Get will download and optionally update the given directory.
12 Get(string, string, bool) error
13}