このページについて

New RelicのWorkflowでSlack通知させるシーン、ありますよね?
その設定をTerraformで入れたいと思いますよね?
今回は、TerraformからNew Relic WorkflowとSlackを連携してみた内容をまとめます。

これまでやっていた設定

TerraformでのWorkflowとSlack通知の連携は行わず(放置し)、Slack通知設定部分は手動設定してました。
Workflow設定画面の下にあるSlackアイコンから追加してます。

Terraformコード側にSlackのことを定義してないので、terraform applyでエラー(と言っても他の変更は反映される)、もしくは、手動設定したSlack設定が削除されるような挙動になってました。(newrelic provider versionによって挙動変わるかもしれません)

現状できること(結論)

  • TerraformでSlackのDestinationの設定を一発でやることはできない
  • そのため、New RelicコンソールでDestination作って、terraform importする
  • インポート後は、以下のリソースでWorkflowとSlack通知の連携の管理可能
    • newrelic_notification_destination
    • newrelic_notification_channel
    • newrelic_workflow

制限

Error: INVALID_PARAMETER: Channels ids are already in use by workflows

複数のWorkflowで同じSlackチャンネルを宛先にできません。。
New Relicコンソールからだとできますが、Terraformでは現状できない仕様です。。

We see that the channel usage restriction causes confusion and do plan to address this problem in the long term. However, as of now, we do not have any concrete plans or timelines.
(DeepL翻訳)チャンネル利用制限が混乱を招いていることは認識しており、長期的にはこの問題に対処する予定です。しかし、現在のところ、具体的な計画やスケジュールはありません。

そのうち解決されそうではありますが、いつになることやら。。

ドキュメントを確認

何はともあれ Resource: newrelic_notification_destination のドキュメントを確認します。
Slackの項目にこんなことが書いてありました。

Slack destinations are created by actively interacting with the UI. This is how OAuth authentication works and there is no way to authenticate otherwise. Because of this, there is no way to create a slack destination via terraform, and must be created in the UI and imported into terraform.
(DeepL翻訳)Slackの宛先は、UIと積極的に対話することで作成されます。これがOAuth認証の仕組みであり、そうでない場合は認証する方法がない。このため、terraform経由でslackの宛先を作成する方法はなく、UIで作成しterraformにインポートする必要があります。

つまり、New RelicコンソールでDestinationを作って、terraform importすればいけると書いてあります。

手順

Resource: newrelic_notification_destination のドキュメント内の Import Slack Destination にて記載されています。

1.Add an empty resource to your terraform file:

resource "newrelic_notification_destination" "foo" {
}

2.Run import command:

$ terraform import newrelic_notification_destination.foo {destination_id}

3.Run the following command after the import successfully done and copy the information to your Slack resource:

$ terraform state show newrelic_notification_destination.foo

4.Add ignore_changes attribute on auth_token in your imported resource:

lifecycle {
    ignore_changes = [auth_token]
}

やってみた

1. Destinationの設定

まず、このコマンドを見た時、 destination_id がよくわかりませんでした。

terraform import newrelic_notification_destination.foo <destination_id>

destination_id は、Workflowの設定画面ではなく、Destinationの設定画面からIDを確認していきます。

(DestinationにSlackを登録していない場合)
Destinations からSlackを登録。

Slackのスペースと紐付けます。

登録したスペースと連携したDestinationの「…」メニューから、Copy destination id to clipboard を選択できます。
この段階ではSlackチャンネルの情報は何も設定していません。

2. terraform import

先にTerraformファイル側に空のリソースを作成します。

resource "newrelic_notification_destination" "matsuki-test" {
}

先ほどコピーしたIDを使います。
ここではコピーしたdestination idを abcdefgh-1234-abcd-1234567819012 とさせていただきます。

$ terraform import newrelic_notification_destination.matsuki-test abcdefgh-1234-abcd-1234567819012
newrelic_notification_destination.matsuki-test: Importing from ID "abcdefgh-1234-abcd-1234567819012"...
newrelic_notification_destination.matsuki-test: Import prepared!
Prepared newrelic_notification_destination for import
newrelic_notification_destination.matsuki-test: Refreshing state... [id=abcdefgh-1234-abcd-1234567819012]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

3. terraform state show

terraform state showを実行し、この出力を newrelic_notification_destination の定義の基にしていきます。

$ terraform state show newrelic_notification_destination.matsuki-test
# newrelic_notification_destination.matsuki-test:
resource "newrelic_notification_destination" "matsuki-test" {
    account_id = XXXXXXX
    active     = true
    id         = "abcdefgh-1234-abcd-1234567819012"
    name       = "cloudpack"
    status     = "DEFAULT"
    type       = "SLACK"

    auth_token {
        prefix = "Bearer"
    }

    property {
        key   = "scope"
        label = "Permissions"
        value = "app_mentions:read,channels:join,channels:read,chat:write,chat:write.public,commands,groups:read,links:read,links:write,team:read,users:read"
    }
    property {
        key   = "teamName"
        label = "Team Name"
        value = "cloudpack"
    }
}

4. Terraformコードに反映

3つのリソースの紐付けが必要です。

  • newrelic_notification_destination
  • newrelic_notification_channel
  • newrelic_workflow

newrelic_notification_destination

以下のドキュメントを確認し、必須じゃない項目をコメントアウトしていきます。
Resource: newrelic_notification_destination

lifecycleの ignore_changes に、 auth_token を含めろとは書いてますが、terraform stateからコピペしてきた auth_token 自体もコメントアウトしないとエラーになりました。( auth_token にはprefixとtokenが必須)
追加したのはlifecycleのみ、あとは不要なものをコメントアウトしただけで、その他内容自体は変えてません。

resource "newrelic_notification_destination" "matsuki-test" {
    # account_id = XXXXXXX
    # active     = true
    # id         = "abcdefgh-1234-abcd-1234567819012"
    name       = "cloudpack"
    # status     = "DEFAULT"
    type       = "SLACK"

    # auth_token {
    #     prefix = "Bearer"
    # }

    property {
        key   = "scope"
        label = "Permissions"
        value = "app_mentions:read,channels:join,channels:read,chat:write,chat:write.public,commands,groups:read,links:read,links:write,team:read,users:read"
    }
    property {
        key   = "teamName"
        label = "Team Name"
        value = "cloudpack"
    }

    lifecycle {
      ignore_changes = [auth_token]
    }
}

newrelic_notification_channel

以下のドキュメントのSlackの例をコピペしつつ、必須じゃない項目をコメントアウトしていきます。
Resource: newrelic_notification_channel

channelIdのvalueは、設定したいSlackチャンネルのチャンネルIDを入れます。
チャンネルIDは、Slackアプリからチャンネルのリンクをコピーして確認できます。
https://xxx.slack.com/archives/XXXXXXXXX のようになっており、
XXXXXXXXX の部分がチャンネルIDとなります。

resource "newrelic_notification_channel" "matsuki-test" {
  # account_id = 12345678
  name = "chat-matsuki"
  type = "SLACK"
  destination_id = newrelic_notification_destination.matsuki-test.id
  product = "IINT"

  property {
    key = "channelId"
    value = "XXXXXXXXX"
  }

  # property {
  #   key = "customDetailsSlack"
  #   value = "issue id - {{issueId}}"
  # }
}

newrelic_workflow

newrelic_workflow側のdestinationに、作成したdestionationのIDを紐付けます。
Resource: newrelic_workflow

resource "newrelic_workflow" "test" {
・・・
  destination {
    channel_id = newrelic_notification_channel.matsuki-test.id
  }
}

5. terraform apply

デプロイすることで、WorkflowにSlackチャンネルが紐付きます。

この後さらにterraform planすると、もちろん No changesが出ます!

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no
changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

確認

WorkflowからSlack通知設定を手動削除して、再度terraform applyしてみます。

手動削除

Deleteした後に、さらにWorkflowの Update workflow も忘れずに。

再度terraform apply

Note: Objects have changed outside of Terraform でSlack設定が削除されたことも確認できます。

Note: Objects have changed outside of Terraform

Terraform detected the following changes made outside of Terraform since the last "terraform apply":

  # newrelic_notification_channel.matsuki-test has been deleted
  - resource "newrelic_notification_channel" "matsuki-test" {
    //内容割愛
    }

  # newrelic_workflow.test has changed
  ~ resource "newrelic_workflow" "test" {
    //内容割愛
    }


Unless you have made equivalent changes to your configuration, or ignored the relevant attributes using
ignore_changes, the following plan may include actions to undo or respond to these changes.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
  + create
  ~ update in-place

Terraform will perform the following actions:

  # newrelic_notification_channel.matsuki-test will be created
  + resource "newrelic_notification_channel" "matsuki-test" {
    //内容割愛
    }

  # newrelic_workflow.test will be updated in-place
  ~ resource "newrelic_workflow" "test" {
    //内容割愛
    }

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

再度Slack通知設定が入っていることを確認できます。
Workflowのdestinationの並び順は、terraformの実行順によるんでしょうか。順番変わったりしますよね。

最後にterraform planすると、まだ Note: Objects have changed outside of Terraform が残っていたりしますが、以下のようなコメントであれば terraform apply -refresh-only でキレイにするだけで良いですね。

No changes. Your infrastructure matches the configuration.

Your configuration already matches the changes detected above. If you'd like to update the Terraform state to
match, create and apply a refresh-only plan:
terraform apply -refresh-only

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

おわりに

TerraformでNew Relic WorkflowのSlack通知設定部分を取り込むことができました。
取り込む手間はありますが、一度取り込んでしまえばTerraformで設定を管理することができるので運用が楽になるかと思います。ぜひお試しください。