5

In serverless i have the following directory structure for my functions:

serverless.yml
functions -
    stories -
        create.js
        get.js

my serverless.yml then looks like this:

functions:
  stories:
    create:
      handler: functions/stories/create.main
      events:
        - http:
          path: stories/create
          method: post
          cors: true
          authorizer: aws_iam
    get:
      handler: functions/stories/get.main
      events:
        - http:
          path: stories/{id}
          method: get
          cors: true
          authorizer: aws_iam

however when i run a test to check the create: serverless invoke local --function create --path mocks/create-event.json i get the following error:

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

  Function "create" doesn't exist in this Service

I managed to get one function working that looks like this:

functions:
  stories:
    handler: functions/stories/create.main
    events:
      - http:
        path: stories/create
        method: post
        cors: true
        authorizer: aws_iam

Since i added the get function, i decided i needed to add the create and get parts after stories, but no matter how i change the handler the functions never seem to exist.

I've tried changing the path to functions/stories/create/create.main with no difference, is there anything obvious i'm missing to allow multiple handlers within the same location?

I was looking at the following example, which uses one folder of "todos" which contains multiple functions, but i can't see any obvious difference between it and mine, except i've added an extra folder.

gardni
  • 1,384
  • 2
  • 24
  • 51

2 Answers2

10

Your template is invalid. You can't just put your function under an arbitrary node to tell the framework that it applies to some object of your app. Your stories: node should be a comment.

Try something like this:

functions:
    # Stories related functions
    createStory:
      handler: functions/stories/create.main
      events:
        - http:
            path: stories   # You can post directly to stories to be more RESTful
            method: post
            cors: true
            authorizer: aws_iam
    getStory:
      handler: functions/stories/get.main
      events:
        - http:
            path: stories/{id}
            method: get
            cors: true
            authorizer: aws_iam

     # More examples to understand the routing
    getAllStories:
      handler: functions/stories/getAll.main # Returns a list of all stories
      events:
        - http:
            path: stories
            method: get
            cors: true
            authorizer: aws_iam
    deleteStory:
      handler: functions/stories/delete.main # Deletes a story
      events:
        - http:
            path: stories/{id}
            method: delete
            cors: true
            authorizer: aws_iam
Quentin Hayot
  • 7,786
  • 6
  • 45
  • 62
  • so are you saying that the serverless.yml always has to be in the format of parent functions node followed by the unique function name regardless of my folder structure for my functions? – gardni Jun 29 '18 at 16:44
  • 3
    Yes, that's correct. Another way of doing it is split your solution up into services, basically having a separate serverless.yml in the sub folders. This is necessary when your solution grows in complexity. Also reduces the size of the payload for each Lambda function. – Matt D Jun 29 '18 at 16:54
8

Took so much time on this! Just figured out that when I typed the command below, I mentioned the function name in the handle.js file which is wrong! I should call the handler name itself that exists in the serverless.yml file instead

For example This was wrong:

enter image description here

sls invoke local --function testFunction

This is right:

enter image description here

sls invoke local --function test
Amr
  • 433
  • 5
  • 12