✍️

AWS Application Composer触ってみた!

2022/12/09に公開

はじめに

先日行われたAWS re:Invent 2022 にて、
AWS Application Composerがプレビューとして発表されました!
第一印象で非常に便利そうだと感じたため、
実際に触って確かめていきたいと思います!
https://reinvent.awsevents.com/

AWS Application Composerとは

AWS Application Composer(以下Application Composer)は、
サーバーレスアプリケーションのためのビジュアル開発ツールです。
GUI上でドラッグ&ドロップしながらAWSの様々なサービスを繋げていくことで、
簡単にサーバーレスアプリケーションの構成を作ることができます。
https://docs.aws.amazon.com/application-composer/latest/dg/what-is-composer.html

なにができるか

Application Composerでは、主に下記3つのことを行うことができます。

  • GUI上でのサーバーレスアプリケーションの構成図作成
  • 既存のテンプレートを読み込み、GUIで表示
  • 作成した構成図をVSCodeなどと連携し、IaCのコードとして出力

つまり、今までであれば
draw.ioなどで構成図を作成
②構成図を見ながら、CloudFormationやSAMテンプレートなどのIaCのコードを記述
という流れで作成していたものを、
Application Composerで構成図を作成するだけで、コードの出力まで行ってくれるようになります。
さらに、コードは変更を行うごとにローカルのVSCodeに反映することもできるため、
非常に直感的にわかりやすくなっています。
(めちゃくちゃ便利、、!)


やってみた

何はともあれ触ってみたいと思います。
Application Composerでは、 File System Access APIを使うため、
Google ChromeMicrosoft Edgeを使ってねとのことです。
※後述するconnected mode を使わない場合は、上記のブラウザでなくでも問題ないです

You can access Application Composer through any modern web browser. For the best experience, we recommend using Google Chrome or Microsoft Edge, which both support Application Composer's connected mode. This mode requires a browser that supports the File System Access API, which allows web applications to read, write, and save files in your local file system. For more information about connected mode and the browsers that support it, see Connected mode reference.

https://docs.aws.amazon.com/application-composer/latest/dg/setting-up-composer.html#:~:text=You can access,mode reference
https://developer.mozilla.org/ja/docs/Web/API/FileSystem

キャンバスの作成

まずは、AWSコンソールから Application Composer を検索します。

右上の「Create project」から新規のプロジェクトを作成していきます。

プロジェクトを作成すると、下記のようなモーダルが表示されます。
下の方にConnected Unconnectedという2つのモードがあり、
それぞれ

  • Connectedモード: ローカルのファイルと同期し、自動的にファイルを更新する
  • Unconnectedモード: ローカルのファイルとは同期せず、手動でファイルをエクスポートする
    モードとなっています。
    今回はConnectedモードを試してみたいと思います。

左下の「Select folder」より、Application Composerと同期する、空のフォルダーを選択していきます。

ポップアップでパーミッションを許可して、満を辞して「Create」(ワクワク、、!)

もう一個ポップアップが出たので「Save changes」をクリック

Application Composerを編集するキャンバスの作成ができました。
ここに左側のアイコンをポチポチして編集していきます。

また、ローカルにはtemplate.yaml というファイルが作成されています。

Application Composerの編集

では早速編集していきます。
手始めにAPI Gatewayを置いていきます。

ダブルクリックすると右側のパネルからプロパティを設定することができます。
作成するAPI GatewayのパスやHTTPメソッドなども指定できます。(すげぇ〜!)

上側の「Template」をクリックすると、現状のコードを確認することができます。

そしてなんと、ローカルのtemplate.yamlを開いてみると、同じ内容のコードが出力されています!(す、すげぇ!)

ちなみに、デフォルトの状態だと!Sub などに警告が表示されるため、
下記の記事を参考にsettings.json を編集しています。
https://qiita.com/yoskeoka/items/6528571a45cd69f93deb

続いて、Lambdaもいくつか配置して、API Gatewayと接続していきます。
まず、API GatewayのMenuを開き、「Add route」よりパスを追加していきます。
今回は既にGetがあるので、Post、Put、Deleteの3つを追加し、「Save」を押します。

続いてLambdaを配置し、先ほど追加したパスと接続していきます。
(複数選択した状態で「Arrange」を押すと、整列できます。)

Lambdaの関数名やランタイム、タイムアウトなどもこの画面から編集することができます。
一つの画面で複数Lambdaの設定をできるのは便利ですね

最後にDynamoDBを追加します。
こちらもPartition keyやSort keyを指定できます。
(この画面からその他の任意の属性を追加することはできなそうです)

LambdaとDynamoDBを接続して完了です!
最終的には下記のような構成になりました。

出力されたコードは下記の通りです。
結構行数ありますね、、
これを自力で書く場合(私の場合は)そこそこ時間かかりそうですが、
ポチポチしていくだけで作れてしまうため、かなり時間短縮することができました。

template.yaml
Transform: AWS::Serverless-2016-10-31
Resources:
  Api:
    Type: AWS::Serverless::Api
    Properties:
      Name: !Sub
        - ${ResourceName} From Stack ${AWS::StackName}
        - ResourceName: Api
      StageName: Prod
      DefinitionBody:
        openapi: '3.0'
        info: {}
        paths:
          /:
            get:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetTodoFunction.Arn}/invocations
              responses: {}
            post:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PostTodoFunction.Arn}/invocations
              responses: {}
            put:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UpdateTodoFunction.Arn}/invocations
              responses: {}
            delete:
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DeleteTodoFunction.Arn}/invocations
              responses: {}
      EndpointConfiguration: REGIONAL
      TracingEnabled: true
  GetTodoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: GetTodoFunction
      CodeUri: src/GetTodoFunction
      Handler: handler.handler
      Runtime: python3.9
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        ApiGET:
          Type: Api
          Properties:
            Path: /
            Method: GET
            RestApiId: !Ref Api
      Environment:
        Variables:
          TABLE_NAME: !Ref DemoTodoTable
          TABLE_ARN: !GetAtt DemoTodoTable.Arn
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref DemoTodoTable
  GetTodoFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${GetTodoFunction}
  PostTodoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: PostTodoFunction
      CodeUri: src/PostTodoFunction
      Handler: index.handler
      Runtime: python3.9
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        ApiPOST:
          Type: Api
          Properties:
            Path: /
            Method: POST
            RestApiId: !Ref Api
      Environment:
        Variables:
          TABLE_NAME: !Ref DemoTodoTable
          TABLE_ARN: !GetAtt DemoTodoTable.Arn
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref DemoTodoTable
  PostTodoFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${PostTodoFunction}
  UpdateTodoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: UpdateTodoFunction
      CodeUri: src/UpdateTodoFunction
      Handler: index.handler
      Runtime: python3.9
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        ApiPUT:
          Type: Api
          Properties:
            Path: /
            Method: PUT
            RestApiId: !Ref Api
      Environment:
        Variables:
          TABLE_NAME: !Ref DemoTodoTable
          TABLE_ARN: !GetAtt DemoTodoTable.Arn
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref DemoTodoTable
  UpdateTodoFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${UpdateTodoFunction}
  DeleteTodoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Description: !Sub
        - Stack ${AWS::StackName} Function ${ResourceName}
        - ResourceName: DeleteTodoFunction
      CodeUri: src/DeleteTodoFunction
      Handler: index.handler
      Runtime: python3.9
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Events:
        ApiDELETE:
          Type: Api
          Properties:
            Path: /
            Method: DELETE
            RestApiId: !Ref Api
      Environment:
        Variables:
          TABLE_NAME: !Ref DemoTodoTable
          TABLE_ARN: !GetAtt DemoTodoTable.Arn
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref DemoTodoTable
  DeleteTodoFunctionLogGroup:
    Type: AWS::Logs::LogGroup
    DeletionPolicy: Retain
    Properties:
      LogGroupName: !Sub /aws/lambda/${DeleteTodoFunction}
  DemoTodoTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
        - AttributeName: timestamp
          AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: id
          KeyType: HASH
        - AttributeName: timestamp
          KeyType: RANGE
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES

Lambdaのハンドラーも作成されてました

src/GetTodoFunction/handler.py
import json
def handler(event, context):
    # Log the event argument for debugging and for use in local development.
    print(json.dumps(event))

    return {}

SAM CLIからのビルド&デプロイも確認できました

sam build

	SAM CLI now collects telemetry to better understand customer needs.

	You can OPT OUT and disable telemetry collection by setting the
	environment variable SAM_CLI_TELEMETRY=0 in your shell.
	Thanks for your help!

	Learn More: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-telemetry.html

Building codeuri: /Users/xxxxxx/Desktop/demo/src/GetTodoFunction runtime: python3.9 metadata: {} architecture: x86_64 functions: GetTodoFunction
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Building codeuri: /Users/xxxxxx/Desktop/demo/src/PostTodoFunction runtime: python3.9 metadata: {} architecture: x86_64 functions: PostTodoFunction
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Building codeuri: /Users/xxxxxx/Desktop/demo/src/UpdateTodoFunction runtime: python3.9 metadata: {} architecture: x86_64 functions: UpdateTodoFunction
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Building codeuri: /Users/xxxxxx/Desktop/demo/src/DeleteTodoFunction runtime: python3.9 metadata: {} architecture: x86_64 functions: DeleteTodoFunction
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided
sam deploy --guided

Configuring SAM deploy
======================

~ 省略 ~

Successfully created/updated stack - application-composer-demo-20221209 in ap-northeast-1

また、GUI上では表示されていないものの、
下記のサービスなどもテンプレートに組み込むことで使用できるそうです。

  • AWS::ECS::TaskDefinition
  • AWS::CloudFront::Function
  • AWS::CloudFront::Distribution

Hidden resources
Hidden resources are those that can be used to design and build with, but their complete feature set of properties and integrations with other resources may not be supported within Application Composer. Hidden resources are not available from the resource palette but will populate on the canvas when you load an existing template that includes them.
A few examples of hidden resources include:

  • AWS::ECS::TaskDefinition
  • AWS::CloudFront::Function
  • AWS::CloudFront::Distribution

https://docs.aws.amazon.com/application-composer/latest/dg/reference-resources.html#:~:text=AWS%3A%3AServerless%3A%3AStateMachine-,Hidden resources,AWS%3A%3ACloudFront%3A%3ADistribution,-When you load

まとめ

今回はApplication Composerを触ってみました。
⌘ + z がGUIのコンポーネントに対して機能しないなど、若干今後に期待な箇所はありましたが、
全体的に直感的にわかりやすく、使いやすかったです。
また、いくつものAWSサービスを行き来することなく、一つの画面で設定ができることも魅力的でした。

  • 爆速サーバーレス環境の立ち上げ
  • CloudFormationやSAMテンプレートの学習
  • ちょっとしたサンドボックス環境の作成
  • 既存のテンプレートの確認
    など、役立つ場面は多そうですね。

それでは、よきAWSライフを!

参考

https://docs.aws.amazon.com/application-composer/latest/dg/what-is-composer.html
https://dev.classmethod.jp/articles/aws-application-composer/
https://youtu.be/BujE_tik5r8
https://developer.mozilla.org/ja/docs/Web/API/FileSystem

Aidemy Tech Blog

Discussion