serverless / serverless

⚡ Serverless Framework – Use AWS Lambda and other managed cloud services to build apps that auto-scale, cost nothing when idle, and boast radically low maintenance.
https://serverless.com
MIT License
46.32k stars 5.69k forks source link

S3 existing bucket additional lambda nodejs runtime is deprecated by AWS #11337

Open ethan-fitsense opened 1 year ago

ethan-fitsense commented 1 year ago

Is there an existing issue for this?

Use case description

Based on the doc: https://www.serverless.com/framework/docs/providers/aws/events/s3#using-existing-buckets, when using existing S3 bucket, an additional lambda will be created. However its runtime is Nodejs 12, and cannot be specified. AWS has deprecated nodejs 12 runtime, so it's going to be a problem.

Proposed solution (optional)

No response

icholy commented 1 year ago

Duplicate https://github.com/serverless/serverless/issues/11400

mokamoto12 commented 1 year ago

We are using v1 and have addressed this issue by adding the following Service local plugin. Fortunately, the lambda source code seems to work on node14.x. In any case, it looks like we should update to v3...

path: .serverless_plugins/lambda-update-deprecated-runtime/index.js

'use strict';

class LambdaUpdateDeprecatedRuntime {

  constructor(serverless, options) {
    this.serverless = serverless;
    this.options = options;
    this.provider = 'aws';

    this.hooks = {
      'after:deploy:compileEvents': this.afterCompileEvents.bind(this),
    };
  }

  afterCompileEvents() {
    let key = 'CustomDashresourceDashexistingDashs3LambdaFunction'
    let resources = this.serverless.service.provider.compiledCloudFormationTemplate.Resources;
    if (key in resources && resources[key].Properties.Runtime == 'nodejs12.x') {
      this.serverless.cli.log("Fixed CustomDashresourceDashexistingDashs3LambdaFunction runtime from `nodejs12.x` to `nodejs14.x`");
      resources[key].Properties.Runtime = 'nodejs14.x'
    }
  }
}

module.exports = LambdaUpdateDeprecatedRuntime;
tharivignesh commented 12 months ago

Hi @all

Is there an option to control the node version of the lambda created using the node version we specify in the serverless?

danmana commented 11 months ago

Is there an option to control the node version of the lambda created using the node version we specify in the serverless?

The LambdaUpdateDeprecatedRuntime service plugin by mokamoto12 does exactly this, and it fixed the issues for me.

Just copy paste it in your project source code and reference it from serverless.yml file

plugins:
  - ./.serverless_plugins/lambda-update-deprecated-runtime.js
LaszloDev commented 8 months ago

Thanks a lot @mokamoto12!

We are using v1 and have addressed this issue by adding the following Service local plugin. Fortunately, the lambda source code seems to work on node14.x. In any case, it looks like we should update to v3...

path: .serverless_plugins/lambda-update-deprecated-runtime/index.js

For everyone who still runs into issues with autogenerated Lambdas being v12, the following modification will change any 'node v12' lambda automatically to v14 (or v16)

'use strict'

class LambdaUpdateDeprecatedRuntime {
  constructor(serverless, options) {
    this.serverless = serverless
    this.options = options
    this.provider = 'aws'

    this.hooks = {
      'after:deploy:compileEvents': this.afterCompileEvents.bind(this),
    }
  }

  afterCompileEvents() {
    let resources = this.serverless.service.provider
      .compiledCloudFormationTemplate.Resources

    Object.keys(resources).forEach((resourceKey) => {
      if (resources[resourceKey].Properties.Runtime == 'nodejs12.x') {
        resources[resourceKey].Properties.Runtime = 'nodejs14.x' // or: 'nodejs16.x'
      }
    })
  }
}

module.exports = LambdaUpdateDeprecatedRuntime
bitsofinfo commented 7 months ago

@mokamoto12 @LaszloDev any chance you can publish that plugin officially?

LaszloDev commented 7 months ago

@mokamoto12 @LaszloDev any chance you can publish that plugin officially?

Do you need help installing/using it? I'm not sure if it makes sense to publish it. You can reach out for help to me on X @laszloschuerg

MarcEspiard commented 7 months ago

@LaszloDev Hi, any chance you'd know how to make this work for Serverless v3 please? I've been trying to get it to work but no luck so far

snabela commented 7 months ago

nodejs16.x is nearing end of support on Lambda. The same issue happens when setting the runtime to nodejs20.x: in that case the "custom-resource-existing-s3" function will still use nodejs16.x.

tom2strobl commented 6 months ago

what @snabela wrote. From the email from AWS: We are ending support for Node.js 16 in Lambda on June 12, 2024. We recommend that you upgrade your existing Node.js 16 functions to Node.js 20 before June 12, 2024.

We're using 18.x right now, so it seems like it's just hardcoded to v16? Why does the S3 shizzle use a different node version than the provider: runtime: nodejs18.x setting in the first place?

noumanbhatti commented 5 months ago

I've to update my lambda to node v20 as I've update aws sdk from v2 to v3 I've added the file as indicated by @laszloschuerg and added the plugin but for me during deployment cloud formation is failing with exception.

changes in serverless.yml

plugins:
  - serverless-domain-manager
  - serverless-plugin-aws-alerts
  - serverless-step-functions
  - serverless-kms-grants
  - ./serverless-plugins/lambda-update-deprecated-runtime.js
  - serverless-newrelic-lambda-layers

exception is

Error:
CREATE_FAILED: CustomDashresourceDashexistingDashs3LambdaFunction (AWS::Lambda::Function)
Resource handler returned message: "The runtime parameter of nodejs14.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs20.x) while creating or updating functions. (Service: Lambda, Status Code: 400, Request ID: 793e3941-3991-479b-aa7b-41c81dfa24f9)" (RequestToken: 806c4a93-b669-b4be-e5ce-e8cc14fad21b, HandlerErrorCode: InvalidRequest)

I urgently need this lambda to use node20.x

mokamoto12 commented 5 months ago

@noumanbhatti I happened to see a comment, but are you still having trouble? Perhaps modifying the following line in ./serverless-plugins/lambda-update-deprecated-runtime.js:

resources[key].Properties.Runtime = 'nodejs14.x'

to:

resources[key].Properties.Runtime = 'nodejs20.x'

work properly?

Sunac commented 4 months ago

@noumanbhatti I happened to see a comment, but are you still having trouble? Perhaps modifying the following line in ./serverless-plugins/lambda-update-deprecated-runtime.js:

resources[key].Properties.Runtime = 'nodejs14.x'

to:

resources[key].Properties.Runtime = 'nodejs20.x'

work properly?

In my case I also used similar approach that worked for me without any issue (I updated to node20 from node16 simply overriding in Resources runtime value for this function (as it was already existing and previously created by sls) # override sls managed custom existingS3lambda runtime CustomDashresourceDashexistingDashs3LambdaFunction: Type: AWS::Lambda::Function Properties: Runtime: 'nodejs20.x'

martinash78 commented 3 months ago

Using sls version 3.38.0 a slight change to the script above seems to be successfully upgrading from 16 to 20.

'use strict';

class LambdaUpdateDeprecatedRuntime {

    constructor(serverless, options) {
        this.serverless = serverless;
        this.options = options;
        this.provider = 'aws';

        this.hooks = {
            'after:package:compileEvents': this.afterCompileEvents.bind(this),
        };
    }

    afterCompileEvents() {
        let key = 'CustomDashresourceDashexistingDashs3LambdaFunction'
        let resources = this.serverless.service.provider.compiledCloudFormationTemplate.Resources;
        if (key in resources && resources[key].Properties.Runtime === 'nodejs16.x') {
            this.serverless.cli.log("Fixed CustomDashresourceDashexistingDashs3LambdaFunction runtime from `nodejs16.x` to `nodejs20.x`");
            resources[key].Properties.Runtime = 'nodejs20.x'
        }
    }
}

module.exports = LambdaUpdateDeprecatedRuntime;
iamtekeste commented 2 months ago

thank you all, @martinash78 snippet worked all i had to change was the key to CustomDashresourceDashapigwDashcwDashroleLambdaFunction and nodejs16.x to nodejs12.x

rurouni-najeeb commented 2 months ago

Thanks a lot @mokamoto12, the snipped worked. For whom the plugin does not run, I changed the hook from 'after:deploy:compileEvents': this.afterCompileEvents.bind(this) to 'before:deploy:deploy': () => this.afterCompileEvents(). Seems like the naming for the lifecycle events changed in serverless 🤷

georgesglynn commented 1 month ago

Hello!

I am running into the same issue here. However it appears the custom resource lambda that is auto-generated by the 'existing: true' flag on an S3 event is using AWS SDK v2 during its deployment step.

This means if you have it appropriately configured to be Node v20 like you all have figured out, on deployments this will fail in CloudFormation when it attempts to pull in 'aws-sdk'.

This is fine if it you don't plan on touching this event notification configuration, but the moment you do, or if you need to perform a fresh deployment, your deployment will fail.

I can't find any guidance from serverless related to this issue, it seems like our only options would be to somehow override that custom resource lambda with code that uses AWS SDK v3, or hope a new version of serverless v3 comes out that upgrades this.

What do you think?

tyingq commented 1 month ago

Adding this to serverless.yml is working in serverless v3.x for me:

resources:
  - extensions:
      CustomDashresourceDashexistingDashs3LambdaFunction:
        Properties:
          Runtime: nodejs20.x
georgesglynn commented 1 month ago

Hello!

I am running into the same issue here. However it appears the custom resource lambda that is auto-generated by the 'existing: true' flag on an S3 event is using AWS SDK v2 during its deployment step.

This means if you have it appropriately configured to be Node v20 like you all have figured out, on deployments this will fail in CloudFormation when it attempts to pull in 'aws-sdk'.

This is fine if it you don't plan on touching this event notification configuration, but the moment you do, or if you need to perform a fresh deployment, your deployment will fail.

I can't find any guidance from serverless related to this issue, it seems like our only options would be to somehow override that custom resource lambda with code that uses AWS SDK v3, or hope a new version of serverless v3 comes out that upgrades this.

What do you think?

Learned today that this was fixed in a later version of serverless very recently. Updating to serverless version 3.39.0 has resolved this issue (you can see in the changelog that they converted this custom resource code to AWS SDK v3!) Woo!