この記事は、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祭りになるのはちょっと辛いですが。