Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@aws-cdk/aws-lambda-python-alpha: PIP_INDEX_URL in buildArgs is not applied #26920

Open
satoxiw opened this issue Aug 29, 2023 · 2 comments
Open
Labels
@aws-cdk/aws-lambda Related to AWS Lambda @aws-cdk/aws-lambda-python bug This issue is a bug. p2

Comments

@satoxiw
Copy link

satoxiw commented Aug 29, 2023

Describe the bug

Even if PIP_INDEX_URL is specified in buildArgs, this is not valid when applying requirements.txt. The reason is that the PIP_INDEX_URL specified in the Dockerfile is only specified in the ARG, so this environment variable is no longer valid when pip install -r requirements.txt is executed (when the container is run).

This problem can be solved by specifying PIP_INDEX_URL in the environment in addition to buildArgs, but this method is redundant.

    const pipIndexUrl = spawnSync("pip", ["config", "get", "global.index-url"]).stdout.toString().trim();
    const bundling = pipIndexUrl == "" ? undefined : {
            buildArgs: { PIP_INDEX_URL: pipIndexUrl },
            environment: { PIP_INDEX_URL: pipIndexUrl },
          };

    const lambdaLayer = new PythonLayerVersion(this, "LambdaLayer", {
      layerVersionName: "SomethingLayer",
      entry: "/lambda/layer",
      compatibleRuntimes: [lambda.Runtime.PYTHON_3_9],
      bundling,
    });

Adding similar values such as PIP_EXTRA_INDEX_URL, HTTPS_PROXY and POETRY_VERSION further accentuates the redundancy.

Another possible method is to put --index-url in the requirements.txt file, but this is not desirable because it is necessary to change the description in the file each time the environment is known.

Expected Behavior

The specification of buildArgs must also affect the installation of libraries in the requirements.txt file.

Current Behavior

In an environment where PIP_INDEX_URL needs to be changed, if I only change PIP_INDEX_URL in buildArgs, CDK execution will stop without access to the pypi.org site for installation of the libraries defined in requirements.txt.
Specifically, pypi.org connection timeouts and attempts are repeated.

Step 11/11 : CMD [ "python" ]
 ---> Running in 6792f94ec7f7
Removing intermediate container 6792f94ec7f7
 ---> da1c164310a2
Successfully built da1c164310a2
Successfully tagged cdk-025e0dd8bb67991ff31bd34edeaca2bd4c2201094770be7454fdbf71d6e13bf4:latest
Bundling asset MyStack/LambdaLayer/Code/Stage...
sending incremental file list
created directory /asset-output/python
./
requirements.txt

sent 120 bytes  received 81 bytes  402.00 bytes/sec
total size is 13  speedup is 0.06
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.urllib3.connection.HTTPSConnection object at 0x7f36964da280>, 'Connection to pypi.org timed out. (connect timeout=15)')': /simple/pillow/
WARNING: Retrying (Retry(total=3, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.urllib3.connection.HTTPSConnection object at 0x7f36964da880>, 'Connection to pypi.org timed out. (connect timeout=15)')': /simple/pillow/

Reproduction Steps

  1. Prepare a closed environment that cannot access pypi.org directly (ex. an EC2 instance in a private subnet with no Internet gateway)
  2. Prepare a separate Python package index other than pipy.org (ex. CodeArtifact)
  3. Prepare a Lambda (Python) function with requirements.txt containing optional libraries
  4. Run the following CDK stack in a closed environment (A separately prepared package index should be accessible)
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import {
  BundlingOptions,
  PythonFunction,
  PythonLayerVersion,
} from "@aws-cdk/aws-lambda-python-alpha";
import { spawnSync } from "child_process";

export class MyLambdaStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const pipIndexUrl = spawnSync("pip", ["config", "get", "global.index-url"])
      .stdout.toString()
      .trim();
    const bundling: BundlingOptions | undefined =
      pipIndexUrl != ""
        ? { buildArgs: { PIP_INDEX_URL: pipIndexUrl } }
        : undefined;

    const lambdaFunction = new PythonFunction(this, "function", {
      entry: "/path/to/function",
      runtime: lambda.Runtime.PYTHON_3_9,
      bundling,
    });
  }
}

Possible Solution

Several proposals exist to correct this problem.

  1. Modify the Dockerfile that aws-lambda-python-alpha has
# The correct AWS SAM build image based on the runtime of the function will be
# passed as build arg. The default allows to do `docker build .` when testing.
ARG IMAGE=public.ecr.aws/sam/build-python3.7
FROM $IMAGE

ARG PIP_INDEX_URL
ARG PIP_EXTRA_INDEX_URL
ARG HTTPS_PROXY
ARG POETRY_VERSION=1.5.1

to

# The correct AWS SAM build image based on the runtime of the function will be
# passed as build arg. The default allows to do `docker build .` when testing.
ARG IMAGE=public.ecr.aws/sam/build-python3.7
FROM $IMAGE

ARG PIP_INDEX_URL
ENV PIP_INDEX_URL=$PIP_INDEX_URL
ARG PIP_EXTRA_INDEX_URL
ENV PIP_EXTRA_INDEX_URL=$PIP_EXTRA_INDEX_URL
ARG HTTPS_PROXY
ENV HTTPS_PROXY=$HTTPS_PROXY
ARG POETRY_VERSION=1.5.1
ENV POETRY_VERSION=$POETRY_VERSION
  1. In terms of preventing redundant code, one possible approach would be to use only the environment without buildArgs. In that case, you need to modify the DockerImage fromBuild to use environment.
    https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk-lib/core/lib/bundling.ts#L354-L363

  2. Allow passing environment variables to bundlingCommand. Add PIP_INDEX_URL to the environment variable at the point where the command is generated.
    https://github.com/aws/aws-cdk/blob/main/packages/%40aws-cdk/aws-lambda-python-alpha/lib/bundling.ts#L119-L134

Additional Information/Context

No response

CDK CLI Version

2.92.0

Framework Version

No response

Node.js Version

16.20.2

OS

Linux

Language

Typescript

Language Version

TypeScript (3.7.5)

Other information

No response

@satoxiw satoxiw added bug This issue is a bug. needs-triage This issue or PR still needs to be triaged. labels Aug 29, 2023
@indrora indrora added p2 @aws-cdk/aws-lambda Related to AWS Lambda dependencies This issue is a problem in a dependency or a pull request that updates a dependency file. and removed needs-triage This issue or PR still needs to be triaged. dependencies This issue is a problem in a dependency or a pull request that updates a dependency file. labels Aug 29, 2023
@indrora
Copy link
Contributor

indrora commented Aug 29, 2023

Hmm... Another day another Docker quirk.

it does look like ARG is the wrong instruction here and that ENV should be the instruction used, at least according to the documentation in the reference.

edit: @rix0rrr was the last one to touch it, I nominate him to look at it.

@sercantor
Copy link

another affect of putting this in environment instead of build args is that it re-calculates the hash differently for me, idk why this is the case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
@aws-cdk/aws-lambda Related to AWS Lambda @aws-cdk/aws-lambda-python bug This issue is a bug. p2
Projects
None yet
Development

No branches or pull requests

3 participants