Open stooj opened 4 months ago
@t0yv0 tagging as requested. Thanks
It appears that the upstream provider is designed to treat changes to body as in-place updates (it is not marked ForceNew). In-place updates do not cascade in Pulumi to dependent resources and there is no way I have found to do this to force the re-creation of aws.apigateway.RestApiPolicy whenever there is an update to the body of aws.apigateway.RestApi. One crude workaround is to apply a replace_on_changes=["body"]
option to aws.apigateway.RestApi to treat this property as if it was marked with ForceNew. If this is done, any changes to body will trigger a replace plan that will replace both the RestApi and RestApiPolicy and pass the above check.
I ended up using this variation for testing (with api_spec.json as above), and check.sh:
#!/usr/bin/env bash
set -euo pipefail
aid=$(pulumi stack output apiid)
aws apigateway --region=us-east-1 get-rest-api --rest-api-id "$aid" |
jq '.policy'
import pulumi as pulumi
import pulumi_aws as aws
username = 't0yv0'
# Load the OpenAPI specification template from file
with open("api_spec.json", "r") as file:
openapi_spec_template = file.read()
# Create the API Gateway
api_gw = aws.apigateway.RestApi(
f"test_api_gw-{username}",
name=f"TestJCa API {username}",
description="TestJCa",
endpoint_configuration={"types": "REGIONAL"},
# put_rest_api_mode="merge",
body=openapi_spec_template,
opts=pulumi.ResourceOptions(replace_on_changes=["body"]),
)
test = aws.iam.get_policy_document_output(statements=[{
"effect": "Allow",
"principals": [{
"type": "AWS",
"identifiers": ["*"],
}],
"actions": ["execute-api:Invoke"],
"resources": [api_gw.execution_arn],
"conditions": [{
"test": "IpAddress",
"variable": "aws:SourceIp",
"values": ["123.123.123.123/32"],
}],
}])
aws.apigateway.RestApiPolicy(
f"test_api_gw_resource_policy-{username}",
rest_api_id=api_gw.id,
policy=test.json,
)
pulumi.export("apiid", api_gw.id)
Could you please let us know if this workaround gets the customer unblocked?
Digging a bit further into this surprising behavior. So when the body of aws.apigateway.RestApi changes, without any resource options, Pulumi executes an Update plan just on the RestApi resource. It hits this code path:
// Terraform implementation uses the `overwrite` mode by default. // Overwrite mode will delete existing literal properties if they are not explicitly set in the OpenAPI definition. // The VPC endpoints deletion and immediate recreation can cause a race condition. // Impacted properties: ApiKeySourceType, BinaryMediaTypes, Description, EndpointConfiguration, MinimumCompressionSize, Name, Policy // The `merge` mode will not delete literal properties of a RestApi if they’re not explicitly set in the OAS definition.
The overwrite update mode is the one that I believe removes policy. If I add this option:
put_rest_api_mode="merge",
Then I'm no longer observing the policy from disappearing. Perhaps the repro I'm trying is missing some important aspect? It sounds like from the description that the customer has already tried put_rest_api_mode.
put_rest_api_mode="merge"
works around the disappearing policy because it won't recreate the RestApi
, but it breaks updates to the api spec (which I'd argue is usually more important).
The merge
behaviour ignores any changes to the api spec that would normally remove an endpoint.
For example, if put_rest_api_mode
is set to merge
, then you delete the /pets
path from the API spec, this path removal will not be applied to the api on any future pulumi up
. (/pets
is still an endpoint on the api)
So the merge workaround introduces a worse behaviour :(
Thanks for clarifying that, it wasn't obvious! How about the replace_on_changes workaround, that is not acceptable either?
@stooj is there anything we need to follow up on here or can we close the issue? Appreciated!
Describe what happened
When managing an
aws:apigateway:RestApi
with an OpenAPI spec and anaws.apigateway.RestApiPolicy
, any change to the API spec will result in a recreation of theRestApi
. This is expected (See warning in the docs).However, when the RestApi is recreated, the
RestApiPolicy
is not attached to the new policy.Pulumi gives no indication that this resource will be deleted, so there's no warning that you need to reattach the policy manually.
Sample program
Sample
__main__.py
Sample
api_spec.json
To reproduce:
pulumi up
Check the policy is attached:
pulumi up
,RestAPI
is recreated as expectedget-rest-api
command again, andnull
will be returned. The policy is goneLog output
No response
Affected Resource(s)
Output of
pulumi about
Additional context
The largest concern here is that pulumi is removing resources without warning the user beforehand. I suspect this is a unique result of this bug though, so fixing the bug will mean users can rely on the preview being accurate.
Contributing
Vote on this issue by adding a 👍 reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).