New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non-idempotent SNS topic creation workaround #3235
Non-idempotent SNS topic creation workaround #3235
Conversation
What does TF do in this case? Does TF have the same problem? If so is there an upstream ticket ref? Does this solve updates as well or only creates? |
Actually reading the original ticket, it sounds like this fix will make it fail loudly, which is slightly better than current silent corruption behavior but still not ideal? To confirm is that what we're going for? |
// Some partitions (e.g. ISO) may not support tag-on-create. | ||
@@ -291,6 +322,7 @@ func resourceTopicCreate(ctx context.Context, d *schema.ResourceData, meta inter | ||
|
||
output, err = conn.CreateTopic(ctx, input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does conn.CreateTopic return if the topic already exists?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is what the docs say:
This action is idempotent, so if the requester already owns a topic with the specified name, that topic's ARN is returned without creating a new topic.
And in my testing that seems to indeed be the behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we need to change the docs since we have changed the behavior of the resource?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither our docs nor terraforms mention anything about the create returning existing resources:
https://www.pulumi.com/registry/packages/aws/api-docs/sns/topic/
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic
Given that the new behaviour is the default behaviour for pulumi resources, I'd say this does not warrant any additional documentation, LMK if you disagree
Yeah, exactly - this change will make the creation of a second SNS topic with the same name fail, instead of the current behaviour of silently passing and creating weirdness down the line. |
// Some partitions (e.g. ISO) may not support tag-on-create. | ||
@@ -291,6 +322,7 @@ func resourceTopicCreate(ctx context.Context, d *schema.ResourceData, meta inter | ||
|
||
output, err = conn.CreateTopic(ctx, input) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we need to change the docs since we have changed the behavior of the resource?
This is the upstream issue: hashicorp/terraform-provider-aws#6245 Note it's closed but not completed. |
Co-authored-by: Ian Wahbe <ian@wahbe.com>
Does the PR have any schema changes?Does the PR have any schema changes?Looking good! No breaking changes found. Maintainer note: consult the runbook for dealing with any breaking changes. |
I'm a little wary of cost-benefit of this PR since upstream didn't fix it we're introducing a bit of slowdown and failure mode for creating the topic, but if we do it right (without slowing down for clients with 1000 topics) I think on balance the fact that it's an upvoted request both in our repo and upstream - let's try it! Thank you! |
+ return diag.Errorf("SNS Topic (%s) already exists", name) | ||
+ } | ||
+ if !tfresource.NotFound(err) { | ||
+ return diag.FromErr(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could go both ways here, logging or erroring out. I guess erroring out is reasonable, though it introduces a new failure path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless AWS changes its URN scheme, it is wrong to create two of these. I agree that we should error here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
I would love to see an ideation doc presenting this strategy as a possible solution for structural resources. My suspicion is that we can determine the "name" (ARN for AWS) for most structural resources.
} | ||
} | ||
|
||
+func constructTopicArn(client *sns.Client, account, region, snsTopicName string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a much cleaner implementation.
+ return diag.Errorf("SNS Topic (%s) already exists", name) | ||
+ } | ||
+ if !tfresource.NotFound(err) { | ||
+ return diag.FromErr(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless AWS changes its URN scheme, it is wrong to create two of these. I agree that we should error here.
pulumi/pulumi#9925 looks like the exact issue this fixes - Fraser noted they are related there. Might be worth lifting the logic into the bridge since there's a few of these resources. I'll merge this and then raise this as a workaround for idempotent creates. Edit: thinking about this a bit more, it might be a bit difficult to lift in the bridge, since there'd be a lot of specific logic for determining the logical name of the resource - our reads prob work off the URN, which would not be the same in this case. |
We would be calling TFs read in the case of the bridge, not Pulumi's. In essence, we would ask TF to "import" the resource, and if the import succeeds, we would then fail. |
This reverts commit 976def3.
This reverts commit 976def3. Until we sort out #3268 (comment) It hasn't been released so no need to patch it.
This is a re-roll of #3235. See [this comment](#3288 (comment)) for why we are re-rolling this. closes #3288 Co-authored-by: VenelinMartinov <venelin.v.martinov@gmail.com>
This is a re-roll of #3235. See [this comment](#3288 (comment)) for why we are re-rolling this. Previously the creation of an SNS topic was idempotent, so you could create multiple pulumi resources corresponding to the same SNS topic, causing confusing behaviour when one was deleted/replaced. With this PR, trying to create a topic which exists will error. Note that this is kind of a breaking change - pulumi programs where the same SNS topic was created through multiple pulumi resources would run fine before but will now error. Note also the mutex around the listing and creating of SNS topics - this is needed to prevent race conditions within the same program. Race conditions with other programs are still possible and that is unavoidable because of the AWS API. fixes #3288, fixes #2009. Co-authored-by: VenelinMartinov venelin.v.martinov@gmail.com
This addresses #2009.
Previously the creation of an SNS topic was idempotent, so you could create multiple pulumi resources corresponding to the same SNS topic, causing confusing behaviour when one was deleted/replaced.
With this PR, trying to create a topic which exists will error.
Note that this is kind of a breaking change - pulumi programs where the same SNS topic was created through multiple pulumi resources would run fine before but will now error.
Note also the mutex around the listing and creating of SNS topics - this is needed to prevent race conditions within the same program. Race conditions with other programs are still possible and that is unavoidable because of the AWS API.