For Pulumi. When I see the pulumi-kotlin example code I much prefer it over my Terraform scripts. (We picked TF before Pulumi was an option, and waaaaay before it had reasonably typesafe lang support)
Idk if the APIs look like what you want, but Scala has ADTs and there's a new Pulumi SDK for Scala that just entered public beta: https://virtuslab.github.io/besom/
If you're into Nix, you might enjoy using this to generate Terraform JSON. The language is inspired by Nix, so it feels familiar to Nixers, but it has a better type system that recently includes ADTs, at least on its master branch: https://github.com/tweag/tf-ncl
We use typescript + pulumi for this. It's pretty amazing. And Pulumi uses Terraform modules under the hood so you get the full power of Terraform with the goodness of Typescript.
Even self hosting your state management in a bucket is simpler with Pulumi since it uses lock files on S3 versus a separate DyanamoDB + S3 combo.
I have been using it in production for 4-5 years and used Terraform for several years before that.
I think not, actually. There would still be cases where a race is not detected. I can think of the following sequence: A checks - no lock, B checks - no lock, A writes - success, A reads - match, success, B writes - success, B reads - match, success. A and B both think they now hold the lock.
For locking to work properly you'd need to have a conditional write that would fail if some prerequisite was not met. GCP offers that operation, S3 AFAIK does not.
client A lists s3://bucket/prefix/.pulumi/locks/, sees nothing
client B lists s3://bucket/prefix/.pulumi/locks/, sees nothing
client A creates s3://bucket/prefix/.pulumi/locks/unique1.json
client A lists s3://bucket/prefix/.pulumi/locks/, only sees unique1.json, and proceeds
client B creates s3://bucket/prefix/.pulumi/locks/unique2.json
client B lists s3://bucket/prefix/.pulumi/locks/ and sees both unique1.json and unique2.json
client B assumes it lost a race, deletes s3://bucket/prefix/.pulumi/locks/unique2.json, and retries
There's another mode where both clients pessimistically retry, but fuzzing a retry delay could eventually choose a winner randomly.
In this case you have the opposite issue, with no-one actually guaranteed to get a lock even though nothing is holding one. Fuzzed retries may work in practice but theoretically speaking this is a flawed algorithm.
https://github.com/VirtuslabRnD/pulumi-kotlin
For Pulumi. When I see the pulumi-kotlin example code I much prefer it over my Terraform scripts. (We picked TF before Pulumi was an option, and waaaaay before it had reasonably typesafe lang support)