How to write a terraform provider to control a singleton resource

Hi everyone. I am new to terraform. It seems like terraform assumes that resources have unique IDs on the remote system. When you name a resource in a terraform file, the name gets associated with the unique ID of that resource on the remote system. But what if the resource you want to manage is a singleton and has no unique ID? How does one write a provider to control a singleton resource with no unique ID?

What I really need is nameless resource in the terraform file such as

resource "some_singleton_instance" {

Since the resource is a singleton, my REST API has no POST or DELETE method. It has only a GET method that takes no parameters to get the one resource and a PUT method to update the same.

Can Terraform support this use case?

Thanks in advance.

Hi @keep94,

You’re correct that Terraform typically expects to be the one to create an object because in the common case that helps avoid the undesirable situation where two Terraform configurations both think they “own” the same object and will thus both keep trying to undo changes made in the other one.

The situation for singleton objects is therefore tricky, because we don’t have any way to directly ensure that two configurations don’t both think they own it. The user must just be vigilant in how they design their various configurations and modules to make sure that the particular object is only declared in one place.

At the moment Terraform has no first-class support for this situation, although we have considered the possibility of allowing a provider to respond to the planning request for a particular new object with an additional annotation to be explicit that the plan is to import an object that already exists, rather than to create a new object. The plan on removal could similarly be annotated to say that the plan is to “forget” the object (in the same sense that terraform state rm would), rather than to destroy it. Terraform could then use a different UI presentation to let the user know that something unusual is happening and decide whether it matches what they intended to do.

With Terraform as it exists today, the closest approximation of that would be to add a plan customization function to your resource type which detects if it’s being asked to “create” the singleton object, and if so returns a warning diagnostic which explains that this is not a real create and that instead Terraform will assume control of the existing object, and that the user should make sure that no other system or Terraform configuration is trying to manage that object.

Thank you apparentlymart for your suggestions. Being new to terraform, I don’t know how to add an annotation that says that the plan is to import the already existing singleton object rather than create a new object. Likewise, I don’t know how to make an annotation that says that the object will be “forgotton” on delete. Besides the go docs on, is there any documentation that you would recommend that I read to come up to speed on what you are suggesting I do? Thanks.


Another way of putting it is that as the provider author, you may implement the resource lifecycle methods Create and Destroy on your Resource struct however you wish to accommodate your API, given that there’s no generic way to tell Terraform to “Create or import a resource if it already exists”. Instead of literally trying to create the resource (object) in your remote system, you can implement Create to just fetch the singleton and record it in state instead of trying to actually create it, if you wish.

A concrete example that’s very similar to the problem here is the aws_db_proxy_default_target_group resource in the AWS provider. Check out the note at the top:

The aws_db_proxy_default_target_group behaves differently from normal resources, in that Terraform does not create or destroy this resource, since it implicitly exists as part of an RDS DB Proxy. On Terraform resource creation it is automatically imported and on resource destruction, Terraform performs no actions in RDS.

Does that help?