以前、AMG(Amazon Managed Grafana)がGrafana APIトークン作成のAPIをサポートしてIaC化しやすくなった、というエントリを書きました。
このときはまだAPI Keyに対応するTerraformリソースがなかったので、External Data Source providerを使ってAWS CLI経由でトークンを作成し、それをTerraformに取り込むという、ややトリッキーな、少しわかりにくい実装を行ないました。
しかしその後2022/08/27にリリースされたAWS Provider v4.28.0にて、aws_grafana_workspace_api_key
リソースが追加されました🎉
これを使えばより簡潔にわかりやすくIaC化できるのでは、と思って挑戦してみました。が、結果うまく行かないことがわかりましたので、レポートします。
テストコード
以下のリソースをプロビジョニングするコードです。
- AMG workspace
- AMG workspace API Key
- 上記workspace上にプロビジョニングする、AMP(Managed Prometheus) workspaceをソースにしたGrafana Data Source
- ※ AMG workspaceが使うロールと、AMP workspaceも必要です。 が、今回は既に作成済みのものがあったのでそちらを利用することにし、これらの情報はvariablesにすることにしました。
main.tf
terraform {
required_version = "= 1.2.1"
required_providers {
aws = {
version = "4.32.0"
}
grafana = {
source = "grafana/grafana"
version = "1.16.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
provider "grafana" {
url = "https://${aws_grafana_workspace.main.endpoint}/"
auth = aws_grafana_workspace_api_key.main.key
}
variables.tf
variable "grafana_workspace_role_arn" {
type = string
}
variable "amp_workspace_url" {
type = string
}
managed_grafana.tf
resource "aws_grafana_workspace" "main" {
account_access_type = "CURRENT_ACCOUNT"
authentication_providers = ["AWS_SSO"]
permission_type = "SERVICE_MANAGED"
name = "kazue-test"
description = "test"
role_arn = var.grafana_workspace_role_arn
data_sources = ["PROMETHEUS", "CLOUDWATCH"]
}
resource "aws_grafana_workspace_api_key" "main" {
key_name = "test-key"
key_role = "ADMIN"
seconds_to_live = 180
workspace_id = aws_grafana_workspace.main.id
}
grafana_datasource.tf
resource "grafana_data_source" "prometheus" {
type = "prometheus"
name = "prometheus_datasource"
is_default = true
url = var.amp_workspace_url
json_data {
http_method = "POST"
sigv4_auth = true
sigv4_auth_type = "workspace-iam-role"
sigv4_region = data.aws_region.current.name
}
}
data "aws_region" "current" {}
初回 apply → OK
% terraform apply
data.aws_region.current: Reading...
data.aws_region.current: Read complete after 0s [id=ap-northeast-1]
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_grafana_workspace.main will be created
+ resource "aws_grafana_workspace" "main" {
+ account_access_type = "CURRENT_ACCOUNT"
+ arn = (known after apply)
+ authentication_providers = [
+ "AWS_SSO",
]
+ data_sources = [
+ "PROMETHEUS",
+ "CLOUDWATCH",
]
+ description = "test"
+ endpoint = (known after apply)
+ grafana_version = (known after apply)
+ id = (known after apply)
+ name = "kazue-test"
+ permission_type = "SERVICE_MANAGED"
+ role_arn = "arn:aws:iam::123456789012:role/service-role/AmazonGrafanaServiceRole-kijC1Ssfn"
+ saml_configuration_status = (known after apply)
+ tags_all = (known after apply)
}
# aws_grafana_workspace_api_key.main will be created
+ resource "aws_grafana_workspace_api_key" "main" {
+ id = (known after apply)
+ key = (known after apply)
+ key_name = "test-key"
+ key_role = "ADMIN"
+ seconds_to_live = 180
+ workspace_id = (known after apply)
}
# grafana_data_source.prometheus will be created
+ resource "grafana_data_source" "prometheus" {
+ access_mode = "proxy"
+ basic_auth_enabled = false
+ id = (known after apply)
+ is_default = true
+ name = "prometheus_datasource"
+ type = "prometheus"
+ url = "https://aps-workspaces.ap-northeast-1.amazonaws.com/workspaces/ws-ecc816a4-f6da-488b-85b4-aaaaaaaaaaaa/"
+ json_data {
+ http_method = "POST"
+ sigv4_auth = true
+ sigv4_auth_type = "workspace-iam-role"
+ sigv4_region = "ap-northeast-1"
}
}
Plan: 3 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.
Enter a value: yes
aws_grafana_workspace.main: Creating...
aws_grafana_workspace.main: Still creating... [10s elapsed]
aws_grafana_workspace.main: Still creating... [20s elapsed]
aws_grafana_workspace.main: Still creating... [30s elapsed]
aws_grafana_workspace.main: Still creating... [40s elapsed]
aws_grafana_workspace.main: Still creating... [50s elapsed]
aws_grafana_workspace.main: Creation complete after 56s [id=g-f2520a71cc]
aws_grafana_workspace_api_key.main: Creating...
aws_grafana_workspace_api_key.main: Creation complete after 0s [id=g-f2520a71cc/test-key]
grafana_data_source.prometheus: Creating...
grafana_data_source.prometheus: Creation complete after 1s [id=1]
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
↑ 依存関係が理由で、以下の順で処理が行われていますね。
- AMG workspace作成
- AMG workspace API Key作成
- (Grafana providerの設定)
- Grafana Data Source作成
2回目以降のapply → OK
% terraform apply
data.aws_region.current: Reading...
aws_grafana_workspace.main: Refreshing state... [id=g-f2520a71cc]
data.aws_region.current: Read complete after 0s [id=ap-northeast-1]
aws_grafana_workspace_api_key.main: Refreshing state... [id=g-f2520a71cc/test-key]
grafana_data_source.prometheus: Refreshing state... [id=1]
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.
API Keyがexpireしたら? → NG
作成したaws_grafana_workspace_api_key.main
のseconds_to_live
attributeは180
つまり3分に設定したので、3分以上待ってもう一度コマンド実行します。
% terraform apply
data.aws_region.current: Reading...
aws_grafana_workspace.main: Refreshing state... [id=g-f2520a71cc]
data.aws_region.current: Read complete after 0s [id=ap-northeast-1]
aws_grafana_workspace_api_key.main: Refreshing state... [id=g-f2520a71cc/test-key]
grafana_data_source.prometheus: Refreshing state... [id=1]
╷
│ Error: status: 401, body: {"message":"Expired API key"}
│
│
│ with grafana_data_source.prometheus,
│ on grafana_data_source.tf line 1, in resource "grafana_data_source" "prometheus":
│ 1: resource "grafana_data_source" "prometheus" {
│
╵
terraform apply
すると、まず現状のリソースの状況を確認する処理(Refreshing state)が走ります。grafana_data_source.prometheus
も既にプロビジョニングされているリソースなのでこの処理が必要です。この際、Grafana provider経由でこの処理が行われるのですが、Grafana providerで使っているAPI Keyは既にexpire(期限切れ)しているためgrafana_data_source.prometheus
の実態にアクセスして状況を確認することができません。
まとめ
新リソースaws_grafana_workspace_api_key
を使ってGrafana Providerの設定をするのはうまくいかないことがわかりました。aws_grafana_workspace_api_key
はあくまでひとつAPI Keyをプロビジョニングするものであり、expireしたら新しいkeyを作り直してくれたりみたいな便利な処理は当然スコープ外です。(なんならexpireしているのかどうかすらわからない。)新リソースaws_grafana_workspace_api_key
に対する私の誤解(過度な期待)でした。。 というわけで前回の構成を使い続けようと思います。