この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんばんは。shoitoです。
ラスベガスは日本と-17時間の時差があるので、まだ火曜夜です。
昨日、こちらのセッションに参加して、AdvancedなCloudFormationの使い方について聞きました。
[レポート]上級者への道: Advanced Infrastructure as Code Programming on AWS #reinvent #DEV327
上記セッションで紹介されていた「troposphere - Python library to create AWS CloudFormation descriptions」を弊社中山が紹介しました。
re:Invent 2018のセッションで紹介されてたtroposphereをさわってみた(CloudFormationをもっと便利に) #reinvent
今回はそれに被せるように「GoFormation - Go library for working with CloudFormation templates」を紹介します。
GoFormationって何?
AWS CloudFormationとAWS Serverless Application Model(SAM)のテンプレートを操作するためのGo言語ライブラリです。
できることとしては以下の2つです。
- テンプレートをGoの構造体で記述して、テンプレートのJSON/YAMLへ変換
- 逆にテンプレートを解析し、Goの構造体へ変換
ではさっそく試してみましょう
Goのライブラリなので go get
コマンドでインストールします。
$ go get github.com/awslabs/goformation
まずはGoからJSON/YAMLへの変換
ソースコードはaws/goformationのexample/go-to-yaml/main.go を使います。
※ コメントは日本語の説明に書き換えています。
package main
import (
"fmt"
"strconv"
"time"
"github.com/awslabs/goformation/cloudformation"
)
func main() {
// CloudFormationテンプレートオブジェクトを生成する
template := cloudformation.NewTemplate()
// 現在時刻をベースにユニークな名前のSNSトピックを生成する
template.Resources["MyTopic"] = &cloudformation.AWSSNSTopic{
TopicName: "my-topic-" + strconv.FormatInt(time.Now().Unix(), 10),
}
// Eメールに通知するSNSサブスクリプションを生成する
template.Resources["MyTopicSubscription"] = &cloudformation.AWSSNSSubscription{
TopicArn: cloudformation.Ref("MyTopic"),
Protocol: "email",
Endpoint: "some.email@example.com",
}
// JSON形式でテンプレートを出力する
j, err := template.JSON()
if err != nil {
fmt.Printf("Failed to generate JSON: %s\n", err)
} else {
fmt.Printf("%s\n", string(j))
}
// YAML形式でテンプレート出力する
y, err := template.YAML()
if err != nil {
fmt.Printf("Failed to generate YAML: %s\n", err)
} else {
fmt.Printf("%s\n", string(y))
}
}
適当なディレクトリで上記ソースコードを main.go
ファイルとして作り、 go run
で実行すると、以下のようにJSONとYAMLでそれぞれテンプレートが出力されます。
Go言語を自由に使えるので、柔軟にCloudFormation/SAMテンプレートを生成できそうです。
$ vi main.go
$ go run main.go
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"MyTopic": {
"Properties": {
"TopicName": "my-topic-1543385240"
},
"Type": "AWS::SNS::Topic"
},
"MyTopicSubscription": {
"Properties": {
"Endpoint": "some.email@example.com",
"Protocol": "email",
"TopicArn": {
"Ref": "MyTopic"
}
},
"Type": "AWS::SNS::Subscription"
}
}
}
AWSTemplateFormatVersion: 2010-09-09
Resources:
MyTopic:
Properties:
TopicName: my-topic-1543385240
Type: AWS::SNS::Topic
MyTopicSubscription:
Properties:
Endpoint: some.email@example.com
Protocol: email
TopicArn:
Ref: MyTopic
Type: AWS::SNS::Subscription
逆にYAMLからGo構造体への変換
ソースコードはaws/goformationのexample/yaml-to-go/template.yaml とexample/yaml-to-go/main.goを使います。
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31
- AWS::CodeStar
Parameters:
ProjectId:
Type: String
Description: AWS CodeStar projectID used to associate new resources to team members
Resources:
GetHelloWorld:
Type: AWS::Serverless::Function
Properties:
Handler: index.get
Runtime: nodejs6.10
Role:
Fn::ImportValue:
!Join ['-', [!Ref 'ProjectId', !Ref 'AWS::Region', 'LambdaTrustRole']]
Events:
GetEvent:
Type: Api
Properties:
Path: /
Method: get
package main
import (
"log"
"github.com/awslabs/goformation"
)
func main() {
// JSONかYAML形式のテンプレートをオープンし、パースする
template, err := goformation.Open("template.yaml")
if err != nil {
log.Fatalf("There was an error processing the template: %s", err)
}
// 特定の型の全リソースを取得できる
// ここではサーバレスファンクションリソース
// https://github.com/awslabs/goformation/blob/master/cloudformation/aws-serverless-function.go#L187
// 他にはtemplate.GetAllAWSLambdaFunctionResources()などがある
// https://github.com/awslabs/goformation/blob/master/cloudformation/aws-lambda-function.go
functions := template.GetAllAWSServerlessFunctionResources()
for name, function := range functions {
// 例として Found a AWS::Serverless::Function named GetHelloWorld (runtime: nodejs6.10) が出力される
log.Printf("Found a %s named %s (runtime: %s)\n", function.AWSCloudFormationType(), name, function.Runtime)
}
// AWS CloudFormationリソースの論理名を指定して検索できる
search := "GetHelloWorld"
function, err := template.GetAWSServerlessFunctionWithName(search)
if err != nil {
log.Fatalf("Function not found")
}
// 例として Found a AWS::Serverless::Function named GetHelloWorld (runtime: nodejs6.10) が出力される
log.Printf("Found a %s named %s (runtime: %s)\n", function.AWSCloudFormationType(), search, function.Runtime)
}
また同じように、適当なディレクトリで上記YAMLを template.yaml
ファイルとして、Goのソースコードを main.go
ファイルとして作り、 go run
で実行すると、テンプレートのYAMLを解析し、以下のようにメッセージが表示されます。
$ vi template.yaml
$ vi main.go
$ go run main.go
2018/11/27 22:22:44 Found a AWS::Serverless::Function named GetHelloWorld (runtime: nodejs6.10)
2018/11/27 22:22:44 Found a AWS::Serverless::Function named GetHelloWorld (runtime: nodejs6.10)
上記のmain.go
からAWS::Serverless::Function
をGoのstrongly-typed resourceとして操作できることが分かります。
さいごに
Python用のライブラリであるtroposphereと合わせて見て、Go用のGoFormationはいかがでしたでしょうか?
CloudFormation/SAMのテンプレートを柔軟に生成したり、テンプレートを解析するプログラムを作りたいときに便利そうです。