outputsだけを追加してtarraform planするとtfnotifyがパースエラーになる
Terraform を触っていて若干面倒になった部分があったのでメモ。
現状としては、「outputsだけを追加してterraform planするとtfnotifyがパースエラーで落ちる」というものです。
tfnotifyとは
tfnotifyはメルカリが開発しているTerraformの実行結果を通知してくれるCLIです。
GitHubやSlackなどに結果を投げられます。
tfnotifyのexit code判定
tfnotifyは下記の正規表現によってterraform planが成功したかどうかを判定しています。
リソースが変更されれば Plan: \d
にマッチして、なにも追加されていなければ No changes.
にマッチするというわけですね。
// NewPlanParser is PlanParser initialized with its Regexp func NewPlanParser() *PlanParser { return &PlanParser{ Pass: regexp.MustCompile(`(?m)^(Plan: \d|No changes.)`), // ここ Fail: regexp.MustCompile(`(?m)^(Error: )`), // "0 to destroy" should be treated as "no destroy" HasDestroy: regexp.MustCompile(`(?m)([1-9][0-9]* to destroy.)`), HasNoChanges: regexp.MustCompile(`(?m)^(No changes. Infrastructure is up-to-date.)`), } }
https://github.com/mercari/tfnotify/blob/master/terraform/parser.go#L61-L70
また、exit codeは下記のswitch文で判定しています。
PassとFailの正規表現両方にマッチしなかったものはパースエラーとして処理されます。
var exitCode int switch { case p.Pass.MatchString(body): exitCode = ExitPass case p.Fail.MatchString(body): exitCode = ExitFail default: return ParseResult{ Result: "", ExitCode: ExitFail, Error: fmt.Errorf("cannot parse plan result"), } }
https://github.com/mercari/tfnotify/blob/master/terraform/parser.go#L101-L113
outputsだけを追加したときの出力
しかし、リソースを変更せずにoutputsだけを追加した場合、下記のような出力になります。
pagerduty_schedule.secondary: Refreshing state... pagerduty_schedule.primary: Refreshing state... pagerduty_team_membership.team[0]: Refreshing state... pagerduty_team_membership.team[1]: Refreshing state... pagerduty_escalation_policy.team: Refreshing state... pagerduty_service.team: Refreshing state... pagerduty_service_integration.datadog: Refreshing state... ------------------------------------------------------------------------ Changes to Outputs: + my_another_project_name = "my-another-project" ------------------------------------------------------------------------
outputsの変更のみが出力されていますね。
リソースの変更がないため Plan: は出力されません。さらに、まったく変更がない(outputsを変更している)ため、No changes. も出力されません。
その結果、tfnotifyの正規表現にマッチせず、パースエラーとしてterraform planは成功するけれどtfnotifyで失敗するということになります。
対応策
今回のoutputsはremote stateから読み込んで外部で使いたいものだったので、outputsとそれを使うリソース定義を同時に行うということができませんでした。
また、terraform planとtfnotifyをCIで実行していたので無理やりマージするのは抵抗があり、雑ですがサービスに影響しない変更を加え、無理やりPlanが結果に出るようにしました。
基本的にはoutputsはリソースの定義と一緒に追加してしまうのがいいかもしれません。
まとめ
下記のことが原因で、outputsだけを追加してterraform planするとtfnotifyがパースエラーになってしまうということが起きました。 1. tfnotifyは正規表現でパースしている 2. outputsだけを追加したterraform planの出力は正規表現にマッチしない 3. パースエラーとして処理される
対応としては、極力outputsはリソースの変更と一緒に追加したほうがよさそうです。
また、issueを投げてみました。時間があるときにPRを投げられるといいなと思います。 github.com