terraform-aws-modules / terraform-aws-lambda

Terraform module, which takes care of a lot of AWS Lambda/serverless tasks (build dependencies, packages, updates, deployments) in countless combinations πŸ‡ΊπŸ‡¦
https://registry.terraform.io/modules/terraform-aws-modules/lambda/aws
Apache License 2.0
886 stars 657 forks source link

local-exec step fails when trying to run 'npm install' on Windows #414

Closed james-mwakichako closed 1 year ago

james-mwakichako commented 1 year ago

Description

Trying to deploy a lambda on Windows and getting the following error:

module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): raise RuntimeError( module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): RuntimeError: Nodejs interpreter version equal to defined lambda runtime (nodejs16.x) should be available in system PATH I have verified that I have node and npm installed .

Screenshot 2023-02-03 at 3 19 08 PM Screenshot 2023-02-03 at 3 22 09 PM

I have ran into the same error on GitBash and CMD. NOT seeing this issue on Mac.

Below are the system specs: Terraform : v1.3.7 Edition Windows 10 Enterprise Version 20H2 Installed on β€Ž09/β€Ž01/β€Ž2022 OS build 19042.2486 Experience Windows Feature Experience Pack 120.2212.4190.0

Versions

Reproduction Code

module "lambdaToDynamo_lambda" {
  source  = "terraform-aws-modules/lambda/aws"
  version = "4.7.1"

  function_name = "testing-lambda"
  handler       = "index.handler"
  runtime       = "nodejs18.x"

  source_path = "../lambda/src/lambdaToDynamo"

  memory_size = 128
  timeout     = 60

  cloudwatch_logs_retention_in_days = 7

  tags = local.common_tags
}

output "lambdaToDynamo_lambda_function_name" {
  value = module.lambdaToDynamo_lambda.lambda_function_name
}

output "lambdaToDynamo_lambda_role_arn" {
  value = module.lambdaToDynamo_lambda.lambda_role_arn
}

provider "aws" {
  region = var.region
}

terraform {

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "4.47.0"
    }
  }
}

locals {
  prefix        = "${var.projectPrefix}-${var.environment}-${var.serviceName}"
  prefix_short  = "${var.projectPrefix}-${var.environment}"
  region_prefix = "${var.projectPrefix}-${var.environment}-${var.region}-${var.serviceName}"
  global_prefix = "${var.projectPrefix}-${var.environment}-${local.region_short}-${var.serviceName}"

  common_tags = {
    Environment = var.environment
  }
}

locals {
  region_short = var.region == "us-east-1" ? "ue1" : "ue2"
}

variable "environment" {
  type    = string
  default = "test"
}

variable "projectPrefix" {
  type = string
  default = "TF-test"
}

variable "region" {
  type    = string
  default = "us-east-1"
}

variable "serviceName" {
  type = string
  default = "TestService"
}

Steps to reproduce the behavior:

terraform init
terraform plan
terraform apply

Expected behavior

Module should run successfully , run npm install against the package.json defined in the same directory as the lambda code and deploy the lambda to AWS.

Actual behavior

Full error message :

module.lambdaToDynamo_lambda.null_resource.archive[0]: Provisioning with 'local-exec'...
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): Executing: ["python.exe" ".terraform/modules/lambdaToDynamo_lambda/package.py" "build" "--timestamp" "1674855599800929000" "./.terraform/test-lambda-builds/835975921e6d253666fa437649970e48ec554ce92fc3951357c6233208daebe8.plan.json"]
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): zip: creating './.terraform/test-lambda-builds/835975921e6d253666fa437649970e48ec554ce92fc3951357c6233208daebe8.zip' archive
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): Installing npm requirements: ../../lambda/src/lambdaToDynamo\package.json
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): > mktemp -d terraform-aws-lambda-XXXXXXXX # 'C:\Users\XXXXXX\AppData\Local\Temp\terraform-aws-lambda-iqttatx9'
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): > cd 'C:\Users\XXXXXX\AppData\Local\Temp\terraform-aws-lambda-iqttatx9'
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): > npm install
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): zip: Error during zip archive creation
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): Traceback (most recent call last):
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1272, in install_npm_requirements
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     check_call(npm_command, env=subproc_env)
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 364, in check_call
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     retcode = call(*popenargs, **kwargs)
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 345, in call
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     with Popen(*popenargs, **kwargs) as p:
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in __init__
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     self._execute_child(args, executable, preexec_fn, close_fds,
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1438, in _execute_child
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): FileNotFoundError: [WinError 2] The system cannot find the file specified

module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): The above exception was the direct cause of the following exception:

module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): Traceback (most recent call last):
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1522, in build_command
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     bpm.execute(build_plan, zs, query)
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 877, in execute
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     with install_npm_requirements(query, npm_requirements, tmp_dir) as rd:
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\contextlib.py", line 135, in __enter__
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     return next(self.gen)
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1274, in install_npm_requirements
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     raise RuntimeError(
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): RuntimeError: Nodejs interpreter version equal to defined lambda runtime (nodejs16.x) should be available in system PATH
β•·
β”‚ Error: local-exec provisioner error
β”‚
β”‚   with module.lambdaToDynamo_lambda.null_resource.archive[0],
β”‚   on .terraform\modules\lambdaToDynamo_lambda\package.tf line 67, in resource "null_resource" "archive":
β”‚   67:   provisioner "local-exec" {
β”‚
β”‚ Error running command
β”‚ './.terraform/test-lambda-builds/835975921e6d253666fa437649970e48ec554ce92fc3951357c6233208daebe8.plan.json':
β”‚ exit status 1. Output: zip: creating
β”‚ './.terraform/test-lambda-builds/835975921e6d253666fa437649970e48ec554ce92fc3951357c6233208daebe8.zip'
β”‚ archive
β”‚ Installing npm requirements: ../../lambda/src/lambdaToDynamo\package.json
β”‚ > mktemp -d terraform-aws-lambda-XXXXXXXX #
β”‚ 'C:\Users\XXXXXX\AppData\Local\Temp\terraform-aws-lambda-iqttatx9'
β”‚ > cd 'C:\Users\XXXXXX\AppData\Local\Temp\terraform-aws-lambda-iqttatx9'
β”‚ > npm install
β”‚ zip: Error during zip archive creation
β”‚ Traceback (most recent call last):
β”‚   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1272, in install_npm_requirements
β”‚     check_call(npm_command, env=subproc_env)
β”‚   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 364, in check_call
β”‚     retcode = call(*popenargs, **kwargs)
β”‚   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 345, in call
β”‚     with Popen(*popenargs, **kwargs) as p:
β”‚   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in __init__
β”‚     self._execute_child(args, executable, preexec_fn, close_fds,
β”‚   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1438, in _execute_child
β”‚     hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
β”‚ FileNotFoundError: [WinError 2] The system cannot find the file specified
β”‚
β”‚ The above exception was the direct cause of the following exception:
β”‚
β”‚ Traceback (most recent call last):
β”‚   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1522, in build_command
β”‚     bpm.execute(build_plan, zs, query)
β”‚   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 877, in execute
β”‚     with install_npm_requirements(query, npm_requirements, tmp_dir) as rd:
β”‚   File "C:\Users\XXXXXX\AppData\Local\Programs\Python\Python310\lib\contextlib.py", line 135, in __enter__
β”‚     return next(self.gen)
β”‚   File "C:\Users\XXXXXX\XXXXXX\XXXXXX\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1274, in install_npm_requirements
β”‚     raise RuntimeError(
β”‚ RuntimeError: Nodejs interpreter version equal to defined lambda runtime
β”‚ (nodejs16.x) should be available in system PATH

Additional context

I have found two work arounds by updating package.py :

  1. Set shell=True in check_call within package.py. This comes with it’s own security considerations
  2. change "npm" "install" to "npm.cmd" "install" in the case the OS is Windows.

The lambdaToDynamo dir contains two files :

james-mwakichako commented 1 year ago

Additional Context:

I also went ahead and used commands option and got the following error in Windows .

module.lambdaToDynamo_lambda.local_file.archive_plan[0]: Creation complete after 0s [id=592971c7c21735af995af3dffbde97e352aae917]
module.lambdaToDynamo_lambda.null_resource.archive[0]: Creating...
module.lambdaToDynamo_lambda.null_resource.archive[0]: Provisioning with 'local-exec'...
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): Executing: ["python.exe" ".terraform/modules/lambdaToDynamo_lambda/package.py" "build" "--timestamp" "1675955070336843000" "./.terraform/test-app-ue1-lambda-builds/0b4f89a1c7e5af849c5d3a686943d420e47ef076ee13fd81af3279c678716fdf.plan.json"]
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): zip: creating './.terraform/test-app-ue1-lambda-builds/0b4f89a1c7e5af849c5d3a686943d420e47ef076ee13fd81af3279c678716fdf.zip' archive
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): zip: Error during zip archive creation
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): Traceback (most recent call last):
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXXX\test\sampleService\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1520, in build_command
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     bpm.execute(build_plan, zs, query)
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXXX\test\sampleService\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 891, in execute
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     p = subprocess.Popen(script, shell=True, cwd=path,
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in __init__
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     self._execute_child(args, executable, preexec_fn, close_fds,
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):   File "C:\Users\XXXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1364, in _execute_child
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec):     assert not pass_fds, "pass_fds not supported on Windows."
module.lambdaToDynamo_lambda.null_resource.archive[0] (local-exec): AssertionError: pass_fds not supported on Windows.
β•·
β”‚ Error: local-exec provisioner error
β”‚
β”‚   with module.lambdaToDynamo_lambda.null_resource.archive[0],
β”‚   on .terraform\modules\lambdaToDynamo_lambda\package.tf line 67, in resource "null_resource" "archive":
β”‚   67:   provisioner "local-exec" {
β”‚
β”‚ Error running command
β”‚ './.terraform/test-app-ue1-lambda-builds/0b4f89a1c7e5af849c5d3a686943d420e47ef076ee13fd81af3279c678716fdf.plan.json':
β”‚ exit status 1. Output: zip: creating
β”‚ './.terraform/test-app-ue1-lambda-builds/0b4f89a1c7e5af849c5d3a686943d420e47ef076ee13fd81af3279c678716fdf.zip'
β”‚ archive
β”‚ zip: Error during zip archive creation
β”‚ Traceback (most recent call last):
β”‚   File "C:\Users\XXXXXXX\test\sampleService\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 1520, in build_command
β”‚     bpm.execute(build_plan, zs, query)
β”‚   File "C:\Users\XXXXXXX\test\sampleService\infrastructure\regional\.terraform\modules\lambdaToDynamo_lambda\package.py", line 891, in execute
β”‚     p = subprocess.Popen(script, shell=True, cwd=path,
β”‚   File "C:\Users\XXXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 969, in __init__
β”‚     self._execute_child(args, executable, preexec_fn, close_fds,
β”‚   File "C:\Users\XXXXXXX\AppData\Local\Programs\Python\Python310\lib\subprocess.py", line 1364, in _execute_child
β”‚     assert not pass_fds, "pass_fds not supported on Windows."
β”‚ AssertionError: pass_fds not supported on Windows.

Terraform code

module "lambdaToDynamo_lambda" {

  source  = "terraform-aws-modules/lambda/aws"
  version = "4.7.1"

  function_name = "${local.prefix}-lambdaToDynamo"
  description   = "Sample service lambda"
  handler       = "index.handler"
  runtime       = "nodejs18.x"

  source_path = [
    {
    path     = "../../lambda/src/lambdaToDynamo",
    commands = [
      "npm.cmd install",
      ":zip"
    ],
    patterns = [
      "node_modules/.+", # Include all node_modules
    ],
  }
  ]

  memory_size = var.memory_size
  timeout     = var.timeout_in_seconds

  cloudwatch_logs_retention_in_days = var.cw_log_retention_in_days

  environment_variables = {
    "SampleTable_Name" = data.aws_dynamodb_table.demoTable.id
  }

  tags = local.common_tags
}

locals {
  account_resource_prefix        = "${var.projectPrefix}-${var.accountProfile}"
  prefix                         = "${var.projectPrefix}-${var.app_name}-${var.environment}"
  region_short                   = var.region == "us-east-1" ? "ue1" : "ue2"
  region_prefix                  = "${var.projectPrefix}-${var.app_name}-${var.environment}-${local.region_short}"
  account_resource_region_prefix = "${var.projectPrefix}-${var.accountProfile}-${local.region_short}"
  lambda_role_arn                = "arn:aws:iam::${var.allowedAccountIds[0]}:role/${local.region_prefix}-lambdaRole"

  common_tags = {
    environment   = var.environment
  }
}

I tried running this on Mac and the lambda was deployed successfully .

james-mwakichako commented 1 year ago

More updates on this. We got around this on Windows by using WSL . Thanks to @jwicks

antonbabenko commented 1 year ago

Exactly, this is the solution all Windows users I know were using.

I am closing this issue.

james-mwakichako commented 1 year ago

@antonbabenko , could that be added in the documentation ?

antonbabenko commented 1 year ago

@james-mwakichako Sure, please open a PR with the updated README file. Highly appreciated!

github-actions[bot] commented 1 year ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.