aws-sam-cli icon indicating copy to clipboard operation
aws-sam-cli copied to clipboard

sam package and sam build refer to different locations for layers

Open ghost opened this issue 5 years ago • 3 comments

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
  1. Create a layer based on instructions from here
  2. Use a CodeUri of Layer1 with 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
  1. 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/
  1. Build:
sam build LayerOne
  1. Package:
	sam package \
		--template-file template.yaml \
		--output-template-file packaged.yaml \
		--s3-bucket ${BUCKET} \
		--s3-prefix ${BUCKET_PREFIX}
  1. 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)

  1. Revise your Makefile Makefile:
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
  1. Re-run steps 3, 4, & 5

Observed result: When you download the layer, all files that are in CodeUri/python will be visible.

ghost avatar Jul 16 '20 17:07 ghost

Should I move this issue to the sam-cli repo here?

ghost avatar Jul 22 '20 05:07 ghost

I think this is a sam-cli issue.

timoschilling avatar Jul 28 '20 10:07 timoschilling

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

dsandor avatar Feb 02 '22 13:02 dsandor

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.

mndeveci avatar Jan 10 '23 20:01 mndeveci

⚠️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.

github-actions[bot] avatar Jan 10 '23 20:01 github-actions[bot]