tech.guitarrapc.cóm

Technical updates

pulumi up 時の文字化け対策

この記事は、Pulumi dotnet Advent Calendar 2019 の19日目です。

qiita.com

そろそろどうやるか見てみましょう。 と思ったのですが、日本語OS上では解決方法が見つからないのでゆるぼ。

目次

TL;DR

現状日本語 Windows では 打つ手なさそう

Summary

pulumi up をすると、dotnet コマンド処理が文字化ける。

cmd/powershell/pwsh のいずれでも発生。

.NET Core ���� Microsoft (R) Build Engine �o�[�W���� 16.3

出力というよりこっちの文字化けをどう対応するか

NOTE: だめな方法

CodePagesEncodingProvider

よく、出力文字列に関しては Encoding の違いということで次の対応がとられる。

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

しかしこれでは、dotnet コマンドの文字化けは解消しない。

chcp

dotnet build がdotnet exec を介しているなら、ということでdotnet 出力が utf-8 であるという前提でコンソールの文字エンコーディングを utf-8にして合わせてみる。

ようはこれ。

.NET Core task outputs garbled characters in build log on non EN-US environments. · Issue #1344 · microsoft/azure-pipelines-agent

Visual Studio Codeタスクのdotnetコマンド出力を文字化けしないようにする - Qiita

この方法で取られるのが、コンソール文字列のエンコーディングを chcp 65001 で utf-8 にしてみる。

が、ダメ。

dotnet の言語を変えるようにしてみる

MSBuild should respect upstream tool language requests · Issue #1596 · microsoft/msbuild · GitHub

set DOTNET_CLI_UI_LANGUAGE=en
set VSLANG=1033

だめ。

推察

dotnet は単純に実行するとコンソールに合わせて文字化けしない。つまり shift-jis で出力している。

が、pulumi up 時に dotnet の出力を食ってはいているので、ここが utf-8 を前提にしている可能性がある。

pulumi/up.go at master · pulumi/pulumi

dotnet > Go > Console の間のエンコーディングっぽいので、現時点では英語OS でという身もふたもない結果になりそう。

REF

.NET Core task outputs garbled characters in build log on non EN-US environments. · Issue #1344 · microsoft/azure-pipelines-agent

Pulumi のプラグインを確認する

この記事は、Pulumi dotnet Advent Calendar 2019 の18日目です。

qiita.com

Pulumi の各プロバイダの実装は Plugin として提供されています。 このプラグインを確認する方法を見てみましょう。

目次

TL;DR

  • Issue 報告などで Pulumi Version や Plugin バージョンを添えると圧倒的に手早い
  • pulumi plugin ls でpluginが確認ができる
  • .NET (C#) では NuGet で管理されている

Pluginの確認

Plugin は、aws とか azure のように、どこの操作をするかのグループ。

pulumi plugin でプラグインの操作ができる。

$ pulumi plugin ls

NAME  KIND      VERSION  SIZE    INSTALLED   LAST USED
aws   resource  1.8.0    220 MB  6 days ago  6 days ago

TOTAL plugin cache size: 220 MB

GitHub

Plugin は、pulumi-xxxx という名前で GitHub 上でオープンに開発されている。

例えば、Awsプラグインなら、pulumi/pulumi-aws

.NET 実装では NuGet で参照される

Pulumi が生成する Infra.csproj を見ると Pulumi の Nuget が入っている。

  <ItemGroup>
    <PackageReference Include="Pulumi.Aws" Version="1.10.0-preview" />
    <PackageReference Include="Pulumi" Version="1.6.0-preview" />
  </ItemGroup>

多くの場合、Pulumi nuget は Pulumi.Aws など実際に使っているプロバイダの依存バージョンで暗黙的に利用されている。 しかし、Pulumi Nuget で修正されていて明示的に取得する必要があることがある。

Pulumi.Aws.Invokes.GetCallerIdentity throws System.NullReferenceException · Issue #801 · pulumi/pulumi-aws

この場合は、プロジェクトの NuGet 管理から PulumiPulumi.Aws NuGet を更新する。

Plugin の元ネタ

基本的に、Terraform をベースに書く言語実装が出力されている。

そのため、Plugin の挙動でもしよくわからないことがあったら、Terraform のリソースでそのパラメーターが受け付けられているかなどを確認すると動作したりもシエル。

バージョン履歴を見ると、現在どのバージョンの Terraform Provider をベースにしているかがわかる。

https://github.com/pulumi/pulumi-aws/blob/a113b17652528591ccee845ea27058de57265066/CHANGELOG.md#190-2019-11-16

Pulumi で他のstate 参照を行う

この記事は、Pulumi dotnet Advent Calendar 2019 の17日目です。

qiita.com

Pulumi のTIPS を見ていきましょう。

Terraform の Remote State に相当する処理を見てみます。 Pulumiで 他のStack で管理しているリソースは参照できるのでしょうか?

目次

TL;DR

  • 現状 Stack の参照は C# 実装では提供されていない
  • Provider を分けて持つことはできるので、Provider でリソースを参照して使うことで回避できる
  • TypeScript などGAされた言語では Stack Reference として提供されている

Stack Reference

TypeScript で次のように書いて、他の Stack の Output を参照できる。

import * as pulumi from "@pulumi/pulumi";
const other = new pulumi.StackReference("acmecorp/infra/other");
const otherOutput = other.getOutput("x")

これは dotnet (C#) ではまだサポートされいない。

そのため、もしほかの Stack を参照したい場合、Stack を直接みるのではなく、そのStack の Providerを別途用意して参照するしかない。

using Pulumi;
using Pulumi.Aws;

class Program
{
   async Task Main() =>
       Deployment.Run(() =>
       {
           // Create an AWS provider for the us-east-1 region.
           var useast1 = new Provider("useast1", new ProviderArgs { Region = "us-east-1" });

           // Create an ACM certificate in us-east-1.
           var cert = new Aws.Acm.Certificate("cert", new Aws.Acm.CertifiateArgs
           {
               DomainName = "foo.com",
               ValidationMethod = "EMAIL",
           }, new ResourceArgs { Provider = useast1 });
       });
}

イメージ的には、terraform の provider による管理に近い。

1つの terraform で複数 AWS Account をまとめて構築・管理する - エムスリーテックブログ

REF

Inter-Stack Dependencies | Organizing Projects and Stacks | Pulumi

Pulumi の state を Export したり Importする

この記事は、Pulumi dotnet Advent Calendar 2019 の16日目です。

qiita.com

Pulumi を WebUI でProject/Stack 配下で管理するということは、ほかの Project/Stack に移動したいときに何か操作がいりそうですね。 それをどうするのか見てみましょう。

この記事の内容までで概ね、完全に理解した()といいたくなるのではないでしょうか。

目次

TL;DR

  • Pulumi は state をExport することで他の Pulumi Project に取り込むための json を取得できる
  • Exportされた json を取り込むときは Import を使う

Summary

State をほかの Pulumi Project で利用することが考えられる。 普段はまず意識する機会が少ないだろうが動作を確認しておく。

terraform でいうところの tfstate をほかの backend で管理するときの操作に相当する。

export

pulumi の Stack にある state を出力する。Pulumi のプロジェクトがあるパスでないと動作しないので注意。

pulumi stack export > stack.json

例えば空のスタックは次の state になっている。

{
    "version": 3,
    "deployment": {
        "manifest": {
            "time": "2019-11-20T12:45:40.5026846+09:00",
            "magic": "1d5f3b62e78892f89b30a2cc29a7eee340fe39a0f777515c72079024e9b448a6",
            "version": "v1.5.2"
        },
        "secrets_providers": {
            "type": "service",
            "state": {
                "url": "https://api.pulumi.com",
                "owner": "guitarrapc",
                "project": "pulumi",
                "stack": "dev"
            }
        }
    }
}

Import

標準出力からpulumiの Stack に State をインポートする。

pulumi stack import < stack.json

どこかの Stack を丸っと別の Pulumi アカウントにお引越しするときなどに便利。

Pulumi でstateから特定のリソースを消す

この記事は、Pulumi dotnet Advent Calendar 2019 の15日目です。

qiita.com

Pulumi の State から特定のリソースだけ管理対象外にしたい、そんなことはきっと起こります。 どのようにやればいいのか見てみましょう。

目次

TL;DR

  • pulumi state rm '<URN>' で消せる
  • URN には、$xxxx が混じるので、シングルクォートで囲っておくと安全。リソース名に$% のような特殊文字は使わないほうがよさそう
  • URN は pulumi stack --show-urns で表示できるので、pulumi stack --show-urns | grep xxxx にすると楽

想定ケース

pulumi で、Route53 を ComponentResource を使わずに組んでいた。

private Zone CreateRoute53Resource(string name, string zoneName, Dictionary<string, object> tags)
{
    var zone = new Zone($"{name}-zone-{zoneName}", new Pulumi.Aws.Route53.ZoneArgs
    {
        Name = zoneName,
        Tags = tags,
    }, new CustomResourceOptions { Parent = this });
    return zone;
}

これをグルーピングしたいので、ComponentResource で組むようにしたい。 早速書いてみて、CreateRoute53Resource は不要なので削除して pulumi up すると次のような実行プランになった。

     Type                       Name                                                    Plan
     pulumi:pulumi:Stack        pulumi-dev
     └─ pkg:EksClusterResource  sandbox
 +      ├─ pkg:Route53Resource  sandbox-route53                                         create
 +      │  └─ aws:route53:Zone  sandbox-route53-zone-eks-sandbox-pulumi.my.exmple.com  create
 -      └─ aws:route53:Zone     sandbox-route53-zone-eks-sandbox-pulumi.my.exmple.com  delete

delete になっているのが、もともとあったリソース定義である CreateRoute53Resource 部分。

ここを消さないようにしたい。 (既存のリソースを取り込むのは Pulumi で既存のリソースを取り込む | kinoco Kibela 参照)

対応方法

pulumi の state は pulumi state で操作できる。特定のリソースのstate を消すなら次のコマンドになる。

pulumi state rm <URN>

この時、pulumi のリソースごとに振られた一意のID、URN が必要になる。 URN は、pulumi stack --show-urns で一覧表示できる。

$ pulumi stack --show-urns

Current stack is dev:
    Owner: guitarrapc
    Last updated: 15 minutes ago (2019-11-19 11:21:31.7024525 +0900 JST)
    Pulumi version: v1.5.2
Current stack resources (51):
    TYPE                                                                     NAME
    pulumi:pulumi:Stack
       └─ aws:route53/zone:Zone                                              sandbox-route53-zone-eks-sandbox-pulumi.my.exmple.com
             URN: urn:pulumi:dev::pulumi::pkg:MyResource$aws:route53/zone:Zone::sandbox-route53-zone-eks-sandbox-pulumi.my.exmple.com

この例のように、リソース名とURN はセットになっているので、リソース名がわかるならそれで grep すれば結果は絞り込める。

$ pulumi stack --show-urns | grep eks-sandbox-pulumi.my.exmple.com

URN が特定できたら、pulumi state rm で削除すればok。 注意点として、URN に $ が混じっているため、シェルによっては変数扱いされたりする。そういった場合に備えて シングルクォート' で括るほうがいいだろう。

pulumi state delete 'urn:pulumi:dev::pulumi::pkg:MyResource$aws:route53/zone:Zone::sandbox-route53-zone-eks-sandbox-pulumi.my.exmple.com'

この状態で pulumi up してみると、先ほどあった delete はなくなっている。

     Type                       Name                                                    Plan
     pulumi:pulumi:Stack        pulumi-dev
     └─ pkg:EksClusterResource  sandbox
 +      └─ pkg:Route53Resource  sandbox-route53                                         create
 +         └─ aws:route53:Zone  sandbox-route53-zone-eks-sandbox-pulumi.my.exmple.com  create

REF

pulumi stack rm