I’m working on a terraform provider using the framework plugin. On the (API) backend there is basically one big configuration file, but it consists of a few logical resources. In my provider I want to enable users to define these resources separately. Basically I’ve a main resource A en B and C are child-resources. If I want to update B and/or C I update resource A.
The problem which occurs is that parallelism is enabled by default in terraform, so it could happen that B and C are simultaneously updating A, which results in unpredictable behaviour.
This is solvable by specifying the parallelism flag (–parallelism=1) when executing terraform, but this is a user setting/flag.
Is there another way to solve this, i.e. by specifying priorities;
Unfortunately I don’t think there’s a good solution here. Terraform makes certain assumptions about what will be modelled as a resource, and it sounds like this scenario is breaking those assumptions. It’s difficult to say what should be done here, without more context on what A, B and C are, but it’s likely to be one of:
The remote API should be fixed to not corrupt itself if receiving multiple updates simultaneously
The composite of A, B & C should be managed as a single Terraform resource, since that’s the best mapping to the remote API.
Can you share more information about what A, B & C are and what goes wrong with simultaneous updates?
Thanks, running them at different times would be sufficient.
The sync.Mutex is new to me, but the first search results sounds promising
Will dive into this and let you know the outcome.
update
The sync.Mutex has solved the issue, was more simple than initially thought.
For reference, if people stumble upon the same problem.
What I did is extended the struct I was already passing with resp.ResourceData with a syc.Mutex field.
type auxoClient struct {
client *auxo.Client
m *sync.Mutex
}
This struct is attached to respo.ResourceData in the provider Configure function.
This resourceData is available in every resource, I retrieve the values in the Configure function of the resource.
c := req.ProviderData.(*auxoClient)
r.client = c.client
r.mutex = c.m
Now I’m able to use it for every call that needs to run exclusively.
p.s. In my case I need to do this for the whole function, to prevent that I read an outdate object. However to my understanding best practice is to keep the lock as short as possible.