Terraform allows providers to define schema attributes that conflict with its meta-arguments
Terraform Version
% terraform version
Terraform v1.0.5
on darwin_amd64
Terraform CLI is allowing providers to define top-level schema attributes that conflict with its own meta-arguments such as provider, so for example if the aws_svc_thing resource defines a required attribute named provider of type String and the practitioner writes their code as
resource "aws_svc_thing" "example" {
provider = "DYNAMODB_PROVIDER" # A value expected by the underlying cloud provider API
}
this will (silently) conflict with the provider meta-argument and whatever behavior actually runs will be unexpected.
Expected Behavior
Terraform could validate that a provider does not define conflicting attributes and error during provider initialization.
References
The validation should also occur in any SDK being used: https://github.com/hashicorp/terraform-plugin-framework/issues/136.
Hi @ewbankkit,
This sort of validation is typically more the responsibility of the SDK than of Terraform Core, because Terraform Core must generally be compatible with providers written at various points in history which may already be defining attributes of certain names and thus to forbid them now would be a breaking change.
While it could be reasonable to block out a subset of reserved names that have been reserved since before Terraform v0.10 (which was the first release that was able to automatically install external providers), I think an SDK is generally in a better position to deal with such concerns because the developers of that SDK can be more specific in what versions of Terraform (and, more recently, which protocol versions now that "protocol version" is a meaningful idea) it's intending to support.
It might interest you to know that we have a currently-undocumented feature in modern Terraform which allows for "escaping" special names like this, just in case we need to add a new name in a future edition of the Terraform language which could potentially overlap with existing providers. It uses a special reserved block type named _ (just an underscore) in order to reduce the chance of that overlapping with a meaningful name defined by a provider:
resource "aws_svc_thing" "example" {
_ {
# Anything inside this block becomes a top-level
# argument guaranteed to be passed to the provider,
# rather than processed by Terraform Core.
provider = "DYNAMODB_PROVIDER"
}
}
I would not suggest that provider developers rely on this to intentionally create conflicts with already-reserved names like provider -- it would still be better for an SDK to provide guidance against using those -- but we have this mechanism as a way to allow continued evolution of the Terraform language under the Terraform 1.0 compatibility promises. In the event that we did introduce a new reserved name later (which we have no current plans to do) then part of the design work for that would be to choose a name which doesn't conflict with commonly-used providers, to make the new feature an opt-in so that no existing modules would be broken by it, and to use this special underscore-named block type as the insurance against potential use of that name in providers we can't see (e.g. because they are private within a company), so that users of such providers can still have a path forward.
We don't intend for anyone to make use of these features today because we expect providers will be written to not use reserved names, and so we've held off on documenting this special mechanism until the first time we need it, but this was part of our efforts to leave ourselves pathways to future editions of the Terraform language without violating the compatibility promises. If an SDK were to have helpful prompts about overlapping names then we'd presumably also want to think about how it would deal with a name that is only reserved in newer editions of the Terraform language: would that be forbidden too, or would it be some sort of warning, or something else?
@apparentlymart Thanks for the explanation. I am happy for this issue to be closed as I have opened a similar issue for the provider SDK I am using.
Revisiting this some time later, I think I'm going to close this because I don't think it's possible for us to retroactively start rejecting argument names that we previously accepted without violating the Terraform v1.x Compatibility Promises.
It is pretty unlikely that there is a provider out there which already declares e.g. provider as an argument name, but it is possible and we cannot see all providers that exist because some of them are internal within companies. If anyone were using such a provider then they would need to use the escaping syntax I mentioned in my previous comment to actually set the argument, which makes this awkward but technically valid as far as the plugin protocol is concerned.
Thanks again for raising this!
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.