PulumiはStackの解析をして、現在のステートとの差分でどのような処理をするかpreview / upで表示します。 このため、Stackの解析中 (=コードをビルドして実行してStack生成中) に例外が生じたときにどのようにハンドルされるかは重要です。
今回はユーザー側の誤った記述で、Stack解析に例外が起こっても処理が止まらず実行されたのをメモしておきます。
tl;dr;
- sdk/dotnetを利用する場合、Program.Mainの返り値の型は
int
またはTask<int>
にしましょう - Top-level statementならreturnを忘れずに、
return await Deployment.RunAsync<MyStack>();
としましょう
どのような問題なのか
C# でPulumiを記述する場合、多くの場合はStackを継承した自分の定義を用いるでしょう。
pulumi preview
やpulumi apply
でStackを実行中に例外が発生した場合は、pulumi cliはそれを検知して実行を止めなくてはいけません。
pulumiは例外を検知すると、「何もStackの内容を実行せず」例外をターミナルに表示して終了します。
しかしProgram.Mainメソッドの返り値の型をint
あるいはTask<int>
にしていないと、例外が起こってもpulumi cliは実行を継続しようとします。
この状態で例外が起こると、「例外以降のコードで記述されたリソースに削除マーカーを付与」して差分+例外をターミナルに表示して終了します。
// bad public static async Task Main(string[] args) { await Deployment.RunAsync<MyStack>(); } // bad (Top-Level statement) await Deployment.RunAsync<MyStack>();
Issueが作られておりそちらを見ると詳しくわかります。
対処法法は前述のとおり、Mainメソッドの返り値をint
かTask<int>
にしましょう。
// ok public static async Task<int> Main(string[] args) { return await Deployment.RunAsync<MyStack>(); } // ok (Expression-bodied Method) public static async Task<int> Main(string[] args) => await Deployment.RunAsync<MyStack>(); // ok (Top-Level statement) await Deployment.RunAsync<MyStack>();
何がおこったのか
Pulumiは言語のビルドはpulumi cliと切り離されているので、何気に .NET 6でもビルド、実行できたりします。
その際にうかつにも、await Deployment.RunAsync<MyStack>();
とreturnを忘れて書いてしまったために、作成してあったリソースの多くが消えるという目にあったのでした。
// missing return!! await Deployment.RunAsync<MyStack>();
PulumiはGitHub AappあるいはGitHub ActionsでPR差分を表示できるのですが、GitHub Actionsでコメントを書くのを使っていたために、差分が埋もれてしまい気づけなかったという顛末です。
対処はreturn
をつけるだけです。
誰かの役に立つと幸いです。
Pulumi に期待すること
例外起こったらEnvironment.ExitCode = -1
など適切な終了コードをセットしてほしいです。
現在はそういったことをしていないのを、終了コードをMainメソッドで示さないと死ぬので基盤で対処してほしい...。