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

Exclude not excluding a node_modules subdirectory #7837

Open
nampas opened this issue Jun 12, 2020 · 6 comments
Open

Exclude not excluding a node_modules subdirectory #7837

nampas opened this issue Jun 12, 2020 · 6 comments

Comments

@nampas
Copy link

nampas commented Jun 12, 2020

I was trying to pull all my node_modules into a lambda layer, but running into an issue because the lambda layer is too big.

ServerlessError: An error occurred: NodemodulesLambdaLayer - Unzipped size must be smaller than 262144000 bytes 

Fair enough, it is big. I went ahead and tried to exclude the aws-sdk node_modules subdirectory:

layers:
  nodemodules:
    name: ${self:service.name}-node-modules-${self:provider.stage}
    path: node_modules
    package:
      exclude:
        - '!node_modules/**'
        - 'node_modules/aws-sdk/**'

package:
  exclude:
    - .envrc*
    - node_modules/**
    - kubernetes/**
    - ci/**
    - images/**

That doesn't work though. I'm still getting the aws-sdk included in the zip:

$ sls package
... does its thing ...
$ unzip .serverless/nodemodules && ls -la .serverless/nodemodules | grep aws-sdk
drwxr-xr-x   24 npastor  staff     768 Jun 12 12:30 aws-sdk
serverless.yml
service: resourceSync

plugins:
  - serverless-plugin-vpc-eni-cleanup
  - serverless-s3-remover
  - serverless-step-functions

custom:
  remover:
    buckets:
      - ${self:custom.lastRunTimeBucketName}
  byStage:
    default:
      # properties
    prod:
      # prod properties
    staging:
      # staging proeprties 
  # Consolidated properties for current stage

provider:
  #
  # General settings
  #
  name: aws
  # Deploy a different stage via `serverless deploy -v --stage somestage`
  stage: ${opt:stage, 'dev'}
  deploymentBucket:
    name: ${self:custom.s3DeployBucket}
  #
  # Lambda-specific settings
  #
  runtime: nodejs10.x
  memorySize: 256
  timeout: 30 # seconds
  versionFunctions: false
  logRetentionInDays: 14
  environment:
    # Env vars
  tags:
    owner: core-marketplace
  role: ${self:custom.lambdaRole}
  vpc: ${self:custom.vpc}
  layers: [{ Ref: NodemodulesLambdaLayer }]

layers:
  nodemodules:
    name: ${self:service.name}-node-modules-${self:provider.stage}
    path: node_modules
    package:
      exclude:
        - '!node_modules/**'
        - 'node_modules/aws-sdk/**'

package:
  exclude:
    - .envrc*
    - node_modules/**
    - kubernetes/**
    - ci/**
    - images/**

functions:
  # Token authentication function for api gateway requests
  tokenAuthorizer:
    enabled: ${self:custom.apiGatewayEnabled}
    name: ${self:service.name}-tokenAuthorizer-${self:provider.stage}
    handler: src/handlers/token_authorizer.handler
    environment:
      TOKEN: ${ssm:${self:service.name}-tokenAuthorizerKey-dev}

  # A function that receives messages from the main event queue
  processResourceUpdate:
    name: ${self:service.name}-processResourceUpdate-${self:provider.stage}
    handler: src/handlers/process_resource_update.handler
    timeout: 120 # needs to be less than or equal to the EventQueue VisibilityTimeout
    events:
      - sqs:
          arn:
            Fn::GetAtt:
              - EventQueue
              - Arn
          batchSize: 1
    environment:
      REDIS_ENDPOINT: ${self:custom.redisEndpoint}
      REDIS_KEY_EXPIRATION: ${self:custom.redisKeyExpiration}
      RESOURCE_CATALOG_S3_BUCKET: ${self:custom.resourceCatalogS3Bucket}
    reservedConcurrency: 50

  # There are some other functions but they're not much different

stepFunctions:
  stateMachines:
    # Input:
    #   {
    #     afterId:    10000, // optional. ID to start after. Default is 0.
    #     untilId:    20000, // optional. Maximum ID to fetch. Default is undefined.
    #     queryLimit:  5000, // optional. Limit of how many ids to query per Lambda invocation. Default is 5000.
    #   }
    reimport:
      id: ResourceReimportStateMachine
      name: ${self:service.name}-reimport-${self:provider.stage}
      role: ${self:custom.sfnRole}
      definition:
        StartAt: PublishItems
        States:
          PublishItems:
            Type: Task
            Resource:
              Fn::GetAtt: [PublishResourceReimportLambdaFunction, Arn]
            Retry:
              - ErrorEquals:
                - States.ALL
                IntervalSeconds: 4
                MaxAttempts: 4
                BackoffRate: 2
            Next: ContinueOrStop
          ContinueOrStop:
            Type: Choice
            Choices:
              - Variable: '$.hasMore'
                BooleanEquals: True
                Next: PublishItems
            Default: Finished
          Finished:
            Type: Succeed
    # One other state machine
REPLACE WITH FULL COMMAND NAME output

$ SLS_DEBUG=* sls package
Serverless: Load command interactiveCli
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command config:tabcompletion
Serverless: Load command config:tabcompletion:install
Serverless: Load command config:tabcompletion:uninstall
Serverless: Load command create
Serverless: Load command install
Serverless: Load command package
Serverless: Load command deploy
Serverless: Load command deploy:function
Serverless: Load command deploy:list
Serverless: Load command deploy:list:functions
Serverless: Load command invoke
Serverless: Load command invoke:local
Serverless: Load command info
Serverless: Load command logs
Serverless: Load command metrics
Serverless: Load command print
Serverless: Load command remove
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command slstats
Serverless: Load command plugin
Serverless: Load command plugin
Serverless: Load command plugin:install
Serverless: Load command plugin
Serverless: Load command plugin:uninstall
Serverless: Load command plugin
Serverless: Load command plugin:list
Serverless: Load command plugin
Serverless: Load command plugin:search
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command upgrade
Serverless: Load command uninstall
Serverless: Load command s3remove
Serverless: Load command invoke
Serverless: Load command invoke:stepf
Serverless: Load command login
Serverless: Load command logout
Serverless: Load command generate-event
Serverless: Load command test
Serverless: Load command dashboard
Serverless: Load command output
Serverless: Load command output:get
Serverless: Load command output:list
Serverless: Load command param
Serverless: Load command param:get
Serverless: Load command param:list
Serverless: Load command studio
Serverless: Load command dev
Serverless: [AWS ssm 400 0.207s 0 retries] getParameter({ Name: 'resourceSync-graphApiSecret-dev',
WithDecryption: false })
Serverless: [AWS ssm 400 0.222s 0 retries] getParameter({ Name: 'resourceSync-datadogApiKey-dev',
WithDecryption: false })
Serverless: [AWS ssm 400 0.207s 0 retries] getParameter({ Name: 'resourceSync-rollbarToken-dev', WithDecryption: false })
Serverless Warning --------------------------------------

A valid SSM parameter to satisfy the declaration 'ssm:resourceSync-rollbarToken-dev' could not be found.

Serverless Warning --------------------------------------

A valid SSM parameter to satisfy the declaration 'ssm:resourceSync-rollbarToken-dev' could not be found.

Serverless Warning --------------------------------------

A valid SSM parameter to satisfy the declaration 'ssm:resourceSync-rollbarToken-dev' could not be found.

Serverless: [AWS ssm 400 0.164s 0 retries] getParameter({ Name: 'resourceSync-sumoEndpoint-dev', WithDecryption: false })

Serverless Warning --------------------------------------

A valid SSM parameter to satisfy the declaration 'ssm:resourceSync-sumoEndpoint-dev' could not be found.

Serverless Warning --------------------------------------

A valid SSM parameter to satisfy the declaration 'ssm:resourceSync-sumoEndpoint-dev' could not be found.

Serverless Warning --------------------------------------

A valid SSM parameter to satisfy the declaration 'ssm:resourceSync-sumoEndpoint-dev' could not be found.

Serverless: [AWS ssm 400 0.186s 0 retries] getParameter({ Name: 'resourceSync-tokenAuthorizerKey-dev',
WithDecryption: false })

Serverless: [AWS cloudformation 200 0.51s 0 retries] describeStacks({ StackName: 'resourceSync-outputs-dev' })
Serverless: Invoke package
Serverless: Invoke aws:common:validate
Serverless: Invoke aws:common:cleanupTempDir
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Excluding development dependencies...
Serverless: [AWS cloudformation 400 0.218s 0 retries] describeStacks({ StackName: 'resourceSync-dev' })
Serverless: Invoke aws:package:finalize
Serverless: Invoke aws:common:moveArtifactsToPackage

Installed version

$ sls --version
Framework Core: 1.72.0
Plugin: 3.6.13
SDK: 2.3.1
Components: 2.30.14
@nampas
Copy link
Author

nampas commented Jun 12, 2020

Note that the reason that aws-sdk isn't getting automatically excluded by the Excluding development dependencies... step is because some node dependencies of this project include aws-sdk as a dependency 🤦 . Either way, I would still expect to be able to manually exclude the folder via the exclude chunk above.

@medikoo
Copy link
Contributor

medikoo commented Jun 15, 2020

@nampas thanks for report. There are known issues with packaging in general, and there's a dedicated issue for that: ehttps://github.com//issues/6580

Still any PR that fixes that before broader refactor is made is welcome

@nampas
Copy link
Author

nampas commented Jun 15, 2020

Sounds good, thanks for the response.

@FanFataL
Copy link
Contributor

FanFataL commented Jun 16, 2020

@nampas You can use include insted of exclude to achive what you want:

  package:
    include:
      - 'node_modules/**'
      - '!node_modules/**/aws-sdk/**'

Hint: If you want you code works with node_modules from lambda you need to put it into nodejs directory. https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path

Our project lambda package build looks like this:
layer-code:
  path: layerPath
  name: layerName
  compatibleRuntimes:
    - nodejs10.x
    - nodejs12.x
  package:
    include:
      - 'nodejs/node_modules/**'
      - '!nodejs/node_modules/lodash/**'
      - '!nodejs/node_modules/moment-timezone/builds/**'
      - '!nodejs/node_modules/moment/min/**'
      - '!nodejs/node_modules/moment/**/locale/**'
      - '!nodejs/node_modules/**/aws-sdk/**'
      - '!nodejs/node_modules/**/.ts-node/**'
      - '!nodejs/node_modules/**/*.md'
      - '!nodejs/node_modules/**/*.flow'
      - '!nodejs/node_modules/**/*.patch'
      - '!nodejs/node_modules/**/*.conf'
      - '!nodejs/node_modules/**/*.markdown'
      - '!nodejs/node_modules/**/*.coffee'
      - '!nodejs/node_modules/**/jsdoc_conf.json'
      - '!nodejs/node_modules/**/*Makefile'
      - '!nodejs/node_modules/**/Dockerfile'
      - '!nodejs/node_modules/**/*.txt'
      - '!nodejs/node_modules/**/*.yml'
      - '!nodejs/node_modules/**/*.xml'
      - '!nodejs/node_modules/**/*.html'
      - '!nodejs/node_modules/**/test/**'
      - '!nodejs/node_modules/**/tests/**'
      - '!nodejs/node_modules/**/docs/**'
      - '!nodejs/node_modules/**/examples/**'
      - '!nodejs/node_modules/**/coverage/**'
      - '!nodejs/node_modules/**/.nyc_output/**'
      - '!nodejs/node_modules/**/bin/**'
      - '!nodejs/node_modules/**/bower.json'
      - '!nodejs/node_modules/**/karma.conf.js'
      - '!nodejs/node_modules/**/Gruntfile.js'
      - '!nodejs/node_modules/**/rollup.config.*'
      - '!nodejs/node_modules/**/yarn.lock'
      - '!nodejs/node_modules/**/sonar-project.properties'
      - '!nodejs/node_modules/**/package-lock.json'
      - '!nodejs/node_modules/**/*.d.ts'
      - '!nodejs/node_modules/**/*.map'
      - '!nodejs/node_modules/**/*.iml'
      - '!nodejs/node_modules/**/*.gif'
      - '!nodejs/node_modules/**/*.png'
      - '!nodejs/node_modules/**/*.jpg'
      - '!nodejs/node_modules/**/*.jpeg'
      - '!nodejs/node_modules/**/bluebird/js/browser/**'
      - 'nodejs/node_modules/moment/**/locale/en-gb.js'
      - 'nodejs/node_modules/lodash/lodash.js'
      - 'nodejs/node_modules/lodash/index.js'
      - 'nodejs/node_modules/lodash/package.json'

Additionaly the nodejs directory can be build with the --production flag.

@medikoo
Copy link
Contributor

medikoo commented Dec 3, 2021

I think this issue is related to #8612 (fact that package patters are resolved against layer directory path and not a service path).

@bitsofinfo
Copy link

same issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants