aws-sam-cli
                                
                                 aws-sam-cli copied to clipboard
                                
                                    aws-sam-cli copied to clipboard
                            
                            
                            
                        sam package and sam build refer to different locations for layers
Description: While working with SAM to build a serverless app using both functions and layers locally appears to refer to different locations depending on if I am building or deploying.
It appears that when you do sam build it copies your CodeUri content to a tmp dir and exposes $(ARTIFACTS_DIR). Which is a pointer to $PWD/.aws-sam/build/<logical-resource-id> . However, when you run sam package it bundles from CodeUri
My project has the following structure:
.aws-sam/build/
Lambda/ # my lambda code is staged here
LayerOne/Makefile
LayerOne/requirements.txt
LayerOne/python # all staged modules are located here
Steps to reproduce the issue:
Python version:
$ pipenv run python -VVV
Loading .env environment variables…
Python 3.7.6 (default, Feb 26 2020, 20:54:15) 
[GCC 7.3.1 20180712 (Red Hat 7.3.1-6)]
OS Version:
$ uname -a
Linux swfa 4.19.76-linuxkit aws/serverless-application-model#1 SMP Tue May 26 11:42:35 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release                                                     
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
SAM version:
$ sam version
SAM CLI, version 0.52.0
- Create a layer based on instructions from here
- Use a CodeUriofLayer1with a config similar too: SAM Template:
  LayerOne:
    Type: "AWS::Serverless::LayerVersion"
    Properties:
      LayerName: layer_one
      CompatibleRuntimes:
        - python3.7
      ContentUri: LayerOne/
      Description: Common code for Lambdas
      LicenseInfo: MIT
      RetentionPolicy: Retain
    Metadata:
      BuildMethod: makefile
- Define a Makefile:
requirements.txt:
	pipenv lock -r > ./requirements.txt
build-LayerOne: requirements.txt
	$(info [+] Installing '3rd party' dependencies...)
	pipenv run pip3 install \
			--isolated \
			--disable-pip-version-check \
			-Ur requirements.txt -t $(ARTIFACTS_DIR)/python
	cp -f ./requirements.txt $(ARTIFACTS_DIR)/python/
- Build:
sam build LayerOne
- Package:
	sam package \
		--template-file template.yaml \
		--output-template-file packaged.yaml \
		--s3-bucket ${BUCKET} \
		--s3-prefix ${BUCKET_PREFIX}
- Deploy
	sam deploy \
	  --no-fail-on-empty-changeset \
          --template-file packaged.yaml \
	  --stack-name ${STACK_NAME} \
	  --s3-bucket ${BUCKET} \
	  --s3-prefix stacks \
  	  --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND
Observed result:
When you download the layer, the only files that will be bundled will be requirements.txt because the pip install
targeted the $(ARTIFACTS_DIR) and did not stage to CodeUri/python
Expected result:
The layer should contain the entire contents of $(ARTIFACTS_DIR)
- Revise your MakefileMakefile:
build-LayerOne: configure
	ls -latr > $(ARTIFACTS_DIR)/log 
	pwd >> $(ARTIFACTS_DIR)/log  
	cp -fa ./python $(ARTIFACTS_DIR)/ 
	cp -f ./requirements.txt $(ARTIFACTS_DIR)/python/
requirements.txt:
	pipenv lock -r > ./requirements.txt
configure: ./requirements.txt
	$(info [+] Installing '3rd party' dependencies...)
	pipenv run pip3 install \
			--isolated \
			--disable-pip-version-check \
			-Ur requirements.txt -t ./python
- Re-run steps 3, 4, & 5
Observed result:
When you download the layer, all files that are in CodeUri/python will be visible.
Should I move this issue to the sam-cli repo here?
I think this is a sam-cli issue.
For what it is worth I have experienced this issue using a custom makefile build for golang lambdas.  Same behavior, the binary is placed in the $(ARTIFACTS_DIR) however the sam package step only includes the source for the lambda and the binary is left in the $(ARTIFACTS_DIR).
Ok I ran a test and determined that the sam deploy CLI behavior is different depending on the use of the -t flag.  If you specify a template.yaml filename when invoking sam deploy the CLI packages up the source in the Lambda CodeUri directory instead of the build artifact.  Removing the -t flag from the same command results in the correct behavior.
I created an issue for this specific scenario here: https://github.com/aws/aws-sam-cli/issues/3616
Hi there,
If we order the commands that is been used during a development or deployment lifecycle (sam build -> sam local -> sam package -> sam deploy) the ones after sam build behaves differently, depending on running sam build or not. If you run sam build before, they will load contents of the function under .aws-sam/build/<loigical-id> folder. But if you haven't run sam build before, then it will use the source directories which is defined in the template.yaml file. Second case could be useful if you don't need to build your function at all.
And for the --template parameter, as explained in the other issue, sam deploy will behave different if it is defined: https://github.com/aws/aws-sam-cli/issues/3616
Please let us know if you have more questions or concerns, resolving this issue for now.
⚠️COMMENT VISIBILITY WARNING⚠️
Comments on closed issues are hard for our team to see. If you need more assistance, please either tag a team member or open a new issue that references this one. If you wish to keep having a conversation with other community members under this issue feel free to do so.