-
Notifications
You must be signed in to change notification settings - Fork 9.3k
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
resource/aws_api_gateway_deployment: Do not delete stages in use by other deployments #3896
resource/aws_api_gateway_deployment: Do not delete stages in use by other deployments #3896
Conversation
I just double checked and this PR still cleanly applies to master and passes the tests. Any chance of a merge soon before a conflict appears? |
If anybody is interested in testing out this feature in a patched v1.21.0 version, I've made some Alpine Linux x64 binaries available here: https://github.com/lifeomic/terraform-provider-aws/releases/tag/v1.21.0_patched_5f7d0def |
@bflad is there anything I can do to help this get merged into an official release? |
If anybody is interested in testing out this feature in a patched v1.36.0 version, I've made some Alpine Linux x64 binaries available here: https://github.com/lifeomic/terraform-provider-aws/releases/tag/v1.36.0_patched_f2d0f833c |
At first glance, I believe this change seems appropriate. We don't have too much precedent of resources that create other unmanaged resources though. 😅 More forward looking: I am not convinced that we should allow the deployment resource to create stages at all (and hence delete them too), as it leaves Terraform management in a precarious state with unmanaged resources or resources that need to be imported. Unfortunately, I do not believe the API Gateway API provides any mechanism to prevent this behavior beyond only sending the deployment to the "default" stage. |
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.
Some initial comments below -- please reach out with any questions!
return nil | ||
}) | ||
if err != nil { | ||
return resource.RetryableError(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.
A few notes:
- It seems like we should not retry on errors calling
GetStage
, especially any error - As its fairly unexpected that the deletion of a resource is requiring a read call to begin with, we should also return a helpful message here, e.g.
return fmt.Errorf("error getting referenced stage: %s", err)
- Seems like we should skip deleting the stage if its not found, instead of returning the stage not found error
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.
I'll make the changes you suggest
// If the stage has been updated to point at a different deployment, then | ||
// the stage should not be removed then this deployment is deleted. | ||
var shouldDeleteStage = true | ||
if *stage.DeploymentId != d.Id() { |
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.
To prevent potential panics, this should perform a nil
check and use the SDK helper function for the string value:
if stage == nil || aws.StringValue(stage.DeploymentId) != d.Id() {
shouldDeleteState = false
}
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.
Good catch! I'll make that change
return func(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).apigateway | ||
|
||
restApiId := aws.String(s.RootModule().Resources["aws_api_gateway_rest_api.test"].Primary.ID) |
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.
Nitpick: Instead of hardcoding this reference, we should prefer to pass into the function (any of these):
- The REST API resource name
- The actual
apigateway.RestApi
object (e.g. fromtestAccCheckAWSAPIGatewayRestAPIExists()
) - The deployment resource name, then reference its
rest_api_id
attribute
Personally, I'd go with the last option since this is explicitly named with Deployment
. 😄
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.
I'll see how hard the last bullet is. Seems like a good approach to me
@bflad I believe that I have addressed all of your feedback. Let me know if there is anything else I should change. |
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.
Thanks @mdlavin 🚀 Two non-blocking nits (which I'll fix on merge), but otherwise LGTM.
--- PASS: TestAccAWSAPIGatewayDeployment_basic (5.56s)
--- PASS: TestAccAWSAPIGatewayDeployment_createBeforeDestoryUpdate (40.73s)
restApiId := aws.String(deploymentResource.Primary.Attributes["rest_api_id"]) | ||
|
||
req := &apigateway.GetStageInput{ | ||
StageName: &stageName, |
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.
Nitpick: the stage name can be fetched from attributes as well (deploymentResource.Primary.Attributes["stage_name"]
) instead of a parameter passed in from the acceptance test
if err != nil { | ||
// If the stage is already deleted then there is no need to attempt deletion | ||
apigatewayErr, _ := err.(awserr.Error) | ||
if apigatewayErr.Code() == "NotFoundException" { |
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.
Nitpick: we have a helper function for this type of logic and prefer the AWS Go SDK constants, e.g. isAWSErr(err, apigateway.ErrCodeNotFoundException, "")
``` --- PASS: TestAccAWSAPIGatewayDeployment_basic (20.41s) --- PASS: TestAccAWSAPIGatewayDeployment_createBeforeDestoryUpdate (33.28s) ```
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks! |
When a deployment has been updated in a way that forces a create/delete, the newly deployed deployment can be left in a bad state. Here how the code used to work:
Here is how the code works now: