troposphereでCloudFormationのテンプレートを作成する。

# はじめに
CloudFormationのテンプレートを作成する[troposphere](https://github.com/cloudtools/troposphere)というライブラリがあるみたいなので使って見ました。


# troposhpereとは？
CloudFormationのテンプレートを作成することができるpythonのライブラリです。
OpenStackについても少しサポートしてるみたいです。
ちなみに _troposphere_ は日本語で「対流圏」という意味だそうです。


# サポートしてるAWSサービス (2018-04-09時点)
現在サポートしてるAWSサービスは以下のようです。

>
AWS::ApiGateway
AWS::ApplicationAutoScaling
AWS::Athena
AWS::AutoScaling
AWS::Batch
AWS::CertificateManager
AWS::Cloud9
AWS::CloudFormation
AWS::CloudFront
AWS::CloudTrail
AWS::CloudWatch
AWS::CodeBuild
AWS::CodeCommit
AWS::CodeDeploy
AWS::CodePipeline
AWS::Cognito
AWS::Config
AWS::DAX
AWS::DMS
AWS::DataPipeline
AWS::DirectoryService
AWS::DynamoDB
AWS::EC2
AWS::ECR
AWS::ECS
AWS::EFS
AWS::EMR
AWS::ElastiCache
AWS::ElasticBeanstalk
AWS::ElasticLoadBalancing
AWS::ElasticLoadBalancingV2
AWS::Elasticsearch
AWS::Events
AWS::GuardDuty
AWS::Glue
AWS::IAM
AWS::Inspector
AWS::IoT
AWS::KMS
AWS::Kinesis
AWS::KinesisAnalytics
AWS::KinesisFirehose
AWS::Lambda
AWS::Logs
AWS::OpsWorks
AWS::RDS
AWS::Redshift
AWS::Route53
AWS::S3
AWS::SDB
AWS::SES
AWS::SNS
AWS::SQS
AWS::SSM
AWS::Serverless
AWS::ServiceDiscovery
AWS::StepFunctions
AWS::WAF
AWS::WAFRegional
AWS::WorkSpaces


# インストール
pipを使ってインストールします。

```bash:インストール
$ pip install troposphere
Collecting troposphere
  Downloading troposphere-2.2.1.tar.gz (115kB)
    100% |████████████████████████████████| 122kB 3.0MB/s 
Collecting cfn_flip>=0.2.5 (from troposphere)
  Downloading cfn_flip-1.0.3.tar.gz
Collecting Click (from cfn_flip>=0.2.5->troposphere)
  Downloading click-6.7-py2.py3-none-any.whl (71kB)
    100% |████████████████████████████████| 71kB 4.4MB/s 
Requirement already satisfied: PyYAML in /Users/kohei/.pyenv/versions/3.6.2/lib/python3.6/site-packages (from cfn_flip>=0.2.5->troposphere)
Requirement already satisfied: six in /Users/kohei/.pyenv/versions/3.6.2/lib/python3.6/site-packages (from cfn_flip>=0.2.5->troposphere)
Installing collected packages: Click, cfn-flip, troposphere
  Running setup.py install for cfn-flip ... done
  Running setup.py install for troposphere ... done
Successfully installed Click-6.7 cfn-flip-1.0.3 troposphere-2.2.1
```


# 作成
今回は例としてインスタンス１台立ち上げるテンプレートを作成します。

```python:json
>>> from troposphere import Ref, Template
>>> import troposphere.ec2 as ec2
>>> t = Template()
>>> instance = ec2.Instance("myinstance")
>>> instance.ImageId = "ami-a77c30c1"
>>> instance.InstanceType = "t1.micro"
>>> t.add_resource(instance)
<troposphere.ec2.Instance object at 0x1057597b8>
>>> print(t.to_json())
{
    "Resources": {
        "myinstance": {
            "Properties": {
                "ImageId": "ami-a77c30c1",
                "InstanceType": "t1.micro"
            },
            "Type": "AWS::EC2::Instance"
        }
    }
}
```

上記はjson形式ですが、yaml形式の場合は以下になります。

```python:yaml
>>> print(t.to_yaml())
Resources:
  myinstance:
    Properties:
      ImageId: ami-a77c30c1
      InstanceType: t1.micro
    Type: AWS::EC2::Instance
```

また、以下のように１つずつではなく、まとめて設定することも可能です。

```python:
>>> from troposphere import Ref, Template
>>> import troposphere.ec2 as ec2
>>> t = Template()
>>> instance = ec2.Instance("myinstance", ImageId="ami-a77c30c1", InstanceType="t1.micro")
>>> t.add_resource(instance)
<troposphere.ec2.Instance object at 0x107c427b8>
>>> print(t.to_yaml())
Resources:
  myinstance:
    Properties:
      ImageId: ami-a77c30c1
      InstanceType: t1.micro
    Type: AWS::EC2::Instance
```

```python:
>>> from troposphere import Ref, Template
>>> import troposphere.ec2 as ec2
>>> t = Template()
>>> instance = t.add_resource(ec2.Instance("myinstance", ImageId="ami-a77c30c1", InstanceType="t1.micro"))
>>> Ref(instance)
<troposphere.Ref object at 0x10b2647f0>
>>> print(t.to_yaml())
Resources:
  myinstance:
    Properties:
      ImageId: ami-a77c30c1
      InstanceType: t1.micro
    Type: AWS::EC2::Instance
```


# 作成
先ほど作成したテンプレートを使って実際にCloudFormationでインスタンスを立ち上げてみます。
作成したテンプレートをテキスト保存し、CloudFormationでテンプレートを **「Amazon S3にアップロード」** から作成します。

![スクリーンショット 2018-04-09 0.32.13.png](https://qiita-image-store.s3.amazonaws.com/0/82090/d8b038d5-1d85-9555-27ef-2970219fc1fd.png)


# エラーチェック
設定が間違った場合はエラーチェックもしてくれます。

```python:
>>> import troposphere.ec2 as ec2
>>> ec2.Instance("ec2instance", image="i-XXXX")
Traceback (most recent call last):
・・・
AttributeError: AWS::EC2::Instance object does not support attribute image
```

```python:
>>> from troposphere import Template
>>> import troposphere.ec2 as ec2
>>> t = Template()
>>> t.add_resource(ec2.Instance("ec2instance", InstanceType="m3.medium"))
<troposphere.ec2.Instance object at 0x110965780>
>>> print(t.to_json())
Traceback (most recent call last):
・・・
ValueError: Resource ImageId required in type AWS::EC2::Instance (title: ec2instance)
```


# おわりに
インスタンス一台だけだとあまり便利さは感じられないですが、規模が大きくなればなるほど便利かもです。