CloudFormationをもっと便利にするGo言語用ライブラリ – GoFormationをさわってみた #reinvent
こんばんは。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のテンプレートを柔軟に生成したり、テンプレートを解析するプログラムを作りたいときに便利そうです。