aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.46k stars 3.82k forks source link

apigatewayv2: Error referencing integration_id when creating route #30512

Open cjhelloletsgo opened 2 months ago

cjhelloletsgo commented 2 months ago

Describe the bug

When creating an integration for a websocket api to create a route you need to have the id of the integration you want to attach, but there are errors that prevent deployment.

This is the error I am getting from referencing get_cases_integration.attr_id: [Error] /Resources/TestGetCasesRoute/Properties/Target/Fn::Join/1/1/Fn::GetAtt: Resource type AWS::ApiGatewayV2::Integration does not support attribute {Id}

attr_id is shown as an attribute I should be able to use in the documentation here: https://docs.aws.amazon.com/cdk/api/v2/python/aws_cdk.aws_apigatewayv2/CfnIntegration.html

and id is shown in the cloudformation docs as well https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-integration.html

Actually using the attribute results in an error though.

Hardcoding the target works fine as shown in the second commented out target in the route.

websocket_api = apigwv2.WebSocketApi(
    self,
    "CPP Websocket API",
    connect_route_options=apigwv2.WebSocketRouteOptions(
        integration=apigwv2_integrations.WebSocketLambdaIntegration(
            "ConnectIntegration",
            handler=websocket_lambda,
        ),
        authorizer=aws_apigatewayv2_authorizers.WebSocketLambdaAuthorizer(
            "Websocket Authorizer",
            handler=websocket_authorizer_lambda,
            identity_source=[
                "route.request.querystring.token",
            ],
            authorizer_name="Websocket_Authorizer",
        ),
    ),
    disconnect_route_options=apigwv2.WebSocketRouteOptions(
        integration=apigwv2_integrations.WebSocketLambdaIntegration(
            "DisconnectIntegration",
            handler=websocket_lambda,
        ),
    ),
    description="Websocket API For CPP",
)

get_cases_model = apigwv2.CfnModel(
    self,
    "Get Cases Model",
    api_id=websocket_api.api_id,
    name="GetCases",
    schema={
        "$schema": "http://json-schema.org/draft-04/schema#",
        "title": "Test",
        "type": "object",
        "properties": {
            "action": {
                "type": "string",
            },
            "email": {
                "type": "string",
            },
        },
        "required": [
            "action",
            "email",
        ],
    },
    content_type="application/json",
    description="Get Cases Model description",
)

get_cases_integration = apigwv2.CfnIntegration(
    self,
    "Test Get Cases Integration",
    api_id=websocket_api.api_id,
    integration_type="AWS_PROXY",
    # the properties below are optional
    connection_type="INTERNET",
    #     content_handling_strategy="contentHandlingStrategy",
    #     credentials_arn="credentialsArn",
    description="get_cases integration",
    integration_method="POST",
    # integration_uri=websocket_lambda.function_arn,
    integration_uri=f"arn:aws:apigateway:{region}:lambda:path/2015-03-31/functions/arn:aws:lambda:{region}:{account}:function:{websocket_lambda.function_name}/invocations",
    # passthrough_behavior="passthroughBehavior",
    # payload_format_version="payloadFormatVersion",
    request_parameters={},
    # request_templates=request_templates,
    # template_selection_expression="templateSelectionExpression",
    timeout_in_millis=29000,
)

get_cases_route = apigwv2.CfnRoute(
    self,
    "Test Get Cases Route",
    api_id=websocket_api.api_id,
    route_key="test_get_cases",
    # the properties below are optional
    api_key_required=False,
    # authorization_scopes=["authorizationScopes"],
    # authorization_type="authorizationType",
    # authorizer_id="authorizerId",
    model_selection_expression="${request.body.action}",
    # operation_name="GetCases",
    request_models={
        "GetCases": get_cases_model.name,
    },
    # request_parameters=request_parameters,
    # route_response_selection_expression="routeResponseSelectionExpression",
    target=f"integrations/{get_cases_integration.attr_id}",
    # target="integrations/3aupm6i",
)

Expected Behavior

I should be able to get the integration id for use with the route.

Current Behavior

The attribute I am trying to use is invalid (attr_id)

Reproduction Steps

Use above code.

Possible Solution

No response

Additional Information/Context

No response

CDK CLI Version

2.145.0 (build fdf53ba)

Framework Version

No response

Node.js Version

v20.14.0

OS

Ubuntu 24.04

Language

Python

Language Version

Python 3.12.3

Other information

No response

pahud commented 2 months ago

I see you are creating the integration with CfnIntegration L1 construct, and according to the api ref doc, you should have attr_id.

get_cases_integration = apigwv2.CfnIntegration(...)

I can reproduce this in TS:

    // create a minimal integration
    const cfnintegration = new apigwv2.CfnIntegration(this, 'dummy', {
      apiId: 'dummy-id',
      integrationType: 'AWS_PROXY',
      integrationUri: 'dummy-uri',
    });

    new CfnOutput(this, 'dummy-uri', { value: cfnintegration.attrId });

CFN

{
 "Resources": {
  "dummy": {
   "Type": "AWS::ApiGatewayV2::Integration",
   "Properties": {
    "ApiId": "dummy-id",
    "IntegrationType": "AWS_PROXY",
    "IntegrationUri": "dummy-uri"
   },
   "Metadata": {
    "aws:cdk:path": "stack1/dummy"
   }
  },
  "CDKMetadata": {
   "Type": "AWS::CDK::Metadata",
   "Properties": {
    "Analytics": "v2:deflate64:H4sIAAAAAAAA/yWNwQrCMBBEv8V7upqi4r0nT0L9AFmTtWyrm5JsWkT8dxM8zZvHwLRg9wfYbXBNjfNT8+Q7fK6KbjJF3XDmAZVWfC8tdA85i9IQUTmIKfWSdc5aqacUcnRUuQviuU6+RoInGNN2sSewx/IzJuYmZlF+EfT//AEunruFhAAAAA=="
   },
   "Metadata": {
    "aws:cdk:path": "stack1/CDKMetadata/Default"
   },
   "Condition": "CDKMetadataAvailable"
  }
 },
 "Outputs": {
  "dummyuri": {
   "Value": {
    "Fn::GetAtt": [
     "dummy",
     "Id"
    ]
   }
  }
 },
 "Conditions": {
  "CDKMetadataAvailable": {
   "Fn::Or": [
    {
     "Fn::Or": [
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "af-south-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "ap-east-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "ap-northeast-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "ap-northeast-2"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "ap-south-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "ap-southeast-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "ap-southeast-2"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "ca-central-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "cn-north-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "cn-northwest-1"
       ]
      }
     ]
    },
    {
     "Fn::Or": [
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "eu-central-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "eu-north-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "eu-south-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "eu-west-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "eu-west-2"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "eu-west-3"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "il-central-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "me-central-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "me-south-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "sa-east-1"
       ]
      }
     ]
    },
    {
     "Fn::Or": [
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "us-east-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "us-east-2"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "us-west-1"
       ]
      },
      {
       "Fn::Equals": [
        {
         "Ref": "AWS::Region"
        },
        "us-west-2"
       ]
      }
     ]
    }
   ]
  }
 },
 "Parameters": {
  "BootstrapVersion": {
   "Type": "AWS::SSM::Parameter::Value<String>",
   "Default": "/cdk-bootstrap/hnb659fds/version",
   "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]"
  }
 },
 "Rules": {
  "CheckBootstrapVersion": {
   "Assertions": [
    {
     "Assert": {
      "Fn::Not": [
       {
        "Fn::Contains": [
         [
          "1",
          "2",
          "3",
          "4",
          "5"
         ],
         {
          "Ref": "BootstrapVersion"
         }
        ]
       }
      ]
     },
     "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI."
    }
   ]
  }
 }
}

❌ Deployment failed: Error: The stack named stack1 failed to deploy: CREATE_FAILED ([Error] /Outputs/dummyuri/Value/Fn::GetAtt: Resource type AWS::ApiGatewayV2::Integration does not support attribute {Id})

This looks like a CFN bug. I'll report internally.

cjhelloletsgo commented 2 months ago

Awesome thanks!

pahud commented 2 months ago

Internal tracking: V1416216620 P135346098

pahud commented 1 week ago

We are still pending for internal response.

Before we get it sorted, you probably need to use Ref like cfnintegration.ref instead. Let me know if it works for you.