この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
ウィスキー、シガー、パイプをこよなく愛する大栗です。
CloudFormationで環境を構築することが多いのですが、EC2にミドルウェアを設定する時に環境固有の情報をパラメータから入力します。しかし日本語のようなマルチバイト文字を入力すると全て『?』と表示されてしまうので、環境を構築した後に個別に設定しており面倒でした。
最近CFnで日本語を入力する方法がわかったので紹介します。
ASCII文字に変換して入力する
結論として、マルチバイト文字を入力する方法はありませんでした。EC2のUserDataやMetadataへ流し込む時にマルチバイトが文字化けしてしまいます。
その代わり一旦ASCII文字に変換すれば、ASCII文字を入力することになるので使用できることがわかりました。CloudFormationで使用できる組み込み関数の中でASCII文字に変換できるのはFn::Base64です。Fn::Base64
を使用してBase64エンコーディングしてASCII文字として入力します。
具体的な記述方法
ダメな例
以下のようなCloudFormationテンプレートでEC2を1台起動して、入力したパラメータをファイルに出力しています。
CloudFormationテンプレートはYAML形式で記述しています。
AWSTemplateFormatVersion : 2010-09-09
Description : Linux Stack
Parameters :
TempVar1 :
Type : String
Default : PARAMETER
TempVar2 :
Type : String
Default : PARAMETER
KeyPairName :
Type : String
Default : KeyPairName
Resources :
Server01 :
Type : AWS::EC2::Instance
Properties :
ImageId : ami-374db956
InstanceType : t2.small
KeyName : !Ref KeyPairName
UserData :
Fn::Base64 : !Sub |
#!/bin/bash
/opt/aws/bin/cfn-init -s ${AWS::StackId} -r Server01 -c sample --region ${AWS::Region}
Metadata :
AWS::CloudFormation::Init :
configSets :
sample :
- execute
execute :
files :
/tmp/cfn-output.sh :
content : !Sub |
VAR1=${TempVar1}
VAR2=${TempVar2}
echo $VAR1 > /tmp/var1.txt
echo $VAR2 >> /tmp/var1.txt
mode : "000755"
commands :
a-write-output-file :
command : /tmp/cfn-output.sh
以下のように入力します。
項目名 | 入力値 |
---|---|
KeyPairName | (各環境のキーペア) |
TempVar1 | クラスメソッド株式会社 |
TempVar2 | 大栗 |
起動したインスタンスの中身を確認します。
作成したスクリプトは以下のように文字化けしています。
$ cat /tmp/cfn-output.sh
VAR1=???????????
VAR2=??
echo $VAR1 > /tmp/var1.txt
echo $VAR2 >> /tmp/var1.txt
実行結果も当然文字化けしています。
$ cat /tmp/var1.txt
???????????
??
修正した例
スクリプト部分を以下のように書き換えます。
!Sub
の第一引数にスクリプトの内容を記述します。ここで新しい変数である${MyVar1}
と${MyVar2}
を使用しています。base64 -d
でBase64デコードした結果をVAR1
とVAR2
に格納しています。
!Sub
の第二引数では、第一引数で使用した引数を定義します。MyVar1
はTempVar1
をBase64エンコードした内容、MyVar2
はTempVar1
をBase64エンコードした内容として定義します。
/tmp/cfn-output.sh :
content : !Sub
- |
VAR1=$(echo ${MyVar1} | base64 -d)
VAR2=$(echo ${MyVar2} | base64 -d)
echo $VAR1 > /tmp/var1.txt
echo $VAR2 >> /tmp/var1.txt
- MyVar1: {"Fn::Base64": !Ref TempVar1}
MyVar2: {"Fn::Base64": !Ref TempVar2}
このテンプレートを実行すると、スクリプトは以下になります。
$ cat /tmp/cfn-output.sh
VAR1=$(echo 44Kv44Op44K544Oh44K944OD44OJ5qCq5byP5Lya56S+ | base64 -d)
VAR2=$(echo 5aSn5qCX | base64 -d)
echo $VAR1 > /tmp/var1.txt
echo $VAR2 >> /tmp/var1.txt
出力結果では、日本語が表示できています。
$ cat /tmp/var1.txt
クラスメソッド株式会社
大栗
さいごに
いかがでしょうか。Fn::Sub
を使ってスクリプト部分とCloudFormation側の変数定義が分離できるので、可読性が高いスッキリした記述となります。
CloudFormationのYAML対応を機にCloudFormationでインフラ環境のコード化を使用している方もいるようなので、参考になれば幸いです。