awsdocs/aws-sam-developer-guide

Docs for "sam local" don't work with Go

mousedownmike opened this issue · 7 comments

Description:

The sam local commands do not work as documented in the AWS Serverless Application Model Developer Guide. They require an additional call to sam build before they will work.

Steps to reproduce:

Assume a simple project structure such as:

simple-go/
├── cmd
│   └── my-func
│       └── main.go
├── go.mod
├── samconfig.toml
└── template.yaml

With a template.yaml of:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: 'Simple Go SAM'
Resources:
  ExampleRoot:
    Type: 'AWS::Serverless::Function'
    Properties:
      CodeUri: './cmd/my-func/'
      Handler: 'my-func'
      Runtime: 'go1.x'
      Events:
        Get:
          Type: 'Api'
          Properties:
            Path: '/'
            Method: 'get'

The documentation indicates the following commands should work from within the simple-go directory:

  • sam local invoke
  • sam local start-api

Observed result:

Running sam local invoke gets you:

$ sam local invoke --debug
2020-11-13 20:11:23,487 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics
2020-11-13 20:11:23,542 | local invoke command is called
2020-11-13 20:11:23,544 | No Parameters detected in the template
2020-11-13 20:11:23,561 | 2 resources found in the template
2020-11-13 20:11:23,561 | Found Serverless function with name='ExampleRoot' and CodeUri='./cmd/my-func/'
2020-11-13 20:11:23,564 | Found one Lambda function with name 'ExampleRoot'
2020-11-13 20:11:23,564 | Invoking my-func (go1.x)
2020-11-13 20:11:23,564 | No environment variables found for function 'ExampleRoot'
2020-11-13 20:11:23,564 | Environment variables overrides data is standard format
2020-11-13 20:11:23,564 | Loading AWS credentials from session with profile 'None'
2020-11-13 20:11:23,572 | Resolving code path. Cwd=/projects/simple-go, CodeUri=./cmd/my-func/
2020-11-13 20:11:23,572 | Resolved absolute path to code is /projects/simple-go/cmd/my-func
2020-11-13 20:11:23,572 | Code /projects/simple-go/cmd/my-func is not a zip/jar file
2020-11-13 20:11:23,575 | Skip pulling image and use local one: amazon/aws-sam-cli-emulation-image-go1.x:rapid-1.7.0.

2020-11-13 20:11:23,575 | Mounting /projects/simple-go/cmd/my-func as /var/task:ro,delegated inside runtime container
2020-11-13 20:11:23,885 | Starting a timer for 3 seconds for function 'ExampleRoot'
START RequestId: 6961a864-2a06-1dca-b722-c2635e27a299 Version: $LATEST
fork/exec /var/task/my-func: no such file or directory: PathError
fork/exec /var/task/my-func: no such file or directory: PathError
null
END RequestId: 6961a864-2a06-1dca-b722-c2635e27a299
REPORT RequestId: 6961a864-2a06-1dca-b722-c2635e27a299  Init Duration: 57.70 ms Duration: 1.44 ms       Billed Duration: 100 ms Memory Size: 128 MB     Max Memory Used: 16 MB
2020-11-13 20:11:24,184 | Sending Telemetry: {'metrics': [{'commandRun': {'awsProfileProvided': False, 'debugFlagProvided': True, 'region': '', 'commandName': 'sam local invoke', 'duration': 696, 'exitReason': 'success', 'exitCode': 0, 'requestId': '78d50567-a61f-42e3-9fa4-b3d0a2e30179', 'installationId': '72eb7872-74c2-473d-b9e1-6ea1da5e4588', 'sessionId': '7084671a-89d6-4499-b213-bd5cf632c207', 'executionEnvironment': 'CLI', 'pyversion': '3.8.5', 'samcliVersion': '1.7.0'}}]}
2020-11-13 20:11:24,530 | HTTPSConnectionPool(host='aws-serverless-tools-telemetry.us-west-2.amazonaws.com', port=443): Read timed out. (read timeout=0.1)

{"errorType":"PathError","errorMessage":"fork/exec /var/task/my-func: no such file or directory"}

sam local start-api starts the API but fails with almost the same error once a request is made.

Expected result:

my-func should be built and executed or the documentation should be updated to indicate an additional step is necessary.

Working result:

Running sam build followed by sam local invoke does work:

$ sam build                                          
Building codeuri: ./cmd/my-func/ runtime: go1.x metadata: {} functions: ['ExampleRoot']  
Running GoModulesBuilder:Build                                                           
                                            
Build Succeeded                                                                          
                                                                                         
Built Artifacts  : .aws-sam/build                                                        
Built Template   : .aws-sam/build/template.yaml                                          
                                                                                         
Commands you can use next                                                                                                                                                         
=========================                                                                                                                                                         
[*] Invoke Function: sam local invoke                                                    
[*] Deploy: sam deploy --guided                                                                                                                                                   
                                                                                                                                                                                  
$ sam local invoke --debug                                                                                                                    
2020-11-13 20:23:37,364 | Telemetry endpoint configured to be https://aws-serverless-tools-telemetry.us-west-2.amazonaws.com/metrics                                              
2020-11-13 20:23:37,415 | local invoke command is called                                                                                                                          
2020-11-13 20:23:37,416 | No Parameters detected in the template                                                                                                                  
2020-11-13 20:23:37,432 | 2 resources found in the template                                                                                                                       
2020-11-13 20:23:37,432 | Found Serverless function with name='ExampleRoot' and CodeUri='ExampleRoot'                                                                             
2020-11-13 20:23:37,434 | Found one Lambda function with name 'ExampleRoot'                                                                                                       
2020-11-13 20:23:37,434 | Invoking my-func (go1.x)                                                                                                                                
2020-11-13 20:23:37,434 | No environment variables found for function 'ExampleRoot'                                                                                               
2020-11-13 20:23:37,434 | Environment variables overrides data is standard format                                                                                                 
2020-11-13 20:23:37,434 | Loading AWS credentials from session with profile 'None'                                                                                                
2020-11-13 20:23:37,443 | Resolving code path. Cwd=/projects/simple-go/.aws-sam/build, CodeUri=ExampleRoot                                                                        
2020-11-13 20:23:37,443 | Resolved absolute path to code is /projects/simple-go/.aws-sam/build/ExampleRoot           
2020-11-13 20:23:37,443 | Code /projects/simple-go/.aws-sam/build/ExampleRoot is not a zip/jar file                                                                               
2020-11-13 20:23:37,447 | Skip pulling image and use local one: amazon/aws-sam-cli-emulation-image-go1.x:rapid-1.7.0.                                                             
                                                                                                                                                                                  2020-11-13 20:23:37,447 | Mounting /projects/simple-go/.aws-sam/build/ExampleRoot as /var/task:ro,delegated inside runtime container                                              2020-11-13 20:23:37,755 | Starting a timer for 3 seconds for function 'ExampleRoot'                                                                                               
2020/11/14 04:23:37 Simple Function                                                                                                                                               
2020/11/14 04:23:37 <nil>                                                                                                                                                         
2020-11-13 20:23:40,756 | Function 'ExampleRoot' timed out after 3 seconds                                                                                                        
2020-11-13 20:23:41,122 | Sending Telemetry: {'metrics': [{'commandRun': {'awsProfileProvided': False, 'debugFlagProvided': True, 'region': '', 'commandName': 'sam local invoke',
 'duration': 3755, 'exitReason': 'success', 'exitCode': 0, 'requestId': 'cef4037b-9689-4610-876c-93413bc413bb', 'installationId': '72eb7872-74c2-473d-b9e1-6ea1da5e4588', 'session
Id': '547dafa5-7733-42bc-96d1-1ebe099d469b', 'executionEnvironment': 'CLI', 'pyversion': '3.8.5', 'samcliVersion': '1.7.0'}}]}                                                    
2020-11-13 20:23:41,437 | Telemetry response: 200  

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

$ go version
go version go1.15.4 linux/amd64
$ sam --version
SAM CLI, version 1.7.0
$ cat /etc/issue
Ubuntu 20.04.1 LTS \n \l

Maybe there should be additional instructions for non-interpreted languages?

Originally from: aws/aws-sam-cli#2377

Having the same issue.. @mousedownmike Did you find any solution?

@felipeap92 you just need to string the two commands together (assuming *nix type environment). The following builds MyFunc using my-func-template.yaml and invokes it with a test SQS Event.

sam build -t my-func-template.yaml && sam local invoke MyFunc --event test/events/my-sqs-event.json

I'm trying to execute the Hello World example from AWS SAM Docs and I'm having this issue:

❯ sam build -t template.yaml
Building codeuri: /home/felipe/src/sam-app/hello-world runtime: go1.x metadata: {} functions: ['HelloWorldFunction']
Running GoModulesBuilder:Build

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided
❯ sam local invoke HelloWorldFunction
Invoking hello-world (go1.x)
Skip pulling image and use local one: amazon/aws-sam-cli-emulation-image-go1.x:rapid-1.24.1.

Mounting /home/felipe/src/sam-app/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: 21b41065-186d-4ce2-b8bf-a9680bfff341 Version: $LATEST
fork/exec /var/task/hello-world: no such file or directory: PathError
null
END RequestId: 21b41065-186d-4ce2-b8bf-a9680bfff341
REPORT RequestId: 21b41065-186d-4ce2-b8bf-a9680bfff341  Init Duration: 3.24 ms  Duration: 108.63 ms     Billed Duration: 200 ms Memory Size: 128 MB     Max Memory Used: 128 MB
{"errorMessage":"fork/exec /var/task/hello-world: no such file or directory","errorType":"PathError"}

Do you know how to solve it?

ps: I'm on Windows using WSL2 (Ubuntu 20.04.1 LTS)

@felipeap92 it looks like the value of the your CodeUri is probably not correct for wherever you're running the commands. If you look at my initial bug report, you'll see a project layout that works. I'm not that familiar with WSL but I imagine it will work if you figure out the correct value for CodeUri. Good luck!

Does it work with start-api? I haven't tested local invoke but even after sam build sam local start-api doesn't seem to work

I'm not sure if this is related, but I had problems with the example Go hello-world app and found what seemed to be my main problem was that the Go app needed building with a CGO_ENABLED=0 parameter.

Unfortunately, I'm not sure how to alter the existing pipeline to make that work, so I ended up converting my app to use the provided.al2 runtime instead of the go.1x one:

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: bootstrap/
      Handler: bootstrap
      Runtime: provided.al2
      Architectures:
        - x86_64
      Events:
        CatchAll:
          Type: Api
          Properties:
            Path: /hello
            Method: GET
      Environment:
        Variables:
          PARAM1: VALUE
    Metadata:
      BuildMethod: makefile

I edited my go.mod so the module name was also set to 'bootstrap' and finally created a Makefile inside the bootstrap/ folder (or where my CodeUri would point to) which let me add the custom build command:

build-HelloWorldFunction:
	CGO_ENABLED=0 go build .
	cp ./bootstrap $(ARTIFACTS_DIR)

After that, I could run the same sam build / sam local start-api / sam deploy workflow that I'm used to

edit: to clarify, I'm building my apps using WSL2 on Win 10, Ubuntu 20.04 distribution, which may be why I needed the CGO_ENABLED statement.

Closing this issue or pull request in advance of archiving this repo. For more information about the decision to archive this repo (and others in the "awsdocs" org), see the announcement on the AWS News Blog.