この記事は、Pulumi dotnet Advent Calendar 2019 の25日目です。
最終日は、Pulumi でこんなときどうするのかをまとめていきます。
目次
- 目次
- TL;DR
- Pulumi.Aws.Iam.Invokes の Input<T> が Output<T> の依存解決を行えない
- Pulumi-aws の destroy で vpc 削除が何度やっても失敗する
- pulumi up の preview と実行でそれぞれ dotnet build がかかる
- pulumi で作成したリソースに直接変更を加えられてもpulumi が検出しない
- pulumi のリソースをプロジェクト間で移動させたい
- 他プロジェクトのリソースを参照したい
- teraform から pulumi に移行する
TL;DR
Pulumi でトラブルに遭遇したときにどのように回避するかのワークアラウドです。
随時更新予定。
Pulumi.Aws.Iam.Invokes の Input<T>
が Output<T>
の依存解決を行えない
Pulumi の DataSourceは、値が決定的に定まっていることを前提にしているため、 Output<T>
を受けることを想定していません。
つまり以下のコードは失敗します。
using System.Collections.Generic; using System.Threading.Tasks; using Pulumi; using Pulumi.Aws.Iam; using Pulumi.Aws.Iam.Inputs; class Program { static Task<int> Main() { return Deployment.RunAsync(async () => { var policy = await Pulumi.Aws.Iam.Invokes.GetPolicyDocument(new GetPolicyDocumentArgs { Statements = new[] { new GetPolicyDocumentStatementsArgs { Actions = "sts:AssumeRole", Effect = "Allow", Principals = new GetPolicyDocumentStatementsPrincipalsArgs { Type = "Service", Identifiers = "ec2.amazonaws.com", } }, }, }); var role = new Pulumi.Aws.Iam.Role($"role", new RoleArgs { AssumeRolePolicy = policy.Json, }); var assumepolicy = await Pulumi.Aws.Iam.Invokes.GetPolicyDocument(new GetPolicyDocumentArgs { Statements = new[] { new GetPolicyDocumentStatementsArgs { Actions = "sts:AssumeRole", Effect = "Allow", Principals = new GetPolicyDocumentStatementsPrincipalsArgs { Type = "Service", Identifiers = "ec2.amazonaws.com", } }, new GetPolicyDocumentStatementsArgs { Actions = "sts:AssumeRole", Effect = "Allow", Principals = new GetPolicyDocumentStatementsPrincipalsArgs { Type = "AWS", // throws exception here! Identifiers = role.Arn, } } } }); return new Dictionary<string, object> { { "arn", role.Arn }, { "assumepolicy", assumepolicy.Json }, }; }); } }
もし Output<T>
な値を受けて、Data Source の取得を行いたい場合は、Output<T>.Apply
でDataSource を Output
の結果を受けて実行されるようにし、出力も Output<T>
に変換します。
using System.Collections.Generic; using System.Threading.Tasks; using Pulumi; using Pulumi.Aws.Iam; using Pulumi.Aws.Iam.Inputs; class Program { static Task<int> Main() { return Deployment.RunAsync(async () => { var policy = await Pulumi.Aws.Iam.Invokes.GetPolicyDocument(new GetPolicyDocumentArgs { Statements = new[] { new GetPolicyDocumentStatementsArgs { Actions = "sts:AssumeRole", Effect = "Allow", Principals = new GetPolicyDocumentStatementsPrincipalsArgs { Type = "Service", Identifiers = "ec2.amazonaws.com", } }, }, }); var role = new Pulumi.Aws.Iam.Role($"role", new RoleArgs { AssumeRolePolicy = policy.Json, }); var assumepolicy = role.Arn.Apply(roleArn => Pulumi.Aws.Iam.Invokes.GetPolicyDocument(new GetPolicyDocumentArgs { Statements = new[] { new GetPolicyDocumentStatementsArgs { Actions = "sts:AssumeRole", Effect = "Allow", Principals = new GetPolicyDocumentStatementsPrincipalsArgs { Type = "Service", Identifiers = "ec2.amazonaws.com", } }, new GetPolicyDocumentStatementsArgs { Actions = "sts:AssumeRole", Effect = "Allow", Principals = new GetPolicyDocumentStatementsPrincipalsArgs { Type = "AWS", Identifiers = roleArn, } } } })); // you can pass assumepolicy to other Resource. return new Dictionary<string, object> { { "arn", role.Arn }, { "assumepolicy", assumepolicy.Json }, }; }); } }
Pulumi-aws の destroy で vpc 削除が何度やっても失敗する
pulumi destory
をしたときに、vpc の削除がどうしても失敗することがあります。
error: Plan apply failed: deleting urn:pulumi:ekscluster::sandbox::pkg:component:ekscluster$pkg:component:network$aws:ec2/vpc:Vpc::sandbox-network-vpc: Error deleting VPC: DependencyViolation: The vpc 'vpc-052ade5d4667965e8' has dependencies and cannot be deleted.
これは Secutiry Group で、自身の Security Group を参照しているときにおこります。 特に、EKS Cluster などが自動的に作成した Security Groupで、自分自身の Security Group を参照しているときに起こりま す。 Pulumi が知っていれば自分で解消するので、知らない状況を作らないようにするのがいいでしょう。
と思っても、Kubernetes 1.14 + eks.3
以降は、EKS デフォルトの挙動として PulumiなどAPIで指定したセキュリティグループは Addtional Security Groupになり、EKS のデフォルト Security Groupに自身を許可するSGを自分で作るようになった。ので、破綻する...。
pulumi up の preview と実行でそれぞれ dotnet build がかかる
pulumi up
を実行すると、Preview と Up が実行されます。
- preview が実行されプロンプトが表示
yes
を選択するとpreview の内容が適用されます
yes を選択したときの適用は、一見すると preview の内容ですが、実際はC# コードが再度評価されて、再度 dotnet build
が実行されます。
そのため、pulumi up
をして yes を選択する前に Visual Studio 上で Pulumi dotnet のコードを変更すると Preview と違う結果が実行されます。
注意しましょう。
pulumi で作成したリソースに直接変更を加えられてもpulumi が検出しない
pulumi は、デフォルトでは実リソースと自分のStateを同期しません。 そのため、該当リソースにコード変更をしない限り気づけません。
terraform のように、コード変更なしに気づくためには、pulumi refresh
か pulumi up --refresh
を行います。
これによって、Pulumi の State と実リソースの状態が同期されて、コードに変更がなくても差分として検出されるようになります。
pulumi のリソースをプロジェクト間で移動させたい
残念ながらサポートされてません。
Support moving resources between projects · Issue #3389 · pulumi/pulumi
他プロジェクトのリソースを参照したい
terraform の remote state 的なものは、pulumi では StackReference といいますが、C# ではサポートされていません。
TypeScript ではサポートされています。
import * as k8s from "@pulumi/kubernetes"; import * as pulumi from "@pulumi/pulumi"; const env = pulumi.getStack(); const infra = new pulumi.StackReference(`acmecorp/infra/${env}`); const provider = new k8s.Provider("k8s", { kubeconfig: infra.getOutput("kubeConfig") }); const service = new k8s.core.v1.Service(..., { provider: provider });
https://www.pulumi.com/docs/intro/concepts/organizing-stacks-projects/#inter-stack-dependencies
teraform から pulumi に移行する
やる意義があるのならやるのは選択がでるでしょう。
terraform から TypeScript への移行プログラムはあります。
pulumi/tf2pulumi: A tool to convert Terraform projects to Pulumi TypeScript programs
他の言語バインディングは今のところ見つからない。
どのみちImport 祭りになるのはちょっと辛いですが。