AWS CDK的功能(与打字稿差异)
#aws #typescript #go #awscdk

AWS CDK通常用打字稿编写,但可以用各种编程语言编写。

在本文中,我想写Golang的AWS CDK功能。

假设

此处介绍的Golang代码使用V1.18.7。

AWS CDK版本为v2.52.0。

我们将在本文中讨论的AWS CDK的功能主要是与Typescript版本。

基本功能可以在the document here中找到。

功能(与打字稿差异)

init的目录结构

在GO的情况下,cdk init app --language go之后创建的目录结构如下。

名为cdk-go的目录(存储库)。

❯ tree
.
├── README.md
├── cdk-go.go
├── cdk-go_test.go
├── cdk.json
└── go.mod

在打字稿的情况下,分开了binlibtest目录,并且基于package.json与init同时安装了模块,并且还生成了node_modules

>

Go更简单,没有层次结构,这可能是由于在GO中开发时经常使用的平坦目录结构。

初始化的文件内容

在GO中,仅生成cdk-go.gocdk-go_test.go GO文件,如上所述。

在Typescript中,堆栈生成代码写在bin中生成的文件和lib中生成的文件中的堆栈定义代码中编写,但是在GO中,两者都在同一单个文件(cdk-go.go)中写入。

这是cdk-go.go的初始代码。

package main

import (
    "github.com/aws/aws-cdk-go/awscdk/v2"
    // "github.com/aws/aws-cdk-go/awscdk/v2/awssqs"
    "github.com/aws/constructs-go/constructs/v10"
    "github.com/aws/jsii-runtime-go"
)

type CdkGoStackProps struct {
    awscdk.StackProps
}

func NewCdkGoStack(scope constructs.Construct, id string, props *CdkGoStackProps) awscdk.Stack {
    var sprops awscdk.StackProps
    if props != nil {
        sprops = props.StackProps
    }
    stack := awscdk.NewStack(scope, &id, &sprops)

    // The code that defines your stack goes here

    // example resource
    // queue := awssqs.NewQueue(stack, jsii.String("CdkGoQueue"), &awssqs.QueueProps{
    //  VisibilityTimeout: awscdk.Duration_Seconds(jsii.Number(300)),
    // })

    return stack
}

func main() {
    defer jsii.Close()

    app := awscdk.NewApp(nil)

    NewCdkGoStack(app, "CdkGoStack", &CdkGoStackProps{
        awscdk.StackProps{
            Env: env(),
        },
    })

    app.Synth(nil)
}

// env determines the AWS environment (account+region) in which our stack is to
// be deployed. For more information see: https://docs.aws.amazon.com/cdk/latest/guide/environments.html
func env() *awscdk.Environment {
    // If unspecified, this stack will be "environment-agnostic".
    // Account/Region-dependent features and context lookups will not work, but a
    // single synthesized template can be deployed anywhere.
    //---------------------------------------------------------------------------
    return nil

    // Uncomment if you know exactly what account and region you want to deploy
    // the stack to. This is the recommendation for production stacks.
    //---------------------------------------------------------------------------
    // return &awscdk.Environment{
    //  Account: jsii.String("123456789012"),
    //  Region:  jsii.String("us-east-1"),
    // }

    // Uncomment to specialize this stack for the AWS Account and Region that are
    // implied by the current CLI configuration. This is recommended for dev
    // stacks.
    //---------------------------------------------------------------------------
    // return &awscdk.Environment{
    //  Account: jsii.String(os.Getenv("CDK_DEFAULT_ACCOUNT")),
    //  Region:  jsii.String(os.Getenv("CDK_DEFAULT_REGION")),
    // }
}

struct CdkGoStackProps具有函数NewCdkGoStackmainenv

NewXxxStack是堆栈定义(在typescript中的lib中),而main是堆栈生成(在typeScript中的bin中)。

main()功能中的defer jsii.Close()是自动清理CDK应用程序(请参阅上面的官方参考)。

在打字稿版本中找不到函数env,而是GO版本(从一开始就写成),并使用AccountRegion返回awscdk.Environment结构。

顺便说一句,初始化时的测试代码在这里。

package main

// import (
//  "testing"

//  "github.com/aws/aws-cdk-go/awscdk/v2"
//  "github.com/aws/aws-cdk-go/awscdk/v2/assertions"
//  "github.com/aws/jsii-runtime-go"
// )

// example tests. To run these tests, uncomment this file along with the
// example resource in cdk-go_test.go
// func TestCdkGoStack(t *testing.T) {
//  // GIVEN
//  app := awscdk.NewApp(nil)

//  // WHEN
//  stack := NewCdkGoStack(app, "MyStack", nil)

//  // THEN
//  template := assertions.Template_FromStack(stack)

//  template.HasResourceProperties(jsii.String("AWS::SQS::Queue"), map[string]interface{}{
//      "VisibilityTimeout": 300,
//  })
// }

指针转换为JSII

在某些地方查看上面的代码,尤其是在指定参数时,诸如jsii.Numberjsii.String之类的函数围绕参数指定的值。

    queue := awssqs.NewQueue(stack, jsii.String("CdkGoQueue"), &awssqs.QueueProps{
        VisibilityTimeout: awscdk.Duration_Seconds(jsii.Number(300)),
    })

jsii.Numberjsii.String仅返回指针的功能

实际上,这是规则在CDK版本中指定参数时

因为GO语言没有零允许的类型,而唯一可以包含nil的类型是指针类型。 (“仅”一词可能具有误导性,但我们不会去这里,而是翻译上述文档。)

so,要实现可选参数的“无属性”,我们可以通过一个可以作为nil的指针类型(请参见上面的文档)。

这是使用的主要区域。

  • JSII.String
  • jsii.number
  • jsii.bool
  • JSII.Time

这是CDK的GO版本的主要且麻烦的功能之一,但是一旦您习惯了,它就没有(?)。我认为一旦您习惯了,这不是问题。 (这会使外观变得更糟,但是...)

CDK模块中的字段和方法名称是Pascal情况

在打字稿版本中,我认为它是骆驼,但是在GO版本中,基本上是 cdk中提供的字段和方法名称是pascalcase(以大写字母开始)(请参阅上面的文档)。

这是GO的语言规范,公众(包装外)呼叫只能通过Pascal案件调用。

在GO中进行编码时,如果范围是私有的(正确,包裹),则将是骆驼。

以下是一个示例:当您尝试通过复制打字稿中编写的样本进行示例时,请小心。

cfnAppRunner.SetHealthCheckConfiguration(&awsapprunner.CfnService_HealthCheckConfigurationProperty{
    Path:     jsii.String("/"),
    Protocol: jsii.String("HTTP"),
})

无法逃脱舱口。

是的,我在逃生舱口上遇到了麻烦。这是一个非常大的问题 GO版本所特有的。

首先,CDK具有一个方便的功能,称为L2 Construct,您可以通过简单地指定一些必需的值来根据最佳实践来构建资源。

也有L1构造,它允许您通过以与云形式一致的方式指定资源来构建资源。

虽然L2构造很方便且易于创建资源,但它也会抽象参数,因此有一些参数在l2 中未指定。。

因此,有一种方法可以将用L2构造创建的资源铸造为L1构造类型,然后覆盖只能用L1指定的参数,即“ Escape Hatch”。

但是,GO的CDK目前不支持the workshop

CDK具有一个名为“逃生舱口”的概念,它允许您修改L2构造的基础CFN资源以访问由云形式支持但尚未得到CDK支持的功能。不幸的是,GO的CDK尚未支持此功能,因此我们必须通过L1构造创建资源。有关更多信息,请参见此GitHub问题,并在GO中遵循支持CDK逃生舱口的支持。

那么,如果要指定在L2构造中无法指定的参数,则该怎么办,它必须是L1构造?

同时,有一种方法可以进行逃生舱口。您可以使用方法 jsii.Get

var cfnAppRunner awsapprunner.CfnService
jsii.Get(apprunnerServiceL2.Node(), "defaultChild", &cfnAppRunner)

cfnAppRunner.SetAutoScalingConfigurationArn(autoScalingConfigurationArn)

但是,这个 jsii.Get被弃用(请参阅this page),所以我觉得我别无选择,只能使用它。

快照测试

“快照测试”是您几乎可以将其视为CDK测试的测试。

您可以在打字稿中使用jest(JavaScript)进行操作,但是在Go中,您可以按照以下方式进行。

从堆栈生成模板,然后将jsonized版本传递给cupaloy.SnapshotT以执行快照。

    stack := NewAppRunnerStack(app, "AppRunnerStack", appRunnerStackProps)

    template := assertions.Template_FromStack(stack, nil)
    templateJson := template.ToJSON()

    t.Run("Snapshot Test", func(t *testing.T) {
        cupaloy.SnapshotT(t, templateJson)
    })

额外的

以下不是与打字稿有所不同,而是更像是独特的开发方法。

工作区模式

使用CDK开发时,您可能有多个代码组。

首先,有CDK代码组,然后是lambda和ecs的代码组。

在这种情况下,可以在一个存储库中准备这些目录,并通过共享go.mod在根目录中构建它们,但是您需要准备一个GO.mod 组合每个中需要的东西一个(多模块)

(顺便说一句,在打字稿中,您可以使用aws-lambda-nodejs在单个软件包中分别在单个软件包中获取一个不错的lambda和cdk定义。)

go在版本1.18中介绍了一个名为"Workspaces mode"的功能,该功能允许多模块(比以前更容易)。

这允许每个子目录的多模块开发并使用go.mod构建。

击中以下命令将使您处于工作空间模式。

go work init moduleA moduleB

然后将创建以下go.work文件以启用多模块开发。

go 1.18

use (
    ./moduleA
    ./moduleB
)

示例实现

如果您想看到它,我用AWS CDK制作了an actual example。 (在示例中,我们正在制作App Runner。)

最后

我总结了我对GO的CDK的经验,因为我发现它与打字稿版本完全不同。

老实说,与CDK的打字稿版本相比,它仍然处于起步阶段,但我仍然很高兴能够写!