Cooping with parallelism, is there a way to prioritise resource types?

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;

  • i.e. resources of type B must run before C.
  • or parallelism is 1 by default.

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?

Currently it is one resource containing A,B and C which works fine. The downside is this is one big resource especially when all fields are filled.

The other downside is that it would for example make sense to use a datasource for A and a resource for C.

Thanks for your help, will leave it to one big blob for now. Still if anyone has a suggestion… :grinning:

In case you were wondering what it is, it is a provider for a managed security platform AUXO, to administer your zero trust environment.

https://registry.terraform.io/providers/on2itsecurity/auxo/latest/docs

I’m only familiar with the plugin framework (not SDKv2), so answering in that context…

Forcing strict priority (B runs before C) sounds like it might not be possible, but if you just want them to run at different times:

I’d think that a provider-created sync.Mutex made available to the various resources would do the trick.

Thanks, running them at different times would be sufficient.

The sync.Mutex is new to me, but the first search results sounds promising :+1:
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.

func (r *measureResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
	r.mutex.Lock()
	defer r.mutex.Unlock()

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.

Thanks again all, for your help !

This sounds (or as I interpret it) exactly as my issue, didn’t the sync.Mutex solve the problem?

We have a plague of spammers on this forum who register a brand new account, and use AI to rephrase the initial post in a topic and repost it.

I have no idea what they think they are achieving. I flag them for moderator action.

2 Likes