[CDK For Terraform]AWSとDatadogでマルチプロバイダー設定する場合

# はじめに

サービスをAWSで構築していて監視をDatadogにしている場合、
監視対象のリソース名が変わったら監視設定も動的に変更したいものです。

ただ、Terraformでは実現できるもののHCL書きたくない症候群だったり、
素のCDKではAWSのみのため実現できません。

CDK for Terraformを使ってAWSとDatadogのリソースを作成してみます。

# 前提条件

- AWSとDataDogのインテグレーション設定が完了している
- `cdktf-docker`の実行環境をあらかじめBuildしてある
https://qiita.com/Myabaou/items/65ab6ad01760cac17182
- `aws-sample`というAWSProfileで設定してある

## 初期化

```sh
docker run -it --rm \
-v ./:/app \
-v ~/.aws:/root/.aws \
-e AWS_PROFILE=aws-sample \
-w /app cdktf-docker:latest \
cdktf  init --template="typescript" --providers="aws@~>5.0"
```

対話式になるので適当に答えます。

```log
? Do you want to continue with Terraform Cloud remote state management? no
? Project Name app
? Project Description A simple getting started project for cdktf.
? Do you want to start from an existing Terraform project? no
? Do you want to send crash reports to the CDKTF team? Refer to https://developer.hashicorp.com/terraform/cdktf/create-and-deploy/configuration-file#enable-crash-reporting-for-the-cli for more information no
```

```sh
ls -l
```

package.json等があればOKです。

```sh
npm install @cdktf/provider-aws
npm install --save-dev @types/node
npm install --save-dev @types/papaparse
npm install papaparse
npm install @cdktf/provider-datadog
```

## Datadog認証情報ファイル作成

```json
{
 "datadog_api_key": "XXXXXXXXXXXXXX",
 "datadog_app_key": "XXXXXXXXXXXXXXXXXXXXXXXX"
}
```

## main.tsの修正

```typescript
import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";
import { DatadogProvider } from "@cdktf/provider-datadog/lib/provider";
import { SqsQueue } from "@cdktf/provider-aws/lib/sqs-queue";
import { Monitor } from '@cdktf/provider-datadog/lib/monitor';

import * as fs from 'fs';

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

    // define resources here
    new AwsProvider(this, 'aws', {
      region: "us-east-2", // Example: 'us-west-2'
      defaultTags: [{
        tags: {
          environment: id,
          IaC: 'cdktf',

        }
      }]
    });

    // 認証情報管理ファイルからパスワードを読み込む
    const credentialConfig = JSON.parse(fs.readFileSync(`credentials_datadog.json`, 'utf-8'));

    // Datadog provider
    const datadog = new DatadogProvider(this, 'datadog', {
      apiKey: credentialConfig.datadog_api_key,
      appKey: credentialConfig.datadog_app_key,
    });

    // SQSを作成
    const queue = new SqsQueue(this, 'queue', {
      name: 'data-dog-queue',
    });

    // Datadog SQS の監視設定

    new Monitor(this, 'sqs-monitor', {
      provider: datadog,
      name: 'SQSのテスト監視',
      tags: ['sqs', 'critical'],
      message: '{{^is_recovery}} SQSのテスト監視。 {{/is_recovery}}',
      query: `avg(last_5m):sum:aws.sqs.approximate_number_of_messages_visible{${queue.name}} > 10`,
      type: 'metric alert',
      monitorThresholds: {
        critical: '10',
        warning: '7',
      },
    });

  }
}

const app = new App();
new MyStack(app, "aws-datadog");
app.synth();

```

Monitorの設定箇所で`provider`の設定をする必要があります。


## 反映

実際に反映してみましょう。

```hcl
[INFO]: AWS SSO goals-us Authentication successful!
[CMD]: 	docker run -it --rm -v ./:/app -v ~/.aws:/root/.aws -e AWS_PROFILE=aws-sample -w /app cdktf-docker:latest cdktf deploy
(node:1) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
${TfToken[TOKEN.0]}

aws-datadog  Initializing the backend...
aws-datadog  Initializing provider plugins...
aws-datadog  - Reusing previous version of datadog/datadog from the dependency lock file
aws-datadog  - Reusing previous version of hashicorp/aws from the dependency lock file
aws-datadog  - Installing datadog/datadog v3.40.0...
aws-datadog  - Installed datadog/datadog v3.40.0 (signed by a HashiCorp partner, key ID FB70BE941301C3EA)
aws-datadog  - Installing hashicorp/aws v5.57.0...
aws-datadog  - Installed hashicorp/aws v5.57.0 (signed by HashiCorp)
             Partner and community providers are signed by their developers.
             If you'd like to know more about provider signing, you can read about it here:
             https://www.terraform.io/docs/cli/plugins/signing.html

             Terraform has been successfully initialized!

             You may now begin working with Terraform. Try running "terraform plan" to see
             any changes that are required for your infrastructure. All Terraform commands
             should now work.

             If you ever set or change modules or backend configuration for Terraform,
             rerun this command to reinitialize your working directory. If you forget, other
             commands will detect it and remind you to do so if necessary.
aws-datadog  - Fetching hashicorp/aws 5.57.0 for linux_amd64...
aws-datadog  - Retrieved hashicorp/aws 5.57.0 for linux_amd64 (signed by HashiCorp)
aws-datadog  - Fetching datadog/datadog 3.40.0 for linux_amd64...
aws-datadog  - Retrieved datadog/datadog 3.40.0 for linux_amd64 (signed by a HashiCorp partner, key ID FB70BE941301C3EA)
             - Obtained hashicorp/aws checksums for linux_amd64; All checksums for this platform were already tracked in the lock file
             - Obtained datadog/datadog checksums for linux_amd64; All checksums for this platform were already tracked in the lock file
aws-datadog  Success! Terraform has validated the lock file and found no need for changes.
aws-datadog  Terraform used the selected providers to generate the following execution plan.
             Resource actions are indicated with the following symbols:
               + create

             Terraform will perform the following actions:
aws-datadog    # aws_sqs_queue.queue (queue) will be created
               + resource "aws_sqs_queue" "queue" {
                   + arn                               = (known after apply)
                   + content_based_deduplication       = false
                   + deduplication_scope               = (known after apply)
                   + delay_seconds                     = 0
                   + fifo_queue                        = false
                   + fifo_throughput_limit             = (known after apply)
                   + id                                = (known after apply)
                   + kms_data_key_reuse_period_seconds = (known after apply)
                   + max_message_size                  = 262144
                   + message_retention_seconds         = 345600
                   + name                              = "data-dog-queue"
                   + name_prefix                       = (known after apply)
                   + policy                            = (known after apply)
                   + receive_wait_time_seconds         = 0
                   + redrive_allow_policy              = (known after apply)
                   + redrive_policy                    = (known after apply)
                   + sqs_managed_sse_enabled           = (known after apply)
                   + tags_all                          = {
                       + "IaC"         = "cdktf"
                       + "environment" = "aws-datadog"
                     }
                   + url                               = (known after apply)
                   + visibility_timeout_seconds        = 30
                 }

               # datadog_monitor.sqs-monitor (sqs-monitor) will be created
               + resource "datadog_monitor" "sqs-monitor" {
                   + enable_samples      = (known after apply)
                   + evaluation_delay    = (known after apply)
                   + id                  = (known after apply)
                   + include_tags        = true
                   + message             = "{{^is_recovery}} SQSのテスト監視。 {{/is_recovery}}"
                   + name                = "SQSのテスト監視"
                   + new_host_delay      = 300
                   + notify_no_data      = false
                   + query               = "avg(last_5m):sum:aws.sqs.approximate_number_of_messages_visible{data-dog-queue} > 10"
                   + require_full_window = true
                   + tags                = [
                       + "critical",
                       + "sqs",
                     ]
                   + type                = "metric alert"

                   + monitor_thresholds {
                       + critical = "10"
                       + warning  = "7"
                     }
                 }

             Plan: 2 to add, 0 to change, 0 to destroy.

             Do you want to perform these actions?
               Terraform will perform the actions described above.
               Only 'yes' will be accepted to approve.
aws-datadog  Enter a value: yes
aws-datadog  aws_sqs_queue.queue: Creating...
aws-datadog  aws_sqs_queue.queue: Still creating... [10s elapsed]
aws-datadog  aws_sqs_queue.queue: Still creating... [20s elapsed]
aws-datadog  aws_sqs_queue.queue: Creation complete after 29s [id=https://sqs.us-east-2.amazonaws.com/XXXXXXXXXXXXXXXXXX/data-dog-queue]
aws-datadog  datadog_monitor.sqs-monitor: Creating...
aws-datadog  datadog_monitor.sqs-monitor: Creation complete after 0s [id=149042347]
aws-datadog
             Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

No outputs found.
```

AWS上にSQSが作成されていてDatadogにも監視アラートが
設定できることが確認できました。

サンプルコードのため変数などは最低限にしていますが、
別Classなどにわけることで可用性を高めることができます。

Terraformでの実行も可能です。

```sh
terraform -chdir=cdktf.out/stacks/aws-datadog state list
```

```log
aws_sqs_queue.queue
datadog_monitor.sqs-monitor
```


## まとめ

自身が好きな言語でクラウドリソースも監視設定も
書きたいといったケースにおいては需要がありそうです。