aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform-config-inspect
diff options
context:
space:
mode:
authorNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
committerNathan Dench <ndenc2@gmail.com>2019-05-24 15:16:44 +1000
commit107c1cdb09c575aa2f61d97f48d8587eb6bada4c (patch)
treeca7d008643efc555c388baeaf1d986e0b6b3e28c /vendor/github.com/hashicorp/terraform-config-inspect
parent844b5a68d8af4791755b8f0ad293cc99f5959183 (diff)
downloadterraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.gz
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.tar.zst
terraform-provider-statuscake-107c1cdb09c575aa2f61d97f48d8587eb6bada4c.zip
Upgrade to 0.12
Diffstat (limited to 'vendor/github.com/hashicorp/terraform-config-inspect')
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/LICENSE353
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/diagnostic.go138
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/doc.go21
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load.go130
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_hcl.go322
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_legacy.go325
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module.go35
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module_call.go11
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/output.go9
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/provider_ref.go9
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/resource.go64
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/schema.go106
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/source_pos.go50
-rw-r--r--vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/variable.go16
14 files changed, 1589 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/LICENSE b/vendor/github.com/hashicorp/terraform-config-inspect/LICENSE
new file mode 100644
index 0000000..82b4de9
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/LICENSE
@@ -0,0 +1,353 @@
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.
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/diagnostic.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/diagnostic.go
new file mode 100644
index 0000000..8d04ad4
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/diagnostic.go
@@ -0,0 +1,138 @@
1package tfconfig
2
3import (
4 "fmt"
5
6 legacyhclparser "github.com/hashicorp/hcl/hcl/parser"
7 "github.com/hashicorp/hcl2/hcl"
8)
9
10// Diagnostic describes a problem (error or warning) encountered during
11// configuration loading.
12type Diagnostic struct {
13 Severity DiagSeverity `json:"severity"`
14 Summary string `json:"summary"`
15 Detail string `json:"detail,omitempty"`
16
17 // Pos is not populated for all diagnostics, but when populated should
18 // indicate a particular line that the described problem relates to.
19 Pos *SourcePos `json:"pos,omitempty"`
20}
21
22// Diagnostics represents a sequence of diagnostics. This is the type that
23// should be returned from a function that might generate diagnostics.
24type Diagnostics []Diagnostic
25
26// HasErrors returns true if there is at least one Diagnostic of severity
27// DiagError in the receiever.
28//
29// If a function returns a Diagnostics without errors then the result can
30// be assumed to be complete within the "best effort" constraints of this
31// library. If errors are present then the caller may wish to employ more
32// caution in relying on the result.
33func (diags Diagnostics) HasErrors() bool {
34 for _, diag := range diags {
35 if diag.Severity == DiagError {
36 return true
37 }
38 }
39 return false
40}
41
42func (diags Diagnostics) Error() string {
43 switch len(diags) {
44 case 0:
45 return "no problems"
46 case 1:
47 return fmt.Sprintf("%s: %s", diags[0].Summary, diags[0].Detail)
48 default:
49 return fmt.Sprintf("%s: %s (and %d other messages)", diags[0].Summary, diags[0].Detail, len(diags)-1)
50 }
51}
52
53// Err returns an error representing the receiver if the receiver HasErrors, or
54// nil otherwise.
55//
56// The returned error can be type-asserted back to a Diagnostics if needed.
57func (diags Diagnostics) Err() error {
58 if diags.HasErrors() {
59 return diags
60 }
61 return nil
62}
63
64// DiagSeverity describes the severity of a Diagnostic.
65type DiagSeverity rune
66
67// DiagError indicates a problem that prevented proper processing of the
68// configuration. In the precense of DiagError diagnostics the result is
69// likely to be incomplete.
70const DiagError DiagSeverity = 'E'
71
72// DiagWarning indicates a problem that the user may wish to consider but
73// that did not prevent proper processing of the configuration.
74const DiagWarning DiagSeverity = 'W'
75
76// MarshalJSON is an implementation of encoding/json.Marshaler
77func (s DiagSeverity) MarshalJSON() ([]byte, error) {
78 switch s {
79 case DiagError:
80 return []byte(`"error"`), nil
81 case DiagWarning:
82 return []byte(`"warning"`), nil
83 default:
84 return []byte(`"invalid"`), nil
85 }
86}
87
88func diagnosticsHCL(diags hcl.Diagnostics) Diagnostics {
89 if len(diags) == 0 {
90 return nil
91 }
92 ret := make(Diagnostics, len(diags))
93 for i, diag := range diags {
94 ret[i] = Diagnostic{
95 Summary: diag.Summary,
96 Detail: diag.Detail,
97 }
98 switch diag.Severity {
99 case hcl.DiagError:
100 ret[i].Severity = DiagError
101 case hcl.DiagWarning:
102 ret[i].Severity = DiagWarning
103 }
104 if diag.Subject != nil {
105 pos := sourcePosHCL(*diag.Subject)
106 ret[i].Pos = &pos
107 }
108 }
109 return ret
110}
111
112func diagnosticsError(err error) Diagnostics {
113 if err == nil {
114 return nil
115 }
116
117 if posErr, ok := err.(*legacyhclparser.PosError); ok {
118 pos := sourcePosLegacyHCL(posErr.Pos, "")
119 return Diagnostics{
120 Diagnostic{
121 Severity: DiagError,
122 Summary: posErr.Err.Error(),
123 Pos: &pos,
124 },
125 }
126 }
127
128 return Diagnostics{
129 Diagnostic{
130 Severity: DiagError,
131 Summary: err.Error(),
132 },
133 }
134}
135
136func diagnosticsErrorf(format string, args ...interface{}) Diagnostics {
137 return diagnosticsError(fmt.Errorf(format, args...))
138}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/doc.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/doc.go
new file mode 100644
index 0000000..1604a6e
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/doc.go
@@ -0,0 +1,21 @@
1// Package tfconfig is a helper library that does careful, shallow parsing of
2// Terraform modules to provide access to high-level metadata while
3// remaining broadly compatible with configurations targeting various
4// different Terraform versions.
5//
6// This packge focuses on describing top-level objects only, and in particular
7// does not attempt any sort of processing that would require access to plugins.
8// Currently it allows callers to extract high-level information about
9// variables, outputs, resource blocks, provider dependencies, and Terraform
10// Core dependencies.
11//
12// This package only works at the level of single modules. A full configuration
13// is a tree of potentially several modules, some of which may be references
14// to remote packages. There are some basic helpers for traversing calls to
15// modules at relative local paths, however.
16//
17// This package employs a "best effort" parsing strategy, producing as complete
18// a result as possible even though the input may not be entirely valid. The
19// intended use-case is high-level analysis and indexing of externally-facing
20// module characteristics, as opposed to validating or even applying the module.
21package tfconfig
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load.go
new file mode 100644
index 0000000..2d13fe1
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load.go
@@ -0,0 +1,130 @@
1package tfconfig
2
3import (
4 "fmt"
5 "io/ioutil"
6 "path/filepath"
7 "strings"
8
9 "github.com/hashicorp/hcl2/hcl"
10)
11
12// LoadModule reads the directory at the given path and attempts to interpret
13// it as a Terraform module.
14func LoadModule(dir string) (*Module, Diagnostics) {
15
16 // For broad compatibility here we actually have two separate loader
17 // codepaths. The main one uses the new HCL parser and API and is intended
18 // for configurations from Terraform 0.12 onwards (though will work for
19 // many older configurations too), but we'll also fall back on one that
20 // uses the _old_ HCL implementation so we can deal with some edge-cases
21 // that are not valid in new HCL.
22
23 module, diags := loadModule(dir)
24 if diags.HasErrors() {
25 // Try using the legacy HCL parser and see if we fare better.
26 legacyModule, legacyDiags := loadModuleLegacyHCL(dir)
27 if !legacyDiags.HasErrors() {
28 legacyModule.init(legacyDiags)
29 return legacyModule, legacyDiags
30 }
31 }
32
33 module.init(diags)
34 return module, diags
35}
36
37// IsModuleDir checks if the given path contains terraform configuration files.
38// This allows the caller to decide how to handle directories that do not have tf files.
39func IsModuleDir(dir string) bool {
40 primaryPaths, _ := dirFiles(dir)
41 if len(primaryPaths) == 0 {
42 return false
43 }
44 return true
45}
46
47func (m *Module) init(diags Diagnostics) {
48 // Fill in any additional provider requirements that are implied by
49 // resource configurations, to avoid the caller from needing to apply
50 // this logic itself. Implied requirements don't have version constraints,
51 // but we'll make sure the requirement value is still non-nil in this
52 // case so callers can easily recognize it.
53 for _, r := range m.ManagedResources {
54 if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
55 m.RequiredProviders[r.Provider.Name] = []string{}
56 }
57 }
58 for _, r := range m.DataResources {
59 if _, exists := m.RequiredProviders[r.Provider.Name]; !exists {
60 m.RequiredProviders[r.Provider.Name] = []string{}
61 }
62 }
63
64 // We redundantly also reference the diagnostics from inside the module
65 // object, primarily so that we can easily included in JSON-serialized
66 // versions of the module object.
67 m.Diagnostics = diags
68}
69
70func dirFiles(dir string) (primary []string, diags hcl.Diagnostics) {
71 infos, err := ioutil.ReadDir(dir)
72 if err != nil {
73 diags = append(diags, &hcl.Diagnostic{
74 Severity: hcl.DiagError,
75 Summary: "Failed to read module directory",
76 Detail: fmt.Sprintf("Module directory %s does not exist or cannot be read.", dir),
77 })
78 return
79 }
80
81 var override []string
82 for _, info := range infos {
83 if info.IsDir() {
84 // We only care about files
85 continue
86 }
87
88 name := info.Name()
89 ext := fileExt(name)
90 if ext == "" || isIgnoredFile(name) {
91 continue
92 }
93
94 baseName := name[:len(name)-len(ext)] // strip extension
95 isOverride := baseName == "override" || strings.HasSuffix(baseName, "_override")
96
97 fullPath := filepath.Join(dir, name)
98 if isOverride {
99 override = append(override, fullPath)
100 } else {
101 primary = append(primary, fullPath)
102 }
103 }
104
105 // We are assuming that any _override files will be logically named,
106 // and processing the files in alphabetical order. Primaries first, then overrides.
107 primary = append(primary, override...)
108
109 return
110}
111
112// fileExt returns the Terraform configuration extension of the given
113// path, or a blank string if it is not a recognized extension.
114func fileExt(path string) string {
115 if strings.HasSuffix(path, ".tf") {
116 return ".tf"
117 } else if strings.HasSuffix(path, ".tf.json") {
118 return ".tf.json"
119 } else {
120 return ""
121 }
122}
123
124// isIgnoredFile returns true if the given filename (which must not have a
125// directory path ahead of it) should be ignored as e.g. an editor swap file.
126func isIgnoredFile(name string) bool {
127 return strings.HasPrefix(name, ".") || // Unix-like hidden files
128 strings.HasSuffix(name, "~") || // vim
129 strings.HasPrefix(name, "#") && strings.HasSuffix(name, "#") // emacs
130}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_hcl.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_hcl.go
new file mode 100644
index 0000000..72b5d4a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_hcl.go
@@ -0,0 +1,322 @@
1package tfconfig
2
3import (
4 "encoding/json"
5 "fmt"
6 "strings"
7
8 "github.com/hashicorp/hcl2/hcl/hclsyntax"
9
10 "github.com/hashicorp/hcl2/gohcl"
11 "github.com/hashicorp/hcl2/hcl"
12 "github.com/hashicorp/hcl2/hclparse"
13 ctyjson "github.com/zclconf/go-cty/cty/json"
14)
15
16func loadModule(dir string) (*Module, Diagnostics) {
17 mod := newModule(dir)
18 primaryPaths, diags := dirFiles(dir)
19
20 parser := hclparse.NewParser()
21
22 for _, filename := range primaryPaths {
23 var file *hcl.File
24 var fileDiags hcl.Diagnostics
25 if strings.HasSuffix(filename, ".json") {
26 file, fileDiags = parser.ParseJSONFile(filename)
27 } else {
28 file, fileDiags = parser.ParseHCLFile(filename)
29 }
30 diags = append(diags, fileDiags...)
31 if file == nil {
32 continue
33 }
34
35 content, _, contentDiags := file.Body.PartialContent(rootSchema)
36 diags = append(diags, contentDiags...)
37
38 for _, block := range content.Blocks {
39 switch block.Type {
40
41 case "terraform":
42 content, _, contentDiags := block.Body.PartialContent(terraformBlockSchema)
43 diags = append(diags, contentDiags...)
44
45 if attr, defined := content.Attributes["required_version"]; defined {
46 var version string
47 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
48 diags = append(diags, valDiags...)
49 if !valDiags.HasErrors() {
50 mod.RequiredCore = append(mod.RequiredCore, version)
51 }
52 }
53
54 for _, block := range content.Blocks {
55 // Our schema only allows required_providers here, so we
56 // assume that we'll only get that block type.
57 attrs, attrDiags := block.Body.JustAttributes()
58 diags = append(diags, attrDiags...)
59
60 for name, attr := range attrs {
61 var version string
62 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
63 diags = append(diags, valDiags...)
64 if !valDiags.HasErrors() {
65 mod.RequiredProviders[name] = append(mod.RequiredProviders[name], version)
66 }
67 }
68 }
69
70 case "variable":
71 content, _, contentDiags := block.Body.PartialContent(variableSchema)
72 diags = append(diags, contentDiags...)
73
74 name := block.Labels[0]
75 v := &Variable{
76 Name: name,
77 Pos: sourcePosHCL(block.DefRange),
78 }
79
80 mod.Variables[name] = v
81
82 if attr, defined := content.Attributes["type"]; defined {
83 // We handle this particular attribute in a somewhat-tricky way:
84 // since Terraform may evolve its type expression syntax in
85 // future versions, we don't want to be overly-strict in how
86 // we handle it here, and so we'll instead just take the raw
87 // source provided by the user, using the source location
88 // information in the expression object.
89 //
90 // However, older versions of Terraform expected the type
91 // to be a string containing a keyword, so we'll need to
92 // handle that as a special case first for backward compatibility.
93
94 var typeExpr string
95
96 var typeExprAsStr string
97 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &typeExprAsStr)
98 if !valDiags.HasErrors() {
99 typeExpr = typeExprAsStr
100 } else {
101
102 rng := attr.Expr.Range()
103 sourceFilename := rng.Filename
104 source, exists := parser.Sources()[sourceFilename]
105 if exists {
106 typeExpr = string(rng.SliceBytes(source))
107 } else {
108 // This should never happen, so we'll just warn about it and leave the type unspecified.
109 diags = append(diags, &hcl.Diagnostic{
110 Severity: hcl.DiagError,
111 Summary: "Source code not available",
112 Detail: fmt.Sprintf("Source code is not available for the file %q, which declares the variable %q.", sourceFilename, name),
113 Subject: &block.DefRange,
114 })
115 typeExpr = ""
116 }
117
118 }
119
120 v.Type = typeExpr
121 }
122
123 if attr, defined := content.Attributes["description"]; defined {
124 var description string
125 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &description)
126 diags = append(diags, valDiags...)
127 v.Description = description
128 }
129
130 if attr, defined := content.Attributes["default"]; defined {
131 // To avoid the caller needing to deal with cty here, we'll
132 // use its JSON encoding to convert into an
133 // approximately-equivalent plain Go interface{} value
134 // to return.
135 val, valDiags := attr.Expr.Value(nil)
136 diags = append(diags, valDiags...)
137 if val.IsWhollyKnown() { // should only be false if there are errors in the input
138 valJSON, err := ctyjson.Marshal(val, val.Type())
139 if err != nil {
140 // Should never happen, since all possible known
141 // values have a JSON mapping.
142 panic(fmt.Errorf("failed to serialize default value as JSON: %s", err))
143 }
144 var def interface{}
145 err = json.Unmarshal(valJSON, &def)
146 if err != nil {
147 // Again should never happen, because valJSON is
148 // guaranteed valid by ctyjson.Marshal.
149 panic(fmt.Errorf("failed to re-parse default value from JSON: %s", err))
150 }
151 v.Default = def
152 }
153 }
154
155 case "output":
156
157 content, _, contentDiags := block.Body.PartialContent(outputSchema)
158 diags = append(diags, contentDiags...)
159
160 name := block.Labels[0]
161 o := &Output{
162 Name: name,
163 Pos: sourcePosHCL(block.DefRange),
164 }
165
166 mod.Outputs[name] = o
167
168 if attr, defined := content.Attributes["description"]; defined {
169 var description string
170 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &description)
171 diags = append(diags, valDiags...)
172 o.Description = description
173 }
174
175 case "provider":
176
177 content, _, contentDiags := block.Body.PartialContent(providerConfigSchema)
178 diags = append(diags, contentDiags...)
179
180 name := block.Labels[0]
181
182 if attr, defined := content.Attributes["version"]; defined {
183 var version string
184 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
185 diags = append(diags, valDiags...)
186 if !valDiags.HasErrors() {
187 mod.RequiredProviders[name] = append(mod.RequiredProviders[name], version)
188 }
189 }
190
191 // Even if there wasn't an explicit version required, we still
192 // need an entry in our map to signal the unversioned dependency.
193 if _, exists := mod.RequiredProviders[name]; !exists {
194 mod.RequiredProviders[name] = []string{}
195 }
196
197 case "resource", "data":
198
199 content, _, contentDiags := block.Body.PartialContent(resourceSchema)
200 diags = append(diags, contentDiags...)
201
202 typeName := block.Labels[0]
203 name := block.Labels[1]
204
205 r := &Resource{
206 Type: typeName,
207 Name: name,
208 Pos: sourcePosHCL(block.DefRange),
209 }
210
211 var resourcesMap map[string]*Resource
212
213 switch block.Type {
214 case "resource":
215 r.Mode = ManagedResourceMode
216 resourcesMap = mod.ManagedResources
217 case "data":
218 r.Mode = DataResourceMode
219 resourcesMap = mod.DataResources
220 }
221
222 key := r.MapKey()
223
224 resourcesMap[key] = r
225
226 if attr, defined := content.Attributes["provider"]; defined {
227 // New style here is to provide this as a naked traversal
228 // expression, but we also support quoted references for
229 // older configurations that predated this convention.
230 traversal, travDiags := hcl.AbsTraversalForExpr(attr.Expr)
231 if travDiags.HasErrors() {
232 traversal = nil // in case we got any partial results
233
234 // Fall back on trying to parse as a string
235 var travStr string
236 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &travStr)
237 if !valDiags.HasErrors() {
238 var strDiags hcl.Diagnostics
239 traversal, strDiags = hclsyntax.ParseTraversalAbs([]byte(travStr), "", hcl.Pos{})
240 if strDiags.HasErrors() {
241 traversal = nil
242 }
243 }
244 }
245
246 // If we get out here with a nil traversal then we didn't
247 // succeed in processing the input.
248 if len(traversal) > 0 {
249 providerName := traversal.RootName()
250 alias := ""
251 if len(traversal) > 1 {
252 if getAttr, ok := traversal[1].(hcl.TraverseAttr); ok {
253 alias = getAttr.Name
254 }
255 }
256 r.Provider = ProviderRef{
257 Name: providerName,
258 Alias: alias,
259 }
260 } else {
261 diags = append(diags, &hcl.Diagnostic{
262 Severity: hcl.DiagError,
263 Summary: "Invalid provider reference",
264 Detail: "Provider argument requires a provider name followed by an optional alias, like \"aws.foo\".",
265 Subject: attr.Expr.Range().Ptr(),
266 })
267 }
268 } else {
269 // If provider _isn't_ set then we'll infer it from the
270 // resource type.
271 r.Provider = ProviderRef{
272 Name: resourceTypeDefaultProviderName(r.Type),
273 }
274 }
275
276 case "module":
277
278 content, _, contentDiags := block.Body.PartialContent(moduleCallSchema)
279 diags = append(diags, contentDiags...)
280
281 name := block.Labels[0]
282 mc := &ModuleCall{
283 Name: block.Labels[0],
284 Pos: sourcePosHCL(block.DefRange),
285 }
286
287 // check if this is overriding an existing module
288 var origSource string
289 if origMod, exists := mod.ModuleCalls[name]; exists {
290 origSource = origMod.Source
291 }
292
293 mod.ModuleCalls[name] = mc
294
295 if attr, defined := content.Attributes["source"]; defined {
296 var source string
297 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &source)
298 diags = append(diags, valDiags...)
299 mc.Source = source
300 }
301
302 if mc.Source == "" {
303 mc.Source = origSource
304 }
305
306 if attr, defined := content.Attributes["version"]; defined {
307 var version string
308 valDiags := gohcl.DecodeExpression(attr.Expr, nil, &version)
309 diags = append(diags, valDiags...)
310 mc.Version = version
311 }
312
313 default:
314 // Should never happen because our cases above should be
315 // exhaustive for our schema.
316 panic(fmt.Errorf("unhandled block type %q", block.Type))
317 }
318 }
319 }
320
321 return mod, diagnosticsHCL(diags)
322}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_legacy.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_legacy.go
new file mode 100644
index 0000000..86ffdf1
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/load_legacy.go
@@ -0,0 +1,325 @@
1package tfconfig
2
3import (
4 "io/ioutil"
5 "strings"
6
7 legacyhcl "github.com/hashicorp/hcl"
8 legacyast "github.com/hashicorp/hcl/hcl/ast"
9)
10
11func loadModuleLegacyHCL(dir string) (*Module, Diagnostics) {
12 // This implementation is intentionally more quick-and-dirty than the
13 // main loader. In particular, it doesn't bother to keep careful track
14 // of multiple error messages because we always fall back on returning
15 // the main parser's error message if our fallback parsing produces
16 // an error, and thus the errors here are not seen by the end-caller.
17 mod := newModule(dir)
18
19 primaryPaths, diags := dirFiles(dir)
20 if diags.HasErrors() {
21 return mod, diagnosticsHCL(diags)
22 }
23
24 for _, filename := range primaryPaths {
25 src, err := ioutil.ReadFile(filename)
26 if err != nil {
27 return mod, diagnosticsErrorf("Error reading %s: %s", filename, err)
28 }
29
30 hclRoot, err := legacyhcl.Parse(string(src))
31 if err != nil {
32 return mod, diagnosticsErrorf("Error parsing %s: %s", filename, err)
33 }
34
35 list, ok := hclRoot.Node.(*legacyast.ObjectList)
36 if !ok {
37 return mod, diagnosticsErrorf("Error parsing %s: no root object", filename)
38 }
39
40 for _, item := range list.Filter("terraform").Items {
41 if len(item.Keys) > 0 {
42 item = &legacyast.ObjectItem{
43 Val: &legacyast.ObjectType{
44 List: &legacyast.ObjectList{
45 Items: []*legacyast.ObjectItem{item},
46 },
47 },
48 }
49 }
50
51 type TerraformBlock struct {
52 RequiredVersion string `hcl:"required_version"`
53 }
54 var block TerraformBlock
55 err = legacyhcl.DecodeObject(&block, item.Val)
56 if err != nil {
57 return nil, diagnosticsErrorf("terraform block: %s", err)
58 }
59
60 if block.RequiredVersion != "" {
61 mod.RequiredCore = append(mod.RequiredCore, block.RequiredVersion)
62 }
63 }
64
65 if vars := list.Filter("variable"); len(vars.Items) > 0 {
66 vars = vars.Children()
67 type VariableBlock struct {
68 Type string `hcl:"type"`
69 Default interface{}
70 Description string
71 Fields []string `hcl:",decodedFields"`
72 }
73
74 for _, item := range vars.Items {
75 unwrapLegacyHCLObjectKeysFromJSON(item, 1)
76
77 if len(item.Keys) != 1 {
78 return nil, diagnosticsErrorf("variable block at %s has no label", item.Pos())
79 }
80
81 name := item.Keys[0].Token.Value().(string)
82
83 var block VariableBlock
84 err := legacyhcl.DecodeObject(&block, item.Val)
85 if err != nil {
86 return nil, diagnosticsErrorf("invalid variable block at %s: %s", item.Pos(), err)
87 }
88
89 // Clean up legacy HCL decoding ambiguity by unwrapping list of maps
90 if ms, ok := block.Default.([]map[string]interface{}); ok {
91 def := make(map[string]interface{})
92 for _, m := range ms {
93 for k, v := range m {
94 def[k] = v
95 }
96 }
97 block.Default = def
98 }
99
100 v := &Variable{
101 Name: name,
102 Type: block.Type,
103 Description: block.Description,
104 Default: block.Default,
105 Pos: sourcePosLegacyHCL(item.Pos(), filename),
106 }
107 if _, exists := mod.Variables[name]; exists {
108 return nil, diagnosticsErrorf("duplicate variable block for %q", name)
109 }
110 mod.Variables[name] = v
111
112 }
113 }
114
115 if outputs := list.Filter("output"); len(outputs.Items) > 0 {
116 outputs = outputs.Children()
117 type OutputBlock struct {
118 Description string
119 }
120
121 for _, item := range outputs.Items {
122 unwrapLegacyHCLObjectKeysFromJSON(item, 1)
123
124 if len(item.Keys) != 1 {
125 return nil, diagnosticsErrorf("output block at %s has no label", item.Pos())
126 }
127
128 name := item.Keys[0].Token.Value().(string)
129
130 var block OutputBlock
131 err := legacyhcl.DecodeObject(&block, item.Val)
132 if err != nil {
133 return nil, diagnosticsErrorf("invalid output block at %s: %s", item.Pos(), err)
134 }
135
136 o := &Output{
137 Name: name,
138 Description: block.Description,
139 Pos: sourcePosLegacyHCL(item.Pos(), filename),
140 }
141 if _, exists := mod.Outputs[name]; exists {
142 return nil, diagnosticsErrorf("duplicate output block for %q", name)
143 }
144 mod.Outputs[name] = o
145 }
146 }
147
148 for _, blockType := range []string{"resource", "data"} {
149 if resources := list.Filter(blockType); len(resources.Items) > 0 {
150 resources = resources.Children()
151 type ResourceBlock struct {
152 Provider string
153 }
154
155 for _, item := range resources.Items {
156 unwrapLegacyHCLObjectKeysFromJSON(item, 2)
157
158 if len(item.Keys) != 2 {
159 return nil, diagnosticsErrorf("resource block at %s has wrong label count", item.Pos())
160 }
161
162 typeName := item.Keys[0].Token.Value().(string)
163 name := item.Keys[1].Token.Value().(string)
164 var mode ResourceMode
165 var rMap map[string]*Resource
166 switch blockType {
167 case "resource":
168 mode = ManagedResourceMode
169 rMap = mod.ManagedResources
170 case "data":
171 mode = DataResourceMode
172 rMap = mod.DataResources
173 }
174
175 var block ResourceBlock
176 err := legacyhcl.DecodeObject(&block, item.Val)
177 if err != nil {
178 return nil, diagnosticsErrorf("invalid resource block at %s: %s", item.Pos(), err)
179 }
180
181 var providerName, providerAlias string
182 if dotPos := strings.IndexByte(block.Provider, '.'); dotPos != -1 {
183 providerName = block.Provider[:dotPos]
184 providerAlias = block.Provider[dotPos+1:]
185 } else {
186 providerName = block.Provider
187 }
188 if providerName == "" {
189 providerName = resourceTypeDefaultProviderName(typeName)
190 }
191
192 r := &Resource{
193 Mode: mode,
194 Type: typeName,
195 Name: name,
196 Provider: ProviderRef{
197 Name: providerName,
198 Alias: providerAlias,
199 },
200 Pos: sourcePosLegacyHCL(item.Pos(), filename),
201 }
202 key := r.MapKey()
203 if _, exists := rMap[key]; exists {
204 return nil, diagnosticsErrorf("duplicate resource block for %q", key)
205 }
206 rMap[key] = r
207 }
208 }
209
210 }
211
212 if moduleCalls := list.Filter("module"); len(moduleCalls.Items) > 0 {
213 moduleCalls = moduleCalls.Children()
214 type ModuleBlock struct {
215 Source string
216 Version string
217 }
218
219 for _, item := range moduleCalls.Items {
220 unwrapLegacyHCLObjectKeysFromJSON(item, 1)
221
222 if len(item.Keys) != 1 {
223 return nil, diagnosticsErrorf("module block at %s has no label", item.Pos())
224 }
225
226 name := item.Keys[0].Token.Value().(string)
227
228 var block ModuleBlock
229 err := legacyhcl.DecodeObject(&block, item.Val)
230 if err != nil {
231 return nil, diagnosticsErrorf("module block at %s: %s", item.Pos(), err)
232 }
233
234 mc := &ModuleCall{
235 Name: name,
236 Source: block.Source,
237 Version: block.Version,
238 Pos: sourcePosLegacyHCL(item.Pos(), filename),
239 }
240 // it's possible this module call is from an override file
241 if origMod, exists := mod.ModuleCalls[name]; exists {
242 if mc.Source == "" {
243 mc.Source = origMod.Source
244 }
245 }
246 mod.ModuleCalls[name] = mc
247 }
248 }
249
250 if providerConfigs := list.Filter("provider"); len(providerConfigs.Items) > 0 {
251 providerConfigs = providerConfigs.Children()
252 type ProviderBlock struct {
253 Version string
254 }
255
256 for _, item := range providerConfigs.Items {
257 unwrapLegacyHCLObjectKeysFromJSON(item, 1)
258
259 if len(item.Keys) != 1 {
260 return nil, diagnosticsErrorf("provider block at %s has no label", item.Pos())
261 }
262
263 name := item.Keys[0].Token.Value().(string)
264
265 var block ProviderBlock
266 err := legacyhcl.DecodeObject(&block, item.Val)
267 if err != nil {
268 return nil, diagnosticsErrorf("invalid provider block at %s: %s", item.Pos(), err)
269 }
270
271 if block.Version != "" {
272 mod.RequiredProviders[name] = append(mod.RequiredProviders[name], block.Version)
273 }
274
275 // Even if there wasn't an explicit version required, we still
276 // need an entry in our map to signal the unversioned dependency.
277 if _, exists := mod.RequiredProviders[name]; !exists {
278 mod.RequiredProviders[name] = []string{}
279 }
280
281 }
282 }
283 }
284
285 return mod, nil
286}
287
288// unwrapLegacyHCLObjectKeysFromJSON cleans up an edge case that can occur when
289// parsing JSON as input: if we're parsing JSON then directly nested
290// items will show up as additional "keys".
291//
292// For objects that expect a fixed number of keys, this breaks the
293// decoding process. This function unwraps the object into what it would've
294// looked like if it came directly from HCL by specifying the number of keys
295// you expect.
296//
297// Example:
298//
299// { "foo": { "baz": {} } }
300//
301// Will show up with Keys being: []string{"foo", "baz"}
302// when we really just want the first two. This function will fix this.
303func unwrapLegacyHCLObjectKeysFromJSON(item *legacyast.ObjectItem, depth int) {
304 if len(item.Keys) > depth && item.Keys[0].Token.JSON {
305 for len(item.Keys) > depth {
306 // Pop off the last key
307 n := len(item.Keys)
308 key := item.Keys[n-1]
309 item.Keys[n-1] = nil
310 item.Keys = item.Keys[:n-1]
311
312 // Wrap our value in a list
313 item.Val = &legacyast.ObjectType{
314 List: &legacyast.ObjectList{
315 Items: []*legacyast.ObjectItem{
316 &legacyast.ObjectItem{
317 Keys: []*legacyast.ObjectKey{key},
318 Val: item.Val,
319 },
320 },
321 },
322 }
323 }
324 }
325}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module.go
new file mode 100644
index 0000000..65ddb23
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module.go
@@ -0,0 +1,35 @@
1package tfconfig
2
3// Module is the top-level type representing a parsed and processed Terraform
4// module.
5type Module struct {
6 // Path is the local filesystem directory where the module was loaded from.
7 Path string `json:"path"`
8
9 Variables map[string]*Variable `json:"variables"`
10 Outputs map[string]*Output `json:"outputs"`
11
12 RequiredCore []string `json:"required_core,omitempty"`
13 RequiredProviders map[string][]string `json:"required_providers"`
14
15 ManagedResources map[string]*Resource `json:"managed_resources"`
16 DataResources map[string]*Resource `json:"data_resources"`
17 ModuleCalls map[string]*ModuleCall `json:"module_calls"`
18
19 // Diagnostics records any errors and warnings that were detected during
20 // loading, primarily for inclusion in serialized forms of the module
21 // since this slice is also returned as a second argument from LoadModule.
22 Diagnostics Diagnostics `json:"diagnostics,omitempty"`
23}
24
25func newModule(path string) *Module {
26 return &Module{
27 Path: path,
28 Variables: make(map[string]*Variable),
29 Outputs: make(map[string]*Output),
30 RequiredProviders: make(map[string][]string),
31 ManagedResources: make(map[string]*Resource),
32 DataResources: make(map[string]*Resource),
33 ModuleCalls: make(map[string]*ModuleCall),
34 }
35}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module_call.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module_call.go
new file mode 100644
index 0000000..5e1e05a
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/module_call.go
@@ -0,0 +1,11 @@
1package tfconfig
2
3// ModuleCall represents a "module" block within a module. That is, a
4// declaration of a child module from inside its parent.
5type ModuleCall struct {
6 Name string `json:"name"`
7 Source string `json:"source"`
8 Version string `json:"version,omitempty"`
9
10 Pos SourcePos `json:"pos"`
11}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/output.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/output.go
new file mode 100644
index 0000000..890b25e
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/output.go
@@ -0,0 +1,9 @@
1package tfconfig
2
3// Output represents a single output from a Terraform module.
4type Output struct {
5 Name string `json:"name"`
6 Description string `json:"description,omitempty"`
7
8 Pos SourcePos `json:"pos"`
9}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/provider_ref.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/provider_ref.go
new file mode 100644
index 0000000..d924837
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/provider_ref.go
@@ -0,0 +1,9 @@
1package tfconfig
2
3// ProviderRef is a reference to a provider configuration within a module.
4// It represents the contents of a "provider" argument in a resource, or
5// a value in the "providers" map for a module call.
6type ProviderRef struct {
7 Name string `json:"name"`
8 Alias string `json:"alias,omitempty"` // Empty if the default provider configuration is referenced
9}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/resource.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/resource.go
new file mode 100644
index 0000000..401c8fc
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/resource.go
@@ -0,0 +1,64 @@
1package tfconfig
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7)
8
9// Resource represents a single "resource" or "data" block within a module.
10type Resource struct {
11 Mode ResourceMode `json:"mode"`
12 Type string `json:"type"`
13 Name string `json:"name"`
14
15 Provider ProviderRef `json:"provider"`
16
17 Pos SourcePos `json:"pos"`
18}
19
20// MapKey returns a string that can be used to uniquely identify the receiver
21// in a map[string]*Resource.
22func (r *Resource) MapKey() string {
23 switch r.Mode {
24 case ManagedResourceMode:
25 return fmt.Sprintf("%s.%s", r.Type, r.Name)
26 case DataResourceMode:
27 return fmt.Sprintf("data.%s.%s", r.Type, r.Name)
28 default:
29 // should never happen
30 return fmt.Sprintf("[invalid_mode!].%s.%s", r.Type, r.Name)
31 }
32}
33
34// ResourceMode represents the "mode" of a resource, which is used to
35// distinguish between managed resources ("resource" blocks in config) and
36// data resources ("data" blocks in config).
37type ResourceMode rune
38
39const InvalidResourceMode ResourceMode = 0
40const ManagedResourceMode ResourceMode = 'M'
41const DataResourceMode ResourceMode = 'D'
42
43func (m ResourceMode) String() string {
44 switch m {
45 case ManagedResourceMode:
46 return "managed"
47 case DataResourceMode:
48 return "data"
49 default:
50 return ""
51 }
52}
53
54// MarshalJSON implements encoding/json.Marshaler.
55func (m ResourceMode) MarshalJSON() ([]byte, error) {
56 return []byte(strconv.Quote(m.String())), nil
57}
58
59func resourceTypeDefaultProviderName(typeName string) string {
60 if underPos := strings.IndexByte(typeName, '_'); underPos != -1 {
61 return typeName[:underPos]
62 }
63 return typeName
64}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/schema.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/schema.go
new file mode 100644
index 0000000..3af742f
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/schema.go
@@ -0,0 +1,106 @@
1package tfconfig
2
3import (
4 "github.com/hashicorp/hcl2/hcl"
5)
6
7var rootSchema = &hcl.BodySchema{
8 Blocks: []hcl.BlockHeaderSchema{
9 {
10 Type: "terraform",
11 LabelNames: nil,
12 },
13 {
14 Type: "variable",
15 LabelNames: []string{"name"},
16 },
17 {
18 Type: "output",
19 LabelNames: []string{"name"},
20 },
21 {
22 Type: "provider",
23 LabelNames: []string{"name"},
24 },
25 {
26 Type: "resource",
27 LabelNames: []string{"type", "name"},
28 },
29 {
30 Type: "data",
31 LabelNames: []string{"type", "name"},
32 },
33 {
34 Type: "module",
35 LabelNames: []string{"name"},
36 },
37 },
38}
39
40var terraformBlockSchema = &hcl.BodySchema{
41 Attributes: []hcl.AttributeSchema{
42 {
43 Name: "required_version",
44 },
45 },
46 Blocks: []hcl.BlockHeaderSchema{
47 {
48 Type: "required_providers",
49 },
50 },
51}
52
53var providerConfigSchema = &hcl.BodySchema{
54 Attributes: []hcl.AttributeSchema{
55 {
56 Name: "version",
57 },
58 {
59 Name: "alias",
60 },
61 },
62}
63
64var variableSchema = &hcl.BodySchema{
65 Attributes: []hcl.AttributeSchema{
66 {
67 Name: "type",
68 },
69 {
70 Name: "description",
71 },
72 {
73 Name: "default",
74 },
75 },
76}
77
78var outputSchema = &hcl.BodySchema{
79 Attributes: []hcl.AttributeSchema{
80 {
81 Name: "description",
82 },
83 },
84}
85
86var moduleCallSchema = &hcl.BodySchema{
87 Attributes: []hcl.AttributeSchema{
88 {
89 Name: "source",
90 },
91 {
92 Name: "version",
93 },
94 {
95 Name: "providers",
96 },
97 },
98}
99
100var resourceSchema = &hcl.BodySchema{
101 Attributes: []hcl.AttributeSchema{
102 {
103 Name: "provider",
104 },
105 },
106}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/source_pos.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/source_pos.go
new file mode 100644
index 0000000..883914e
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/source_pos.go
@@ -0,0 +1,50 @@
1package tfconfig
2
3import (
4 legacyhcltoken "github.com/hashicorp/hcl/hcl/token"
5 "github.com/hashicorp/hcl2/hcl"
6)
7
8// SourcePos is a pointer to a particular location in a source file.
9//
10// This type is embedded into other structs to allow callers to locate the
11// definition of each described module element. The SourcePos of an element
12// is usually the first line of its definition, although the definition can
13// be a little "fuzzy" with JSON-based config files.
14type SourcePos struct {
15 Filename string `json:"filename"`
16 Line int `json:"line"`
17}
18
19func sourcePos(filename string, line int) SourcePos {
20 return SourcePos{
21 Filename: filename,
22 Line: line,
23 }
24}
25
26func sourcePosHCL(rng hcl.Range) SourcePos {
27 // We intentionally throw away the column information here because
28 // current and legacy HCL both disagree on the definition of a column
29 // and so a line-only reference is the best granularity we can do
30 // such that the result is consistent between both parsers.
31 return SourcePos{
32 Filename: rng.Filename,
33 Line: rng.Start.Line,
34 }
35}
36
37func sourcePosLegacyHCL(pos legacyhcltoken.Pos, filename string) SourcePos {
38 useFilename := pos.Filename
39 // We'll try to use the filename given in legacy HCL position, but
40 // in practice there's no way to actually get this populated via
41 // the HCL API so it's usually empty except in some specialized
42 // situations, such as positions in error objects.
43 if useFilename == "" {
44 useFilename = filename
45 }
46 return SourcePos{
47 Filename: useFilename,
48 Line: pos.Line,
49 }
50}
diff --git a/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/variable.go b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/variable.go
new file mode 100644
index 0000000..0f73fc9
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform-config-inspect/tfconfig/variable.go
@@ -0,0 +1,16 @@
1package tfconfig
2
3// Variable represents a single variable from a Terraform module.
4type Variable struct {
5 Name string `json:"name"`
6 Type string `json:"type,omitempty"`
7 Description string `json:"description,omitempty"`
8
9 // Default is an approximate representation of the default value in
10 // the native Go type system. The conversion from the value given in
11 // configuration may be slightly lossy. Only values that can be
12 // serialized by json.Marshal will be included here.
13 Default interface{} `json:"default,omitempty"`
14
15 Pos SourcePos `json:"pos"`
16}