command: Show snippet of invalid resource addresses in import
If we fail to parse the resource address given to "terraform import" then it's helpful to produce a "source code" snippet of what the user provided so they might see more precisely which part of the address was invalid.
This commit is contained in:
parent
27d086d8bd
commit
d63c2fdd8d
|
@ -62,9 +62,11 @@ func (c *ImportCommand) Run(args []string) int {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
// Parse the provided resource address.
|
// Parse the provided resource address.
|
||||||
traversal, travDiags := hclsyntax.ParseTraversalAbs([]byte(args[0]), "<import-address>", hcl.Pos{Line: 1, Column: 1})
|
traversalSrc := []byte(args[0])
|
||||||
|
traversal, travDiags := hclsyntax.ParseTraversalAbs(traversalSrc, "<import-address>", hcl.Pos{Line: 1, Column: 1})
|
||||||
diags = diags.Append(travDiags)
|
diags = diags.Append(travDiags)
|
||||||
if travDiags.HasErrors() {
|
if travDiags.HasErrors() {
|
||||||
|
c.registerSynthConfigSource("<import-address>", traversalSrc) // so we can include a source snippet
|
||||||
c.showDiagnostics(diags)
|
c.showDiagnostics(diags)
|
||||||
c.Ui.Info(importCommandInvalidAddressReference)
|
c.Ui.Info(importCommandInvalidAddressReference)
|
||||||
return 1
|
return 1
|
||||||
|
@ -72,6 +74,7 @@ func (c *ImportCommand) Run(args []string) int {
|
||||||
addr, addrDiags := addrs.ParseAbsResourceInstance(traversal)
|
addr, addrDiags := addrs.ParseAbsResourceInstance(traversal)
|
||||||
diags = diags.Append(addrDiags)
|
diags = diags.Append(addrDiags)
|
||||||
if addrDiags.HasErrors() {
|
if addrDiags.HasErrors() {
|
||||||
|
c.registerSynthConfigSource("<import-address>", traversalSrc) // so we can include a source snippet
|
||||||
c.showDiagnostics(diags)
|
c.showDiagnostics(diags)
|
||||||
c.Ui.Info(importCommandInvalidAddressReference)
|
c.Ui.Info(importCommandInvalidAddressReference)
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -594,7 +594,7 @@ func TestImport_dataResource(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := ui.ErrorWriter.String()
|
msg := ui.ErrorWriter.String()
|
||||||
if want := `resource address must refer to a managed resource`; !strings.Contains(msg, want) {
|
if want := `A managed resource address is required`; !strings.Contains(msg, want) {
|
||||||
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
|
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -624,7 +624,7 @@ func TestImport_invalidResourceAddr(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := ui.ErrorWriter.String()
|
msg := ui.ErrorWriter.String()
|
||||||
if want := `invalid resource address "bananas"`; !strings.Contains(msg, want) {
|
if want := `Error: Invalid address`; !strings.Contains(msg, want) {
|
||||||
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
|
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ func TestImport_targetIsModule(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := ui.ErrorWriter.String()
|
msg := ui.ErrorWriter.String()
|
||||||
if want := `resource address must include a full resource spec`; !strings.Contains(msg, want) {
|
if want := `Error: Invalid address`; !strings.Contains(msg, want) {
|
||||||
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
|
t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,6 +309,25 @@ func (m *Meta) modulesDir() string {
|
||||||
return filepath.Join(m.DataDir(), "modules")
|
return filepath.Join(m.DataDir(), "modules")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// registerSynthConfigSource allows commands to add synthetic additional source
|
||||||
|
// buffers to the config loader's cache of sources (as returned by
|
||||||
|
// configSources), which is useful when a command is directly parsing something
|
||||||
|
// from the command line that may produce diagnostics, so that diagnostic
|
||||||
|
// snippets can still be produced.
|
||||||
|
//
|
||||||
|
// If this is called before a configLoader has been initialized then it will
|
||||||
|
// try to initialize the loader but ignore any initialization failure, turning
|
||||||
|
// the call into a no-op. (We presume that a caller will later call a different
|
||||||
|
// function that also initializes the config loader as a side effect, at which
|
||||||
|
// point those errors can be returned.)
|
||||||
|
func (m *Meta) registerSynthConfigSource(filename string, src []byte) {
|
||||||
|
loader, err := m.initConfigLoader()
|
||||||
|
if err != nil || loader == nil {
|
||||||
|
return // treated as no-op, since this is best-effort
|
||||||
|
}
|
||||||
|
loader.Parser().ForceFileSource(filename, src)
|
||||||
|
}
|
||||||
|
|
||||||
// initConfigLoader initializes the shared configuration loader if it isn't
|
// initConfigLoader initializes the shared configuration loader if it isn't
|
||||||
// already initialized.
|
// already initialized.
|
||||||
//
|
//
|
||||||
|
|
Loading…
Reference in New Issue