Skip to content
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

feat(apigateway): define Resources on imported RestApi #8270

Merged
merged 10 commits into from
Jun 12, 2020

Conversation

nija-at
Copy link
Contributor

@nija-at nija-at commented May 29, 2020

The apigateway CDK construct library creates a large number of
CloudFormation resources.
To define a single Method that is backed with a Lambda function and
authorizer with an Authorizer, ~8 CloudFormation resources are created.
This quickly grows and a reasonable sized RestApi is bound to hit the
200 resource limit on their stack.

Re-organizing the CDK app into multiple Stacks that share the same
instance of RestApi will not resolve this problem, since the CDK
still makes an executive decision to keep the Methods and Resources in
the same stack as the RestApi construct. (see #7391)

This change introduces a new import style API fromRestApiAttributes()
that returns an instance of IRestApi that allows for new Resources to
be defined across stacks.

As a nice side effect, this change also adds the ability to define
Resources on SpecRestApi in addition to what has already been defined in
the OpenAPI spec.

closes #1477
closes #7391
fixes #8347


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

The apigateway CDK construct library creates a large number of
CloudFormation resources.
To define a single Method that is backed with a Lambda function and
authorizer with an Authorizer, ~8 CloudFormation resources are created.
This quickly grows and a reasonable sized RestApi is bound to hit the
200 resource limit on their stack.

Re-organizing the CDK app into multiple `Stack`s that share the same
instance of `RestApi` will not resolve this problem, since the CDK
still makes an executive decision to keep the Methods and Resources in
the same stack as the `RestApi` construct. (see #7391)

This change introduces a new import style API `fromRestApiAttributes()`
that returns an instance of `IRestApi` that allows for new Resources to
be defined across stacks.

As a nice side effect, this change also adds the ability to define
Resources on SpecRestApi in addition to what has already been defined in
the OpenAPI spec.

closes #1477
@nija-at nija-at requested review from eladb and a team May 29, 2020 09:47
@nija-at nija-at self-assigned this May 29, 2020
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label May 29, 2020
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: ad39968
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: fc760a9
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@nija-at nija-at requested review from a team and eladb June 4, 2020 17:11
eladb
eladb previously requested changes Jun 9, 2020
}
}

export class Resource extends ResourceBase {
public readonly parentResource?: IResource;
public readonly restApi: RestApi;
public readonly api: MutableRestApi;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to just expose IRestApi here and this way avoid exposing MutableRestApi as a public api?

This might require type checks in the code but it will keep the public api cleaner and with less surface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've taken another stab at trying to erase this type from the public API. However, it requires some methods to be promoted into IRestApi. Let me know what you think here.

@nija-at nija-at requested review from eladb and a team June 9, 2020 16:11
@nija-at nija-at dismissed eladb’s stale review June 9, 2020 16:15

Feedback addressed

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: fb8a765
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: ce878c0
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

* Checks if the given object is an instance of RestApiBase.
*/
public static isRestApiBase(x: any): x is IRestApi {
return x !== null && typeof(x) === 'object' && RESTAPI_SYMBOL in x;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this symbol is no longer required now that we use peer dependencies. You can just use instanceof

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this method is needed.

Copy link
Contributor Author

@nija-at nija-at Jun 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instanceof still does not work in some cases. See 1423c53.

symbol based matching seems more more robust.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @RomainMuller who has thoughts on why this should not be instanceof.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is enough to have ONE package in your dependency closure incorrectly modeling their dependencies for the instanceof idiom to fail. This is a surprisingly easy way to break people's code.

Additionally, the npm de-duplication logic is strictly best-effort, so it is possible that for some reason, npm decides to install multiple copies of some library, and then boom, the instanceof idiom breaks.

In my opinion, instanceof can only be safely used in JavaScript if the tested instance has been created in the same file that performs the instanceof check (guaranteeing the imported types come from the same location).

Copy link
Contributor Author

@nija-at nija-at Jun 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aside from the Romain's points, the error message to a customer when they don't use peer dependencies is not very informative. In some cases these are not failures either - they just result in the wrong template or state.

Using the current symbol based approach just works in all these cases.

Comment on lines 216 to 218
if (RestApiBase.isRestApiBase(props.resource.api)) {
(props.resource.api as any)._attachMethod(this);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should work (the static method is redundant and you don't need that as any):

Suggested change
if (RestApiBase.isRestApiBase(props.resource.api)) {
(props.resource.api as any)._attachMethod(this);
}
if (props.resource.api instanceof RestApiBase) {
props.resource.api._attachMethod(this);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cast would not be needed if isRestApiBase returned x is RestApiBase instead of x is IRestApi.

@nija-at nija-at requested a review from eladb June 11, 2020 09:15
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: 9f7ee9b
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: ae3b59f
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: f7dfa3f
  • Result: FAILED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify
Copy link
Contributor

mergify bot commented Jun 12, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit 21a1de3 into master Jun 12, 2020
@mergify mergify bot deleted the nija-at/apigateway-configureImported branch June 12, 2020 10:42
@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: bce41e4
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@tristanHessell
Copy link

@nija-at Is there an expected time-frame for an npm release containing these changes?

@nija-at
Copy link
Contributor Author

nija-at commented Jun 16, 2020

It should be available this week.

@zubairzahoor
Copy link

If an authorizer is created by passing the reference of main restApiId, can that authorizer be used to authenticate the API Endpoints that are defined across stacks?

@zubairzahoor
Copy link

It works but only with MockIntegration. When I try to use LambdaIntegration(lambdaFn) the following error is thrown:
RestApi is not available on Resource not connected to an instance of RestApi. Use api instead
What am I missing here? @nija-at

@nija-at
Copy link
Contributor Author

nija-at commented Jun 22, 2020

Please open a separate issue to report bugs and guidance queries.

mergify bot pushed a commit that referenced this pull request Dec 23, 2024
### Description of changes
Fixes the readme sections order to match the original order when `Breaking up Methods and Resources across Stacks` section was originally added in this PR #8270.  The current order does not make sense, this section does not related to the Step function backed rest API 

### Checklist
- [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md)

----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS.
Projects
None yet
6 participants