serverless-webpack icon indicating copy to clipboard operation
serverless-webpack copied to clipboard

sls invoke local causing rewriting .webpack directory

Open LantosIstvan opened this issue 7 years ago • 20 comments

This is a Bug Report

Description

I have the following serverless.yml:

# NOTE: update this with your service name
service: lanti-serverless-stack-api
frameworkVersion: "=1.27.1"

# Use the serverless-webpack plugin to transpile ES6
plugins:
  - serverless-webpack
  - serverless-dynamodb-local
  - serverless-offline #serverless-offline needs to be last in the list

# serverless-webpack configuration
# Enable auto-packing of external modules
custom:
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true
    packager: yarn
  stage: ${opt:stage, self:provider.stage}
  DB_PREFIX: ${file(./env.yml):${self:custom.stage}.DB_PREFIX}
  dynamodb:
    start:
      port: 8000
      inMemory: true
      migrate: true
      seed: true
    seed:
      domain:
        sources:
          - table: notes
            sources: [./offline/migrations/todo-seed.json]

resources:
  Resources: ${file(offline/migrations/todo.yml)}

package:
  individually: true
  exclude:
    - node_modules/dynamodb-localhost/**
    - node_modules/serverless-dynamodb-local/**
    - node_modules/serverless-offline/**

provider:
  name: aws
  runtime: nodejs8.10
  profile: serverless
  stage: dev
  region: us-east-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:DescribeTable
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource:
        - "arn:aws:dynamodb:*:*"
  environment:
    APP_SECRET: ${file(./env.yml):${self:custom.stage}.APP_SECRET}
    DB_PREFIX: ${file(./env.yml):${self:custom.stage}.DB_PREFIX}

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: hello
          method: get
          cors: true
  create:
    handler: lambdas/create.main
    events:
      - http:
          path: notes
          method: post
          cors: true
          authorizer: aws_iam
  get:
    handler: lambdas/get.main
    events:
      - http:
          path: notes/{id}
          method: get
          cors: true
          authorizer: aws_iam
  list:
    handler: lambdas/list.main
    events:
      - http:
          path: notes
          method: get
          cors: true
          authorizer: aws_iam
  update:
    handler: lambdas/update.main
    events:
      - http:
          path: notes/{id}
          method: put
          cors: true
          authorizer: aws_iam
  delete:
    handler: lambdas/delete.main
    events:
      - http:
          path: notes/{id}
          method: delete
          cors: true
          authorizer: aws_iam

This is my webpack.config.js:

const slsw = require('serverless-webpack');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  entry: slsw.lib.entries,
  target: 'node',
  // Generate sourcemaps for proper error messages
  devtool: 'source-map',
  // Since 'aws-sdk' is not compatible with webpack,
  // we exclude all node dependencies
  externals: [nodeExternals()],
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  optimization: {
    // We no not want to minimize our code.
    minimize: false,
  },
  performance: {
    // Turn off size warnings for entry points
    hints: false,
  },
  // Run babel on all .js files and skip those in node_modules
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: __dirname,
        exclude: /node_modules/,
      },
    ],
  },
};

When I try to run the following command:

$ SET SLS_DEBUG=* && sls invoke local --function create --path mocks/create-event.json

It's halting the server, because re-writing the entire folder with the one create function only:

Serverless: Load command run
Serverless: Load command config
Serverless: Load command config:credentials
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 login
Serverless: Load command logout
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 emit
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command webpack
Serverless: Load command dynamodb
Serverless: Load command dynamodb:migrate
Serverless: Load command dynamodb:seed
Serverless: Load command dynamodb:start
Serverless: Load command dynamodb:noStart
Serverless: Load command dynamodb:remove
Serverless: Load command dynamodb:install
Serverless: Load command offline
Serverless: Load command offline:start
Serverless: Invoke invoke:local
Serverless: Invoke webpack:validate
Serverless: Invoke webpack:compile
Serverless: Bundling with Webpack...
Time: 2157ms
Built at: 2018-05-05 22:02:57
                Asset      Size          Chunks             Chunk Names
    lambdas/create.js  9.69 KiB  lambdas/create  [emitted]  lambdas/create
lambdas/create.js.map  8.34 KiB  lambdas/create  [emitted]  lambdas/create
Entrypoint lambdas/create = lambdas/create.js lambdas/create.js.map
[./lambdas/create.js] 2.34 KiB {lambdas/create} [built]
[./libs/dynamodb-lib.js] 754 bytes {lambdas/create} [built]
[./libs/response-lib.js] 840 bytes {lambdas/create} [built]
[aws-sdk] external "aws-sdk" 42 bytes {lambdas/create} [built]
[babel-runtime/core-js/json/stringify] external "babel-runtime/core-js/json/stringify" 42 bytes {lambdas/create} [built]
[babel-runtime/helpers/asyncToGenerator] external "babel-runtime/helpers/asyncToGenerator" 42 bytes {lambdas/create} [built]
[babel-runtime/regenerator] external "babel-runtime/regenerator" 42 bytes {lambdas/create} [built]
[source-map-support/register] external "source-map-support/register" 42 bytes {lambdas/create} [built]
[uuid] external "uuid" 42 bytes {lambdas/create} [built]
{ ResourceNotFoundException: Requested resource not found
    at Request.extractError (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\protocol\json.js:48:27)
    at Request.callListeners (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:105:20)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:77:10)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:683:14)
    at Request.transition (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:22:10)
    at AcceptorStateMachine.runTo (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:14:12)
    at D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:26:10
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:38:9)
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:685:12)
    at Request.callListeners (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:115:18)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:77:10)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:683:14)
    at Request.transition (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:22:10)
    at AcceptorStateMachine.runTo (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:14:12)
    at D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:26:10
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:38:9)
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:685:12)
    at Request.callListeners (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:115:18)
    at callNextListener (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:95:12)
    at IncomingMessage.onEnd (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\event_listeners.js:269:13)
    at IncomingMessage.emit (events.js:187:15)
    at IncomingMessage.EventEmitter.emit (domain.js:442:20)
    at endReadableNT (_stream_readable.js:1091:14)
    at process._tickCallback (internal/process/next_tick.js:174:19)
  message: 'Requested resource not found',
  code: 'ResourceNotFoundException',
  time: 2018-05-05T20:02:59.235Z,
  requestId: 'MSHUC9B0RLRIH4TL3J3I52MGQ7VV4KQNSO5AEMVJF66Q9ASUAAJG',
  statusCode: 400,
  retryable: false,
  retryDelay: 9.94491247364846 }

In a normal build, functions presented in .webpack/service folder (handler.js file), and every other function in a lambda subfolder.

If I run this with the --no-build flag, this is what I got:

Serverless: Load command run
Serverless: Load command config
Serverless: Load command config:credentials
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 login
Serverless: Load command logout
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 emit
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command webpack
Serverless: Load command dynamodb
Serverless: Load command dynamodb:migrate
Serverless: Load command dynamodb:seed
Serverless: Load command dynamodb:start
Serverless: Load command dynamodb:noStart
Serverless: Load command dynamodb:remove
Serverless: Load command dynamodb:install
Serverless: Load command offline
Serverless: Load command offline:start
Serverless: Invoke invoke:local
Serverless: Invoke webpack:validate
Serverless: Skipping build and using existing compiled output

  Error --------------------------------------------------

  ENOENT: no such file or directory, chdir 'D:\www\node\serverless\lanti-serverless-stack\api\.webpack\create'

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Stack Trace --------------------------------------------

Error: ENOENT: no such file or directory, chdir 'D:\www\node\serverless\lanti-serverless-stack\api\.webpack\create'
    at process.chdir (C:\Users\User\AppData\Roaming\npm\node_modules\serverless\node_modules\graceful-fs\polyfills.js:21:9)
    at process.chdir (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\graceful-fs\polyfills.js:21:9)
    at ServerlessWebpack.prepareLocalInvoke (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\serverless-webpack\lib\prepareLocalInvoke.js:24:13)
From previous event:
    at Object.before:invoke:local:invoke [as hook] (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\serverless-webpack\index.js:123:10)
    at BbPromise.reduce (C:\Users\User\AppData\Roaming\npm\node_modules\serverless\lib\classes\PluginManager.js:372:55)
    at runCallback (timers.js:696:18)
    at tryOnImmediate (timers.js:667:5)
    at processImmediate (timers.js:649:5)
    at process.topLevelDomainCallback (domain.js:121:23)

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information -----------------------------
     OS:                     win32
     Node Version:           10.0.0
     Serverless Version:     1.27.1

Similar or dependent issue(s):

  • None that I know about.

Additional Data

  • Serverless-Webpack Version you're using: 5.1.5
  • Webpack version you're using: 4.7.0
  • Serverless Framework Version you're using: 1.27.1
  • Operating System: Windows 10 v10.0.17134.1

LantosIstvan avatar May 05 '18 20:05 LantosIstvan

Hi @DJviolin,

I have to make sure that I understand your problem correctly to solve it.

Please confirm that this is what you want to do:

  • Run your service with serverless-offline
  • Invoke a single function while the service is running with offline

Normally this should work by using the --no-build switch with incoke local because serverless-offline will take care of the rebuilds implicitly. But I have an idea what could be the issue here - if my assumption above of what you want to achieve is right. The offline build uses service packaging, whilst the invoke function (even with --no-build) assumes individual packaging.

I'm quite sure that I can solve this quickly in this case.

HyperBrain avatar May 06 '18 11:05 HyperBrain

Hi @HyperBrain ,

Yes, this is exactly what I want to achieve. First I start my dev environment with the following commands in package.json by $ yarn start (I use Yarn):

"start:dynamodb": "cd api && sls dynamodb start",
"start:offline-server": "cd api && sls offline start --noAuth",
"start:client": "cd client && yarn start",
"start": "concurrently \"yarn run start:dynamodb\" \"yarn run start:offline-server\" \"yarn run start:client\""

Then I want to test the functions from the command line, like this one:

$ cd api && sls invoke local --function create --path mocks/create-event.json --no-build

LantosIstvan avatar May 06 '18 12:05 LantosIstvan

I'll try to fix it and will open a PR tomorrow that you can use to test.

HyperBrain avatar May 06 '18 12:05 HyperBrain

Thank You!

LantosIstvan avatar May 06 '18 12:05 LantosIstvan

@DJviolin Can you try with "serverless-webpack": "github:serverless-heaven/serverless-webpack#385-support-no-build-with-offline" and then use serverless invoke local ... --no-build --webpack-offline to invoke a function while serverless-offline is running?

I had to add a new switch, because the invoke local command cannot determine if a serverless-offline session is running and also that you want to execute a single function locally in its context.

I'll think a bit further about the new switch and maybe a combined --no-build=offline would be better in the end. However, please check with the additional --webpack-offline switch first, if the approach works in general. I'll keep you updated on the final implementation.

HyperBrain avatar May 08 '18 11:05 HyperBrain

I'm getting this output now:

$ cd api && SET SLS_DEBUG=* && sls invoke local --function create --path offline/mocks/create-event.json --no-build --webpack-offline
Serverless: Load command run
Serverless: Load command config
Serverless: Load command config:credentials
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 login
Serverless: Load command logout
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 emit
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command webpack
Serverless: Load command dynamodb
Serverless: Load command dynamodb:migrate
Serverless: Load command dynamodb:seed
Serverless: Load command dynamodb:start
Serverless: Load command dynamodb:noStart
Serverless: Load command dynamodb:remove
Serverless: Load command dynamodb:install
Serverless: Load command offline
Serverless: Load command offline:start
Serverless: Invoke invoke:local
Serverless: Invoke webpack:validate
Serverless: Skipping build and using existing compiled output
{ ResourceNotFoundException: Requested resource not found
    at Request.extractError (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\protocol\json.js:48:27)
    at Request.callListeners (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:105:20)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:77:10)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:683:14)
    at Request.transition (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:22:10)
    at AcceptorStateMachine.runTo (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:14:12)
    at D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:26:10
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:38:9)
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:685:12)
    at Request.callListeners (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:115:18)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:77:10)
    at Request.emit (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:683:14)
    at Request.transition (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:22:10)
    at AcceptorStateMachine.runTo (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:14:12)
    at D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\state_machine.js:26:10
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:38:9)
    at Request.<anonymous> (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\request.js:685:12)
    at Request.callListeners (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:115:18)
    at callNextListener (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\sequential_executor.js:95:12)
    at IncomingMessage.onEnd (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\aws-sdk\lib\event_listeners.js:269:13)
    at IncomingMessage.emit (events.js:187:15)
    at IncomingMessage.EventEmitter.emit (domain.js:442:20)
    at endReadableNT (_stream_readable.js:1091:14)
    at process._tickCallback (internal/process/next_tick.js:174:19)
  message: 'Requested resource not found',
  code: 'ResourceNotFoundException',
  time: 2018-05-08T14:57:47.645Z,
  requestId: '52LTIEDBKTD14E2FUK4EPKB7KFVV4KQNSO5AEMVJF66Q9ASUAAJG',
  statusCode: 400,
  retryable: false,
  retryDelay: 5.893724675164447 }

This is how the .webpack directory looks like in this case (and this is the normal directory structure, without invoke local as well):

\---service
    |   handler.js
    |   handler.js.map
    |
    \---lambdas
            create.js
            create.js.map
            delete.js
            delete.js.map
            get.js
            get.js.map
            list.js
            list.js.map
            update.js
            update.js.map

If I ditching the --no-build flag:

$ cd api && SET SLS_DEBUG=* && sls invoke local --function create --path offline/mocks/create-event.json --webpack-offline
Serverless: Load command run
Serverless: Load command config
Serverless: Load command config:credentials
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 login
Serverless: Load command logout
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 emit
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command webpack
Serverless: Load command dynamodb
Serverless: Load command dynamodb:migrate
Serverless: Load command dynamodb:seed
Serverless: Load command dynamodb:start
Serverless: Load command dynamodb:noStart
Serverless: Load command dynamodb:remove
Serverless: Load command dynamodb:install
Serverless: Load command offline
Serverless: Load command offline:start
Serverless: Invoke invoke:local
Serverless: Invoke webpack:validate
Serverless: Invoke webpack:compile
Serverless: Bundling with Webpack...
Time: 1944ms
Built at: 2018-05-08 17:00:54
                Asset      Size          Chunks             Chunk Names
    lambdas/create.js  11.2 KiB  lambdas/create  [emitted]  lambdas/create
lambdas/create.js.map  8.43 KiB  lambdas/create  [emitted]  lambdas/create
Entrypoint lambdas/create = lambdas/create.js lambdas/create.js.map
[./lambdas/create.js] 2.9 KiB {lambdas/create} [built]
[./libs/dynamodb-lib.js] 1.34 KiB {lambdas/create} [built]
[./libs/response-lib.js] 1.18 KiB {lambdas/create} [built]
[aws-sdk] external "aws-sdk" 42 bytes {lambdas/create} [built]
[babel-runtime/core-js/json/stringify] external "babel-runtime/core-js/json/stringify" 42 bytes {lambdas/create} [built]
[babel-runtime/helpers/asyncToGenerator] external "babel-runtime/helpers/asyncToGenerator" 42 bytes {lambdas/create} [built]
[babel-runtime/regenerator] external "babel-runtime/regenerator" 42 bytes {lambdas/create} [built]
[source-map-support/register] external "source-map-support/register" 42 bytes {lambdas/create} [built]
[uuid] external "uuid" 42 bytes {lambdas/create} [built]

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

  --webpack-offline can only be specified together with --no-build

  Stack Trace --------------------------------------------

ServerlessError: --webpack-offline can only be specified together with --no-build
    at ServerlessWebpack.prepareLocalInvoke (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\serverless-webpack\lib\prepareLocalInvoke.js:20:31)
From previous event:
    at Object.before:invoke:local:invoke [as hook] (D:\www\node\serverless\lanti-serverless-stack\api\node_modules\serverless-webpack\index.js:123:10)
    at BbPromise.reduce (C:\Users\User\AppData\Roaming\npm\node_modules\serverless\lib\classes\PluginManager.js:372:55)
    at runCallback (timers.js:696:18)
    at tryOnImmediate (timers.js:667:5)
    at processImmediate (timers.js:649:5)
    at process.topLevelDomainCallback (domain.js:121:23)

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com

  Your Environment Information -----------------------------
     OS:                     win32
     Node Version:           10.0.0
     Serverless Version:     1.27.2

In this case, this is how the .webpack folder looks like:

\---create
    \---lambdas
            create.js
            create.js.map

In the first case, why the functions putted into a service folder inside .webpack? And in the second case, why the single create function putted into a create folder inside .webpack? Maybe the issue here are mismatching directories?

LantosIstvan avatar May 08 '18 15:05 LantosIstvan

If I ditching the --no-build flag

--webpack-offline is only valid as a specifier together with the --no-build flag to tell the plugin to invoke in the context of serverless-offline.

In the first case, why the functions putted into a service folder inside .webpack

serverless-offline requires service packaging and not individual packaging. Offline does not support multi-root environments where every function is put into a separate subfolder. That's why the plugin switches the mode automatically when invoked with serverless offline.

I think the invoke with --no-build --webpack-offline actually worked and executed the create function. The ResourceNotFoundException: Requested resource not found error is emitted by your code (some call into the aws-sdk) and seems to be related to some resource the create function is trying to access.

message: 'Requested resource not found',
  code: 'ResourceNotFoundException',
  time: 2018-05-08T14:57:47.645Z,
  requestId: '52LTIEDBKTD14E2FUK4EPKB7KFVV4KQNSO5AEMVJF66Q9ASUAAJG',
  statusCode: 400,
  retryable: false,
  retryDelay: 5.893724675164447

is definitely an error response from AWS. What kind of resource do you access in the create function, can you try to isolate the call that fails in the create function?

HyperBrain avatar May 08 '18 15:05 HyperBrain

Regarding the resource error: I think you also received that when you just execute the serverless invoke local without --no-build and without a running serverless-offline as you posted above.

Can you double check what a "standard" invoke local on the create function returns? I mean without serverless-offline running and without the --no-build switch.

HyperBrain avatar May 08 '18 15:05 HyperBrain

create.js is just the standard function from the Serverless Stack example, converted to node8.10 (but the errors are the same with the original code structure):

import uuid from 'uuid';
import * as dynamoDbLib from './libs/dynamodb-lib';
import { success, failure } from './libs/response-lib';

export const main = async (event) => {
  const data = JSON.parse(event.body);
  const params = {
    TableName: 'notes',
    Item: {
      userId: event.requestContext.identity.cognitoIdentityId,
      noteId: uuid.v1(),
      content: data.content,
      attachment: data.attachment,
      createdAt: Date.now(),
    },
  };

  try {
    await dynamoDbLib.call('put', params);
    return success(params.Item);
  } catch (err) {
    console.log(err);
    return failure({ status: false });
  }
};

I uploaded here the entire project for you to testing:

https://github.com/DJviolin/lanti-serverless-stack-gh

I slightly re-structured the functions.

The purpose of this project would be to spin up (and remove) the entire stack with Serverless + CloudFormation script inside, without touching the web console.

LantosIstvan avatar May 08 '18 16:05 LantosIstvan

Did you create the "notes" table in AWS?

I think the reason is, that with serverless-offline the dynamodb-local plugin gets activated and simulates the table locally. But with invoke local the code is executed as is and tries to access the live table in AWS Dynamo and not locally. Maybe the dynamodb-local plugin does not support invoke local.

To verify this assumption, can you create an empty DynamoDB table named "notes" in your account and see if invoke local then works?

HyperBrain avatar May 08 '18 16:05 HyperBrain

Your assumption is right, it tries to push into AWS directly and it succeeds. It's populated the newly created table on AWS.

I didn't thought about this, sorry.

LantosIstvan avatar May 08 '18 16:05 LantosIstvan

No problem. Maybe a feature request for dynamodb-local to somehow support invoke local would be useful.

HyperBrain avatar May 08 '18 16:05 HyperBrain

I will do, but right now this is not my priority.

I wonder, what would I gain if invoke local will work in serverless-offline? Maybe I'm wrong, but authorization in serverless-offline is not available and only a dummy user exists namely: offlineContext_cognitoIdentityId.

So I used curl and I was able to modify the local DynamoDB table with these commands on the exposed api routes:

# create-event.json
$ curl -X POST -H "Content-Type: application/json" -d "{\"content\":\"hello world\",\"attachment\":\"hello.jpg\"}" http://localhost:3000/notes
# list-event.json
$ curl -X GET http://localhost:3000/notes
# get-event.json
$ curl -X GET http://localhost:3000/notes/8293efa0-457a-11e8-b562-fdcf930649e8
# update-event.json
$ curl -X PUT -H "Content-Type: application/json" -d "{\"content\":\"new world\",\"attachment\":\"new.jpg\"}" http://localhost:3000/notes/8293efa0-457a-11e8-b562-fdcf930649e8
# delete-event.json
$ curl -X DELETE http://localhost:3000/notes/8293efa0-457a-11e8-b562-fdcf930649e8

So there's no any kind of authorization in this local environment.

Am I missing something?

LantosIstvan avatar May 08 '18 18:05 LantosIstvan

Yes, you're right, serverless-offline does not implement any authorization and uses dummies anywhere. So tests relying on proper authorization should be done with a live dynamodb database. However, testing APIs is quite convenient using offline and doing final tests on a deployed development stage.

I wonder, what would I gain [...]

You might have a service that has API triggered functions and functions that are invoked by other functions or via the aws-sdk. Testing the API (and the triggered funtions) is possible with offline. For the other functions you'd need invoke local. What you now gain with executing the function with the compiled code from the running offline service is two things: (1) You save the compile, as offline already compiled it (2) While running offline Webpack works in watch mode, i.e. if you change a file it will recompile in the background and any new request to offline uses the changed code. With invoking on the offline compiled code, you automatically gain this benefit too, because it then also just invokes the recompiled code.

HyperBrain avatar May 08 '18 19:05 HyperBrain

I get the same original exception with serverless-webpack 5.1.5 with the --no-build option (see below).

From looking at the code it's that prepareLocalInvoke.js expects the .webpack/<function> directory to be present (tries to chdir into it), but with --no-build the webpack:compile step is skipped, that directory is not created at all and chdir fails.

Maybe the assumption is that the directory should be present because one ran webpack manually before, but it would probably be nice to have a more specific error message. In my case it would be great if it would ignore this and just continue without chdir, as I have another plugin that hooks in later and takes care of the invoke local preparation (although I might try to avoid the situation altogether).

{ Error: ENOENT: no such file or directory, chdir '/my/project/.webpack/action'
    at process.chdir (internal/process/methods.js:21:12)
    at process.chdir (/my/project/node_modules/graceful-fs/polyfills.js:21:9)
    at ServerlessWebpack.prepareLocalInvoke (/my/project/node_modules/serverless-webpack/lib/prepareLocalInvoke.js:24:13)
    at ServerlessWebpack.tryCatcher (/my/project/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/my/project/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/my/project/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/my/project/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/my/project/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (/my/project/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (/my/project/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/my/project/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:696:18)
    at tryOnImmediate (timers.js:667:5)
    at processImmediate (timers.js:649:5)
    at process.topLevelDomainCallback (domain.js:121:23)
  errno: -2,
  code: 'ENOENT',
  syscall: 'chdir',
  path:
   '/my/project/.webpack/action' }

alexkli avatar Aug 15 '18 05:08 alexkli

Hi @alexkli ,

Maybe the assumption is that the directory should be present because one ran webpack manually before,

Exactly 😄 . The --no-build switch was introduced into the plugin to use it in environments, where you have one compile and then multiple serverless invoke local invocations, e.g. running integration or unit tests. So the correct way when using it is to execute serverless webpack once and then serverless invoke local --no-build multiple times or with any other command that supports the no-build switch.

HyperBrain avatar Aug 24 '18 19:08 HyperBrain

Sure, but a better error would be really helpful rather than letting chdir fail uncontrolled. Check if the directory exists or not, and if not print:

No build found. If using --no-build, you have to run the build manually, e.g. `serverless package`

alexkli avatar Aug 25 '18 01:08 alexkli

I believe I am seeing the same issue. In order to test with serverless-offline I must set individually: false, otherwise I'll see Error: ENOENT: no such file or directory, uv_chdir when I attempt to invoke a function with serverless invoke local -f functionName --no-build.

It's a minor inconvenience, so long as I remember to set individually:true when I am done.

dboune avatar Jan 18 '19 19:01 dboune

What is the status of this issue? I have this problem right now...

codingyourlife avatar Nov 26 '19 14:11 codingyourlife

@HyperBrain regarding: https://github.com/serverless-heaven/serverless-webpack/issues/385#issuecomment-387368856 Can't you just look at the process.argv too see exactly how serverless is running?

drc-gcoakley avatar May 10 '20 13:05 drc-gcoakley