dougmoscrop / serverless-plugin-split-stacks

A plugin to generate nested stacks to get around CloudFormation resource/parameter/output limits
297 stars 68 forks source link

Outputs count X is greater than max allowed 60. #15

Open NijsTom opened 6 years ago

NijsTom commented 6 years ago

Have been running into the 200 stack limit and my solution to it was manually maintaining a swagger doc file and manually updating it. Attempted to use this plugin and ran into an issue listed below, if you need any more information from me, just ask. Cheers

Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: [serverless-plugin-split-stacks]: Summary: 99 resources migrated in to 3 nested stacks Serverless: [serverless-plugin-split-stacks]: Resources per stack: Serverless: [serverless-plugin-split-stacks]: - (root): 167 Serverless: [serverless-plugin-split-stacks]: - APINestedStack: 97 Serverless: [serverless-plugin-split-stacks]: - PermissionsNestedStack: 1 Serverless: [serverless-plugin-split-stacks]: - VersionsNestedStack: 1 Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Uploading service .zip file to S3 (37.36 MB)... Serverless: Validating template... Serverless: Updating Stack... Serverless: Checking Stack update progress... ..... Serverless: Operation failed!

Serverless Error ---------------------------------------

An error occurred: APINestedStack - Template format error: Outputs count 81 is greater than max allowed 60.

Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Forums: forum.serverless.com Chat: gitter.im/serverless/serverless

Your Environment Information ----------------------------- OS: win32 Node Version: 6.10.2 Serverless Version: 1.23.0

dougmoscrop commented 6 years ago

Unfortunately this is another CloudFormation limitation. We might be able to make some of this done via a Map:: parameter instead. The hope is that we can revisit splitting per function, which also might help here.

If you want to share your cloudformation .json files, please feel free - I will have a look, but make sure you've sanitized them of anything sensitive (anonymize stuff, remove secrets/etc).

dougmoscrop commented 6 years ago

I pushed a branch, of mostly untested code (sorry!) that initiate sub-stack splitting if outputs reaches 60. You can try it by changing the plugin version in your package.json to: github:dougmoscrop/serverless-plugin-split-stacks#split_on_outputs -- let me know if this works for you, @NijsTom @yogumanivannan @brunocascio

AgentGoldPaw commented 6 years ago

this did not work for me. I switched my package.json to this and am still getting the above mentioned error.

dfloresgonz commented 6 years ago

any solutions to this error?

dougmoscrop commented 6 years ago

Ok so the output-splitting I did is a fix for one scenario but not another.

I don't think the problem is with this library, per se. The problem is Serverless puts each function version in an Output: https://github.com/serverless/serverless/blob/2fe45421133d25ec81093744752f852aa672a795/lib/plugins/aws/package/compile/functions/index.js#L379

So, this plugin just let you get to a real world situation of having too many functions. But if you created a toy Serverless project and added like 60 or so functions to it, I expect you would get the same error.

Whoops: I had suggested using Mappings in the past, but they only supports literals. We, nor Serverless, can use them for things that have to use intrinsic functions (Ref or Fn::GetAtt to get arn, for example).

Given that Serverless Output always contains bucket and possibly API endpoint, I think hard limit of 58 functions at most can be supported.

This is a limitation of CloudFormation and Serverless and working around it is gonna be .. complicated.

Ideas:

dougmoscrop commented 6 years ago

You can try setting:

provider:
  versionFunctions: false

https://github.com/serverless/serverless/blob/2fe45421133d25ec81093744752f852aa672a795/lib/plugins/aws/package/compile/functions/index.js#L386

AgentGoldPaw commented 6 years ago

I will get back to on this. Just wanted to let you know I saw this.

AgentGoldPaw commented 6 years ago

versionFunctions fixed me issue.

SpencerGreene commented 6 years ago

I'm having this exact problem and setting versionFunctions: false makes no difference. Any theories why that might be?

MacMcIrish commented 6 years ago

If anyone is having issues with the APINestedStack having too many outputs, we were able to resolve this by further separating the ApiGateway resources into more stacks grouped together with the api methods. So a lambda function for GET /foo would be broken into at least the following 3 stacks:

FooNestedStack (contains the lamdba function foo) FooResourcesNestedStack (contains the AWS::ApiGateway::Method and AWS::ApiGateway::Resource cloudformation resources) APINestedStack (contains and exports the reference to the Api Gateway)

The issue for us was the APINestedStack needed to export the ApiGateway::Resources so they could be referenced by the ApiGateway::Methods. Grouping them together removes the need for the export, which resolves the output limit.

ivanhoe1982 commented 5 years ago

@MacMcIrish how exactly did you do this split? can you point me to the right part of the plugin and what you modified? I've been banging my head on this topic for a couple of hours now, still without success

dougmoscrop commented 5 years ago

You should not have to modify the plugin, just the custom split-stacks.js file which lets you totally customize the 'routing' logic.

That said, I'd welcome any PRs that add more intelligent splitting for these things that affect many users

ivanhoe1982 commented 5 years ago

@dougmoscrop I have written a strategy in stacks-map.js by overloading ServerlessPluginSplitStacks.resolveMigration which did somethign similar to 'per-type' strategy... until I hit the 60 outputs limit for AWS::ApiGateway::Resource (which I did hit in per-type strategy too); any attempts at further splitting this result in 'circular dependency' warning and that's why I would love to see a custom strategy written by someone smarter than me - it would probably help me diagnose what I'm doing wrong

MacMcIrish commented 5 years ago

@ivanhoe1982 I'll warn you upfront, this solution only worked as a bandaid for us. Serverless-plugin-split-stacks is a great plugin for when serverless brings you up to just short of your requirements, but eventually you'll hit other cloudformation limits as well. Since my comment, we've actually removed having our api endpoints separated by api gateway resources, and instead use some internal routing.

But what we were doing in the meantime was we would create a mapping for each api endpoint based on it's root uri, as well as a mapping for each routes AWS::ApiGateway::Method and AWS::ApiGateway::Resource. So /foo/bar/baz's handler would bucket into a stack called fooStack The actual route /foo/bar/baz for the api gateway would bucket into fooStackResources And GET /foo/bar/baz would bucket into fooStackResources The way these relationships work internally meant no circular dependencies, and it works if you want to split further, ie /foo -> [fooStack, fooStackResources], /foo/bar/ -> [fooBarStack, fooBarStackResources]

I tried to make this as accurate as I could, and apologies for any misinformation, it's been a month since we've ripped this out so it's only slightly fresh in my mind :)

juvaly commented 5 years ago

I have a similar issue with Parameter count: Template format error: Parameter count 89 is greater than max allowed 60

Any ideas how to resolve?

dougmoscrop commented 5 years ago

You have to refactor your stacks to split them more aggressively using stacks-map

juvaly commented 5 years ago

I did. I tried splitting them by Alphabet :) But the max 60 parameters seems to be global and not per stack. The 89 count I get in the error is the sum of parameters in all nested stacks.

On Wed, Apr 17, 2019, 22:07 Doug Moscrop notifications@github.com wrote:

You have to refactor your stacks to split them more aggressively using stacks-map

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/dougmoscrop/serverless-plugin-split-stacks/issues/15#issuecomment-484221871, or mute the thread https://github.com/notifications/unsubscribe-auth/AAOAANEXB32MN52TFA2ZGJTPQ5YQPANCNFSM4EAXJTUA .

dougmoscrop commented 5 years ago

I've been meaning to write a helper utility to explain stack summaries but for now you have to look at the compiled cloudformation (stack-update.json) and see which stack has a huge # of params. It's def not "total" but per-nested stack

juvaly commented 5 years ago

You are right. The split did the job, and the error that followed was unrelated to the Parameters. I was too tired to notice :/ Thanks for the help!

On Wed, Apr 17, 2019 at 11:04 PM Doug Moscrop notifications@github.com wrote:

I've been meaning to write a helper utility to explain stack summaries but for now you have to look at the compiled cloudformation (stack-update.json) and see which stack has a huge # of params. It's def not "total" but per-nested stack

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/dougmoscrop/serverless-plugin-split-stacks/issues/15#issuecomment-484240529, or mute the thread https://github.com/notifications/unsubscribe-auth/AAOAANC2KAMFSJQOYROYJ5TPQ57GDANCNFSM4EAXJTUA .

dougmoscrop commented 5 years ago

The support for splitting when Outputs reaches 60 landed in 1.9.0, however I realized just now that it assumes each resource only adds one Output, so in theory it could go 1, 2, 3... 59, then have a resource that adds two outputs and it would blow up. Supporting that scenario is a bit more involved so I will leave this open, and consider the Output support that currently exists as hopeful/optimistic

vicary commented 5 years ago

I pushed a branch, of mostly untested code (sorry!) that initiate sub-stack splitting if outputs reaches 60. You can try it by changing the plugin version in your package.json to: github:dougmoscrop/serverless-plugin-split-stacks#split_on_outputs -- let me know if this works for you, @NijsTom @yogumanivannan @brunocascio

This method temporarily solves our problem, but our AppSync stack is growing fast. Hope it doesn't hit the limitations soon.

I have function versions disabled.

martineca commented 4 years ago

Hi all! I am a bit confused, if we are getting this error but from the main stack, the one that holds links to all the nested stacks does that mean that our only option is to split the project into more .yml files? If yes then isn't that limit of 200 resources not valid if you have mainly lambdas as each lambda created new output line meaning maximum lambdas = 60?

dougmoscrop commented 4 years ago

yes, you have to turn off version functions for that

martineca commented 4 years ago

I was passing --versionFunction true as cli variable on each deploy but that is being read as a string instead of a boolean. Just changed it to false in the .yml file and it works as expected now. Thanks!

gmagella-ca commented 4 years ago

You can try setting:

provider:
  versionFunctions: false

https://github.com/serverless/serverless/blob/2fe45421133d25ec81093744752f852aa672a795/lib/plugins/aws/package/compile/functions/index.js#L386

Fantastic! this should be documented a bit better in the docs, or even in the treated error message from Serverless. Helped me! Thanks