AWSがGitHubで公開しているCloudFormationの変換ツールを使ってみた

2017.03.10

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは、中山です。

先日AWSがGitHub上に開設しているアカウントを見ていたのですが、便利そうなツールを発見したので本エントリでご紹介したいと思います。aws-cfn-template-flipというCloudFormation(以下CFn)をJSON/YAML間で変換するツールです。READMEに分かりやすい説明が記載されているので以下に引用します。

AWS CloudFormation Template Flip is a tool that converts AWS CloudFormation templates between JSON and YAML formats, making use of the YAML format’s short function syntax where possible.The term "Flip" is inspired by the well-known Unix command-line tool flip which converts text files between Unix, Mac, and MS-DOS formats.

以前弊社のエントリでRubyのワンライナーを利用したJSON/YAML間の変換方法をご紹介しました。

これはこれでとても便利なのですが、単純に変換しているだけなのでCFnの短縮表記まで変換することはできません。また、AWSが公開しているツールという点も何となく安心できるポイントだと思います。基本的にコマンドラインから利用することが多いと思いますが、モジュールとしても利用可能なので、PythonからCFnテンプレートを生成しているようなケースでも使えます。

なお、本エントリを執筆する上で検証に利用した主要な各種ツールのバージョンは以下の通りです。バージョンによって結果が変更される可能性があるので、その点ご了承ください。

  • aws-cfn-template-flip: 0.2.1

使ってみる

インストールは簡単です。 pip コマンドでインストールするだけです。

$ pip install cfn_flip

インストールが完了すると cfn-flip というコマンドが利用できます。 -h オプションでヘルプが表示されます。

$ cfn-flip -h
usage: cfn-flip [-h] [-c] [input] [output]

AWS CloudFormation Template Flip is a tool that converts AWS CloudFormation
templates between JSON and YAML formats, making use of the YAML format's short
function syntax where possible.

positional arguments:
  input        File to read from. If you do not supply a file, input will be
               read from stdin.
  output       File to write to. If you do not supply a file, output will be
               written to stdout.

optional arguments:
  -h, --help   show this help message and exit
  -c, --clean  Performs some opinionated cleanup on your template. For now,
               this just converts uses of Fn::Join to Fn::Sub.

リポジトリにテスト用のCFnテンプレートが用意されているので、それを利用して試してみましょう。まずはJSONからYAMLに変換してみます。元となるJSONは以下の通りです。

  • examples/clean.json
{
    "Description": "Test",
    "Foo": {
        "Fn::Sub": "The ${cake} is a lie"
    },
    "Bar": {
        "Fn::Base64": {
            "Ref": "Binary"
        }
    }
}

対象ファイルの読み込み方法や出力方法は複数用意されています。

# 標準入力から対象ファイルを読み込み
$ cat examples/clean.json | cfn-flip
Description: Test
Foo: !Sub 'The ${cake} is a lie'
Bar: !Base64
  Ref: Binary
# 引数で対象ファイルを読み込み
$ cfn-flip examples/clean.json
Description: Test
Foo: !Sub 'The ${cake} is a lie'
Bar: !Base64
  Ref: Binary
# 別ファイルに出力
$ cfn-flip examples/clean.json clean.yml && cat clean.yml
Description: Test
Foo: !Sub 'The ${cake} is a lie'
Bar: !Base64
  Ref: Binary

-c オプションを指定すると現時点(2017/03/10)ではFn::Join関数Fn::Sub関数に変換してくれます。一部 Fn::Sub が対応していない場合などがあるのですが、 Fn::Join より可読性が高いので基本的にこのオプションを使った方がよいかと思います。 Fn::Join を含んだCFnテンプレートも用意してくれているのでそれを使って結果を確認してみます。元となるファイルは以下です。

  • examples/test.json
{
    "Description": "Test",
    "Foo": {
        "Fn::Join": [
            " ",
            [
                "The",
                {
                    "Ref": "cake"
                },
                "is",
                "a",
                "lie"
            ]
        ]
    },
    "Bar": {
        "Fn::Base64": {
            "Ref": "Binary"
        }
    }
}

結果は以下のようになります。最高ですね。

$ cfn-flip -c examples/test.json
Description: Test
Foo: !Sub 'The ${cake} is a lie'
Bar: !Base64
  Ref: Binary

Pythonモジュールとして利用する場合は以下のように使えます。コマンドラインと基本的に同じ感覚で利用可能です。

# メソッドのインポート
In [1]: from cfn_flip import flip, to_yaml, to_json
# JSONファイルを読み込むと自動でYAMLに変換してくれる
In [2]: with open('examples/clean.json') as f:
   ...:     clean_yaml = flip(f.read())
   ...:

In [3]: clean_yaml
Out[3]: "Description: Test\nFoo: !Sub 'The ${cake} is a lie'\nBar: !Base64\n  Ref: Binary\n"
# YAMLからJSONへの変換
In [4]: to_json(clean_yaml)
Out[4]: '{\n    "Description": "Test", \n    "Foo": {\n        "Fn::Sub": "The ${cake} is a lie"\n    }, \n    "Bar": {\n        "Fn::Base64": {\n            "Ref": "Binary"\n        }\n    }\n}'
# JSONからYAMLへの変換
In [5]: to_yaml(to_json(clean_yaml))
Out[5]: "Description: Test\nFoo: !Sub 'The ${cake} is a lie'\nBar: !Base64\n  Ref: Binary\n"
# clean_up=Trueにすると-cオプションと同等の処理をしてくれる
In [6]: with open('examples/test.json') as f:
   ...:     print(to_yaml(f.read(), clean_up=True))
   ...:
Description: Test
Foo: !Sub 'The ${cake} is a lie'
Bar: !Base64
  Ref: Binary

まとめ

いかがだったでしょうか。

AWSが公開しているCFn変換ツールをご紹介しました。CFnのYAML対応は比較的最近です。既存プロジェクトではJSON業に励んでいた方も多いかと思いますが、このツールを利用することで簡単にYAMLへ変換できそうですね。

本エントリがみなさんの参考になれば幸いに思います。