serverless-aws-alias icon indicating copy to clipboard operation
serverless-aws-alias copied to clipboard

Compatibility with shared API GW

Open a-panickar opened this issue 6 years ago • 1 comments

@HyperBrain Thanks for the plugin.

I see that you had mentioned this plugin wouldn't work with the PR that enables reusing existing API GW's across multiple sls stacks.

Do you plan on updating the plugin to support that model anytime soon? Also, do you have any short-term recommendations or workarounds in the interim?

a-panickar avatar Nov 09 '17 16:11 a-panickar

Maybe I first explain what the problems we'll face are with a common APIG approach, so that everyone who comes here has the same understanding and we can come to a good discussion and maybe a viable solution how this can be supported.

Serverless approach from the PR

The mentioned PR introduces the ability to reference the target APIG API in a service instead of having it defined in the stack itself. So the API is defined in one project (and created there as CF resource) and only referenced by its id in other projects.

As a consequence only the CF template of the "master" project that controls the API contains an API gateway and root resource.

Problems / Ideas / Questions

I'll list the problems that I see with such a change here. The list is based on my sole thoughts, so it is likely to be incomplete. I'd appreciate any additions ;-).

APIG references

Handling APIG references instead of referencing an existing APIG CF resource should be no problem and can be integrated into the plugin quite easily. It just has to use the apiId and apiRootResourceId given in the serverless.yml. These will be used then in the APIG stage resources and the APIG path resources. The deployment process would work as before in this regard. The alias stages would automatically be deployed to the given API.

Alias stages

Here comes a problem that is a hard one (at least from what I see right now). The alias plugin deploys all alias endpoints (of a service) into an APIG alias stage.

One needs to know how exactly AWS APIG stage deployments work, before I continue with the problem analysis. What you see in the APIG console (the methods and API paths) are the unstaged contents of an API (let's name this staging area). If you deploy an API (i.e. with a CF APIGateway::Deployment resource executed by CF) the content of this staging area is persisted (read-only) within an APIG API stage, whatever currently is in there. Each deployment of a project will put its content first in the staging area. So what you see there in an API is the content of the last deployment, whatever that was. With aliases, the latest deployed alias. Then it's persisted.

Schematics aliasdeploy

Now let's imagine we have a common API that is served and used by multiple projects. All alias stage deployments will create their APIG stage resources in this one API.

Schematics with single API aliasdeployoneapi

Stage resources

One problem are the stage resources. The AWS::ApiGateway::Stage resources that guarantee the ownership of stages are stored in the alias stacks. This is important, because the removal of an alias currently also removes all objects it created. With a single API approach, there can be only one AWS::ApiGateway::Stage resource that owns the APIG stage. That means in a single API/multiple projects scenario we would have the restriction that only one of the projects are allowed to create a CF stage resource and all others would have to reference the resource via ImportValue.

A second thought would be to allow only unique alias names over all participating projects (including the master alias a.k.a. the stage). This means that all projects must not share any stage names. Alone from reading the previous sentence I think this is not feasible?

Let's assume that the master project somehow owns the resource.

:boom: Then an alias must be deployed on the master project, before it could be used and deployed on any other project. All other projects must now know the name of the original project, because the alias stage resides in the alias CF stack of the master project and the id has to be retrieved from there. Having a manual setting in serverless.yml is not really an option because everything will be broken if the stage is not protected from deletion (which is only possible via a direct Fn::ImportValue reference.

:boom: The stage deployment of a single project (integrity of it's own resources) in case the APIG stage is shared, should work as long as the projects do not share any API paths (imo thats also a requirement for the SLS PR).

:boom: An alias deploy from an arbitrary project would put everything into the stage that is available in the staging area (i.e. all API paths that were deployed by other projects and aliases before). If you now deploy an alias of a specific project where you test a new API (maybe some old paths deleted) this will end up in any alias. As the staging area now contains all endpoints from the last deployments they will be included. Regardless for which alias.

Sample:
* Deploy Project A mynewAPI (incompatible with myOldAPI).
* Deploy Project B myOldAPI
=> The last deployment will grab everything from the staging area (see my AWS stage explanation above), which now apparently contains A's mynewApi and puts it into the shared stage myOldAPI. So this deployment breaks the stage.

Imo this is the hardest nut in the collection of problems that have to be solved. One solution would be to deploy all projects every time ... not good!

:boom: Removals of project aliases will not remove their API anymore because that is owned by the master project now.

:boom: The master project must not uninstall any of it's aliases before all related project's aliases with the same names are removed. Otherwise the stage would just disappear leaving the alias stacks of the other projects in an inconsistent state.

API global resources

Authorizers and domain name mappings are global per API. With a shared API their names must be unique. Not sure if that imposes any problems.

I think for the beginning this should be enough to start a discussion.... I did not want to write an entire book here :smiley:

HyperBrain avatar Nov 09 '17 19:11 HyperBrain