Skip to content

sam package and sam build refer to different locations for layers #2419

@ghost

Description

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions