長話短說

俗話說,給貓剝皮有多種方法…在科技界,給 Lambda 函數剝皮有 5 種方法 🤩

我們將比較 5 個開發工具

介紹

當開發人員試圖彌合開發和 DevOps 之間的差距時,我認為比較程式語言和 DevTools 會很有幫助。

讓我們從一個簡單函數的想法開始,該函數將文字檔案上傳到我們的雲端應用程式中的儲存桶。

下一步是展示實現這一目標的幾種方法。

注意:在雲端開發中,管理權限和儲存桶身分、打包執行時程式碼以及處理基礎架構和執行時的多個檔案會增加開發過程的複雜性。

讓我們開始吧

讓我們深入研究一些程式碼!


1.

安裝 Wing後,讓我們建立一個檔案: main.w

如果您不熟悉 Wing 程式語言,請查看此處的開源儲存庫


bring cloud;

let bucket = new cloud.Bucket();

new cloud.Function(inflight () => {
  bucket.put("hello.txt", "world!");
});

讓我們詳細分析一下上面程式碼中發生的情況。

bring cloud是 Wing 的導入語法

建立一個雲端儲存桶: let bucket = new cloud.Bucket();初始化一個新的雲端儲存桶實例。

在後端,Wing 平台在您的雲端供應商環境中配置一個新儲存桶。此桶用於儲存和檢索資料。

建立雲端函數: new cloud.Function(inflight () => { ... });語句定義了一個新的雲函數。

該函數被觸發後,將執行其主體內定義的操作。

bucket.put("hello.txt", "world!");上傳一個名為 hello.txt 的文件,其中包含內容世界!到之前建立的雲端儲存桶。

編譯並部署到 AWS

  • wing compile --platform tf-aws main.w

  • terraform apply

就是這樣,Wing 負責處理複雜性(權限、在執行時程式碼中獲取存儲桶身份、將執行時程式碼打包到存儲桶中、必須編寫多個文件 - 用於基礎設施和執行時)等。

更不用說它會產生 IAC(TF 或 CF),以及可以使用現有工具部署的 Javascript。

但在開發時,您可以使用本機模擬器獲得即時回饋並縮短迭代周期

翼控制台

Wing 甚至還有一個遊樂場,您可以在瀏覽器中試用!

2.刷子

步驟1:初始化一個新的Pulumi專案

mkdir pulumi-s3-lambda-ts
cd pulumi-s3-lambda-ts
pulumi new aws-typescript

步驟 2. 編寫程式碼以將文字檔案上傳到 S3。

這將是您的專案結構。

pulumi-s3-lambda-ts/
├─ src/
│  ├─ index.ts              # Pulumi infrastructure code
│  └─ lambda/
│     └─ index.ts           # Lambda function code to upload a file to S3
├─ tsconfig.json            # TypeScript configuration
└─ package.json             # Node.js project file with dependencies

讓我們將此程式碼加入index.ts


import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

// Create an AWS S3 bucket
const bucket = new aws.s3.Bucket("myBucket", {
    acl: "private",
});

// IAM role for the Lambda function
const lambdaRole = new aws.iam.Role("lambdaRole", {
    assumeRolePolicy: JSON.stringify({
        Version: "2023-10-17",
        Statement: [{
            Action: "sts:AssumeRole",
            Principal: {
                Service: "lambda.amazonaws.com",
            },
            Effect: "Allow",
            Sid: "",
        }],
    }),
});

// Attach the AWSLambdaBasicExecutionRole policy
new aws.iam.RolePolicyAttachment("lambdaExecutionRole", {
    role: lambdaRole,
    policyArn: aws.iam.ManagedPolicy.AWSLambdaBasicExecutionRole,
});

// Policy to allow Lambda function to access the S3 bucket
const lambdaS3Policy = new aws.iam.Policy("lambdaS3Policy", {
    policy: bucket.arn.apply(arn => JSON.stringify({
        Version: "2023-10-17",
        Statement: [{
            Action: ["s3:PutObject", "s3:GetObject"],
            Resource: `${arn}/*`,
            Effect: "Allow",
        }],
    })),
});

// Attach policy to Lambda role
new aws.iam.RolePolicyAttachment("lambdaS3PolicyAttachment", {
    role: lambdaRole,
    policyArn: lambdaS3Policy.arn,
});

// Lambda function
const lambda = new aws.lambda.Function("myLambda", {
    code: new pulumi.asset.AssetArchive({
        ".": new pulumi.asset.FileArchive("./src/lambda"),
    }),
    runtime: aws.lambda.Runtime.NodeJS12dX,
    role: lambdaRole.arn,
    handler: "index.handler",
    environment: {
        variables: {
            BUCKET_NAME: bucket.bucket,
        },
    },
});

export const bucketName = bucket.id;
export const lambdaArn = lambda.arn;

接下來,為 Lambda 函數程式碼建立lambda/index.ts目錄:


import { S3 } from "aws-sdk";

const s3 = new S3();

export const handler = async (): Promise<void> => {
    const bucketName = process.env.BUCKET_NAME || "";
    const fileName = "example.txt";
    const content = "Hello, Pulumi!";

    const params = {
        Bucket: bucketName,
        Key: fileName,
        Body: content,
    };

    try {
        await s3.putObject(params).promise();
        console.log(`File uploaded successfully at https://${bucketName}.s3.amazonaws.com/${fileName}`);
    } catch (err) {
        console.log(err);
    }
};

步驟 3:TypeScript 設定 (tsconfig.json)

{
  "compilerOptions": {
    "target": "ES2018",
    "module": "CommonJS",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}

建立Pulumi專案後,會自動產生yaml檔案。 pulumi.yaml

name: s3-lambda-pulumi
runtime: nodejs
description: A simple example that uploads a file to an S3 bucket using a Lambda function
template:
  config:
    aws:region:
      description: The AWS region to deploy into
      default: us-west-2

與 Pulumi 一起部署

確保正確設定包含index.js檔案的lambda目錄。然後,執行以下命令來部署您的基礎架構: pulumi up


  1. AWS-CDK

步驟1:初始化一個新的CDK專案

mkdir cdk-s3-lambda
cd cdk-s3-lambda
cdk init app --language=typescript

第 2 步:新增依賴項

npm install @aws-cdk/aws-lambda @aws-cdk/aws-s3

步驟 3:在 CDK 中定義 AWS 資源

文件: index.js


import * as cdk from '@aws-cdk/core';
import * as lambda from '@aws-cdk/aws-lambda';
import * as s3 from '@aws-cdk/aws-s3';

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

    // Create the S3 bucket
    const bucket = new s3.Bucket(this, 'MyBucket', {
      removalPolicy: cdk.RemovalPolicy.DESTROY, // NOT recommended for production code
    });

    // Define the Lambda function
    const lambdaFunction = new lambda.Function(this, 'MyLambda', {
      runtime: lambda.Runtime.NODEJS_14_X, // Define the runtime
      handler: 'index.handler', // Specifies the entry point
      code: lambda.Code.fromAsset('lambda'), // Directory containing your Lambda code
      environment: {
        BUCKET_NAME: bucket.bucketName,
      },
    });

    // Grant the Lambda function permissions to write to the S3 bucket
    bucket.grantWrite(lambdaFunction);
  }
}

步驟 4:Lambda 函數程式碼

在 pulumi 目錄中建立與上面相同的檔案結構: index.ts

import { S3 } from 'aws-sdk';
const s3 = new S3();

exports.handler = async (event: any) => {
  const bucketName = process.env.BUCKET_NAME;
  const fileName = 'uploaded_file.txt';
  const content = 'Hello, CDK! This file was uploaded by a Lambda function!';

  try {
    const result = await s3.putObject({
      Bucket: bucketName!,
      Key: fileName,
      Body: content,
    }).promise();

    console.log(`File uploaded successfully: ${result}`);
    return {
      statusCode: 200,
      body: `File uploaded successfully: ${fileName}`,
    };
  } catch (error) {
    console.log(error);
    return {
      statusCode: 500,
      body: `Failed to upload file: ${error}`,
    };
  }
};

部署 CDK 堆疊

首先,編譯 TypeScript 程式碼: npm run build ,然後

將您的 CDK 部署到 AWS: cdk deploy


4.Terraform 的 CDK

步驟1:初始化一個新的CDKTF專案

mkdir cdktf-s3-lambda-ts
cd cdktf-s3-lambda-ts

然後,使用 TypeScript 初始化一個新的 CDKTF 專案:

cdktf init --template="typescript" --local

步驟 2:安裝 AWS Provider 並新增相依性


npm install @cdktf/provider-aws

第 3 步:定義基礎設施

編輯 main.ts 以定義 S3 儲存桶和 Lambda 函數:

import { Construct } from 'constructs';
import { App, TerraformStack } from 'cdktf';
import { AwsProvider, s3, lambdafunction, iam } from '@cdktf/provider-aws';

class MyStack extends TerraformStack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new AwsProvider(this, 'aws', { region: 'us-west-2' });

    // S3 bucket
    const bucket = new s3.S3Bucket(this, 'lambdaBucket', {
      bucketPrefix: 'cdktf-lambda-'
    });

    // IAM role for Lambda
    const role = new iam.IamRole(this, 'lambdaRole', {
      name: 'lambda_execution_role',
      assumeRolePolicy: JSON.stringify({
        Version: '2023-10-17',
        Statement: [{
          Action: 'sts:AssumeRole',
          Principal: { Service: 'lambda.amazonaws.com' },
          Effect: 'Allow',
        }],
      }),
    });

    new iam.IamRolePolicyAttachment(this, 'lambdaPolicy', {
      role: role.name,
      policyArn: 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole',
    });

    const lambdaFunction = new lambdafunction.LambdaFunction(this, 'MyLambda', {
      functionName: 'myLambdaFunction',
      handler: 'index.handler',
      role: role.arn,
      runtime: 'nodejs14.x',
      s3Bucket: bucket.bucket, // Assuming the Lambda code is uploaded to this bucket
      s3Key: 'lambda.zip', // Assuming the Lambda code zip file is named lambda.zip
      environment: {
        variables: {
          BUCKET_NAME: bucket.bucket,
        },
      },
    });

    // Grant the Lambda function permissions to write to the S3 bucket
    new s3.S3BucketPolicy(this, 'BucketPolicy', {
      bucket: bucket.bucket,
      policy: bucket.bucket.apply(name => JSON.stringify({
        Version: '2023-10-17',
        Statement: [{
          Action: 's3:*',
          Resource: `arn:aws:s3:::${name}/*`,
          Effect: 'Allow',
          Principal: {
            AWS: role.arn,
          },
        }],
      })),
    });
  }
}

const app = new App();
new MyStack(app, 'cdktf-s3-lambda-ts');
app.synth();

步驟 4:Lambda 函數程式碼

Lambda 函數程式碼應使用 TypeScript 編寫並編譯為 JavaScript,因為 AWS Lambda 本機執行 JavaScript。以下是您需要編譯和壓縮的 Lambda 函數的範例index.ts


import { S3 } from 'aws-sdk';

const s3 = new S3();

exports.handler = async () => {
  const bucketName = process.env.BUCKET_NAME || '';
  const content = 'Hello, CDKTF!';
  const params = {
    Bucket: bucketName,
    Key: `upload-${Date.now()}.txt`,
    Body: content,
  };

  try {
    await s3.putObject(params).promise();
    return { statusCode: 200, body: 'File uploaded successfully' };
  } catch (err) {
    console.error(err);
    return { statusCode: 500, body: 'Failed to upload file' };
  }
};

您需要將此 TypeScript 程式碼編譯為 JavaScript,對其進行壓縮,然後手動或使用腳本將其上傳到 S3 儲存桶。

確保 LambdaFunction 資源中的 s3Key 指向儲存桶中正確的 zip 檔案。

編譯和部署您的 CDKTF 專案

使用npm run build編譯專案

生成 Terraform 配置文件

執行cdktf synth指令。此命令執行您的 CDKTF 應用程式,該應用程式在cdktf.out目錄中產生 Terraform 設定檔( *.tf.json檔案):

部署您的基礎設施

cdktf deploy

5.地形

第 1 步:Terraform 設定

定義您的 AWS 供應商和 S3 儲存桶

使用以下內容建立名為main.tf的檔案:


provider "aws" {
  region = "us-west-2" # Choose your AWS region
}

resource "aws_s3_bucket" "lambda_bucket" {
  bucket_prefix = "lambda-upload-bucket-"
  acl           = "private"
}

resource "aws_iam_role" "lambda_execution_role" {
  name = "lambda_execution_role"

  assume_role_policy = jsonencode({
    Version = "2023-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      },
    ]
  })
}

resource "aws_iam_policy" "lambda_s3_policy" {
  name        = "lambda_s3_policy"
  description = "IAM policy for Lambda to access S3"

  policy = jsonencode({
    Version = "2023-10-17"
    Statement = [
      {
        Action   = ["s3:PutObject", "s3:GetObject"],
        Effect   = "Allow",
        Resource = "${aws_s3_bucket.lambda_bucket.arn}/*"
      },
    ]
  })
}

resource "aws_iam_role_policy_attachment" "lambda_s3_access" {
  role       = aws_iam_role.lambda_execution_role.name
  policy_arn = aws_iam_policy.lambda_s3_policy.arn
}

resource "aws_lambda_function" "uploader_lambda" {
  function_name = "S3Uploader"

  s3_bucket = "YOUR_DEPLOYMENT_BUCKET_NAME" # Set your deployment bucket name here
  s3_key    = "lambda.zip" # Upload your ZIP file to S3 and set its key here

  handler = "index.handler"
  role    = aws_iam_role.lambda_execution_role.arn
  runtime = "nodejs14.x"

  environment {
    variables = {
      BUCKET_NAME = aws_s3_bucket.lambda_bucket.bucket
    }
  }
}

步驟 2:Lambda 函數程式碼 (TypeScript)

為 Lambda 函數建立 TypeScript 檔案index.ts


import { S3 } from 'aws-sdk';

const s3 = new S3();

exports.handler = async (event: any) => {
  const bucketName = process.env.BUCKET_NAME;
  const fileName = `uploaded-${Date.now()}.txt`;
  const content = 'Hello, Terraform and AWS Lambda!';

  try {
    await s3.putObject({
      Bucket: bucketName!,
      Key: fileName,
      Body: content,
    }).promise();

    console.log('Upload successful');
    return {
      statusCode: 200,
      body: JSON.stringify({ message: 'Upload successful' }),
    };
  } catch (error) {
    console.error('Upload failed:', error);
    return {
      statusCode: 500,
      body: JSON.stringify({ message: 'Upload failed' }),
    };
  }
};

最後,將 Lambda 函數程式碼上傳到指定的 S3 儲存桶後,執行terraform apply


我希望您喜歡在我們的雲端應用程式中編寫將文字檔案上傳到儲存桶的函數的五種簡單方法的比較。

正如您所看到的,除了一段程式碼之外,大多數程式碼都變得非常複雜。

結論!

泰勒絲

點擊圖片⬆️

圖片描述

如果您對 Wing 感興趣並且喜歡我們如何簡化雲端開發流程,請給我們一顆 ⭐ 顆星。

{% cta https://github.com/winglang/wing %} 請star ⭐ Wing {% endcta %}


原文出處:https://dev.to/winglang/5-ways-to-write-a-simple-function-in-your-cloud-app-1jgl


共有 0 則留言