question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

defaultMethodOptions in SpecRestApi is confusing

See original GitHub issue

The documentation states about defaultIntegration:

An integration to use as a default for all methods created within this API unless an integration is specified.

Yet when I define an API with no integration defined within the OpenAPI spec, the default integration is ignored and an error occurs when deploying.

Reproduction Steps

SpecRestApi openapiRestApi = SpecRestApi.Builder.create(this, "MyApi")
						.restApiName("MyApi")
						.apiDefinition(ApiDefinition.fromAsset("openapi.yaml"))
						.defaultIntegration(LambdaIntegration.Builder.create(myLambda)
									.proxy(false)
									.build())
						.deploy(true)
						.build();

where myLambda is a lambda defined earlier in the CDK.

The OpenApi spec has a single method defined (the header and model are not shown):

paths:
  /items:
    get:
      summary: List all items.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ItemList'

Error Log

The following error appears in the CloudFormation events when deploying:

No integration defined for method (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 56113150-1460-4ed2-93b9-a12618864582)

Environment

  • CLI Version : 1.42.0
  • Framework Version: 1.42.1
  • Node.js Version: v12.16.0
  • OS : Windows
  • Language (Version): Java

Other


This is 🐛 Bug Report

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
john-tippercommented, Jun 30, 2020

This means that any value provided under defaultIntegration or any other property in the CDK application will only apply to Methods and Resources in the CDK app. We are not able to (and currently do not) apply these to the Methods and Resources defined in the OpenAPI definitions.

@nija-at Actually, I think it might just be fine to call this out clearly in the documentation, as I had interpreted the name defaultIntegration to mean exactly that, i.e. if I do nothing then it is the integration used, come what may, whereas it is only ever used if the API is defined using CDK Methods and Resources.

@mmuller88 I got around the chicken and the egg problem by templating the API spec, rather than having to do two deployments and I used Mustache. So, for a CDK defined API in Java, I added this to the dependencies:

implementation 'com.github.spullara.mustache.java:compiler:0.9.6'

Then, within the API spec, I defined things like:

x-amazon-apigateway-integration:
uri: "{{restapi-lambda}}"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
type: "aws_proxy"
credentials: "{{restapi-role}}"

Finally, within the CDK definition, I did this:

Map<String, Object> variables = new HashMap<>();
variables.put("restapi-lambda", String.format(
    "arn:aws:apigateway:%s:lambda:path/2015-03-31/functions/%s/invocations",
    props.getEnv()
       .getRegion(),
    myRestHandler.getFunctionArn()));
variables.put("restapi-role", apiGatewayRole.getRoleArn());

Writer writer = new StringWriter();
MustacheFactory mf = new DefaultMustacheFactory();

Object openapiSpecAsObject;
try (Reader reader = new FileReader(new File("openapi.yaml"))) {
  Mustache mustache = mf.compile(reader, "OAS");
  mustache.execute(writer, variables);
  writer.flush();

  ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());

  openapiSpecAsObject = yamlMapper.readValue(writer.toString(), Object.class);

}

SpecRestApi openapiRestApi = SpecRestApi.Builder.create(this, "MyRestApi")
                        .restApiName("MyApi")
                        .apiDefinition(ApiDefinition.fromInline(openapiSpecAsObject))
                        .deploy(true)
                        .deployOptions(StageOptions.builder()
                                       .stageName("prod")
                                       .build())
                        .build();

I found some bizarre dependency issues that sometimes cropped up where the deployment seemed to happen before the Lambda permissions had been created and then the ApiGateway would not be able to invoke the functions, even though the permissions had been set. I’d have to re-deploy the API in the console in order to have the permissions set correctly, so I can only assume that the ApiGateway, when it creates a deployment, takes a copy of the Lambda permissions as they exist at that moment of deployment, and any subsequent changes have no effect. To get around this, I needed to do the following:

CfnPermission restPermission = CfnPermission.Builder.create(this, "GrantPermissionToApiGateway")
									.action("lambda:InvokeFunction")
									.principal("apigateway.amazonaws.com")
									.sourceArn(String.format(
											"arn:aws:execute-api:%s:%s:*",
											props.getEnv()
												 .getRegion(),
											props.getEnv()
												 .getAccount()))
									.functionName(myRestHandler.getFunctionName())
									.build();


openapiRestApi.getNode()
	  .addDependency(apiGatewayRole);

openapiRestApi.getNode()
	  .addDependency(restPermission);

openapiRestApi.getDeploymentStage()
	  .getNode()
	  .addDependency(restPermission);
1reaction
gregorypiercecommented, Jul 7, 2020

I think it creates some confusion only because there is some assumption that it helps with defining the required pieces for OpenApi. Removing it would make it clearer that there is no functionality there and folks need to, unfortunately, roll their own solution.

Maybe an example of how it’s intended to work would help. There are a lot of people parsing the spec and inserting tokens and such. Is that what we are expected to do? If so, simply saying that would help people understand the intent. I personally intend to do that under the assumption that if I push tokens from the synth process into a document that will be passed to apigateway that cdk will substitute the tokens along the way. As such I’m generating the integrations in memory and plan to insert function arns and the like along the way - then pass that token filled doc to the restapi. It appears that I will get all the function deploys before the restapi is generated so - all good 😉

On Tue, Jun 30, 2020, 4:51 AM Niranjan Jayakar notifications@github.com wrote:

Re-reading some of the comments here.

The CDK does not open and read the OpenAPI definition files. This means that any value provided under defaultIntegration or any other property in the CDK application will only apply to Methods and Resources in the CDK app. We are not able to (and currently do not) apply these to the Methods and Resources defined in the OpenAPI definitions.

Perhaps having a defaultIntegration property on SpecRestApi is creating this confusion. Would it be less ambiguous if this property was removed entirely and users had to explicitly define the integration for each API?

If I’ve misunderstood and this is not what you’re trying to do, could you please clarify and provide code examples for reproduction?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/aws/aws-cdk/issues/8347#issuecomment-651689058, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAXNUTCOCDYXDW4N4E5TXDRZGYRLANCNFSM4NR34JDA .

Read more comments on GitHub >

github_iconTop Results From Across the Web

aws-cdk/aws-apigateway module - AWS Documentation
This is to prevent people duplication of these properties and potential confusion. Endpoint configuration. By default, SpecRestApi will create an edge optimized ...
Read more >
@aws-cdk/aws-apigateway | Yarn - Package Manager
The defaultIntegration and defaultMethodOptions properties can be used to configure a default integration at any resource level. These options will be used ...
Read more >
awsapigateway - Go Packages
See reference documentation for default method options. The following example defines the booksBackend integration as a default integration. This means that all ...
Read more >
Ask Question - Stack Overflow
How to do lambda integrations for API Gateways defined with AWS CDK SpecRestApi and swagger.yml/openapi · Ask Question. Asked 8 months ago.
Read more >
OpenAPI Specs from CDK Stack WITHOUT Deploying First
defaultMethodOptions && props.apiProps.defaultMethodOptions.authorizer) { this.openApiSpec.components.securitySchemes.authorizer = { 'type': ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found