diff --git a/internal/addrs/parse_target.go b/internal/addrs/parse_target.go index 6891b90fc7..33147b9208 100644 --- a/internal/addrs/parse_target.go +++ b/internal/addrs/parse_target.go @@ -181,6 +181,15 @@ func parseResourceInstanceUnderModule(moduleAddr ModuleInstance, allowPartial bo // Starting a resource address with "resource" is optional, so we'll // just ignore it. remain = remain[1:] + case "count", "each", "local", "module", "path", "self", "terraform", "var", "template", "lazy", "arg": + // These are all reserved words that are not valid as resource types. + diags = diags.Append(&hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Invalid address", + Detail: fmt.Sprintf("The keyword %q is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with \"resource.\".", remain.RootName()), + Subject: remain.SourceRange().Ptr(), + }) + return AbsResourceInstance{}, diags } if len(remain) < 2 { diff --git a/internal/addrs/parse_target_test.go b/internal/addrs/parse_target_test.go index 5dbf155532..781f386848 100644 --- a/internal/addrs/parse_target_test.go +++ b/internal/addrs/parse_target_test.go @@ -431,6 +431,61 @@ func TestParseTarget(t *testing.T) { nil, `Unexpected extra operators after address.`, }, + { + `each.key`, + nil, + `The keyword "each" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `module.foo[1].each`, + nil, + `The keyword "each" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `count.index`, + nil, + `The keyword "count" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `local.value`, + nil, + `The keyword "local" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `path.root`, + nil, + `The keyword "path" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `self.id`, + nil, + `The keyword "self" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `terraform.planning`, + nil, + `The keyword "terraform" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `var.foo`, + nil, + `The keyword "var" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `template`, + nil, + `The keyword "template" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `lazy`, + nil, + `The keyword "lazy" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, + { + `arg`, + nil, + `The keyword "arg" is reserved and cannot be used to target a resource address. If you are targeting a resource type that uses a reserved keyword, please prefix your address with "resource.".`, + }, } for _, test := range tests { diff --git a/website/docs/language/moved.mdx b/website/docs/language/moved.mdx index 0f61090217..6c32e0b60d 100644 --- a/website/docs/language/moved.mdx +++ b/website/docs/language/moved.mdx @@ -16,8 +16,8 @@ The `moved` block programmatically changes the address of a resource. Refer to [ The following list outlines field hierarchy, language-specific data types, and requirements in the `moved` block. - [`moved`](#moved): map - - [`from`](#moved): string - - [`to`](#moved): string + - [`from`](#moved): reference + - [`to`](#moved): reference ## Complete configuration