Amazon Q DeveloperがGAされたのでVisual Studio Codeから使ってみる
今回は2024年4月の終わりにGAとなったAmazon Q Developerを使ってみました。
背景
以前Amazon CodeWhispererからCloudFormationコードの開発を試しましたが、つい先日Amazon Q DeveloperがGAとなり、CodeWhispererもAmazon Q Developerの機能の一部として変更されました。
なお今回は触れませんが、GAになって以下のような機能が追加されています。
- AWSアカウント上のリソース情報の提供: S3バケットやLambda関数といったリソースの個数などをチャットから質問できます。
- AWSコスト情報の提供: アカウント上で利用料金の大きいリソース種別などを質問できます。
- Software development:
/devコマンドと自然言語を組み合わせて、コードを生成します(CodeCatalystとの連携が必要)。 - Code transformation: Javaのコードのバージョン更新に合わせてコードを修正します (ドキュメント)。
※参考:
検証
Visual Studio Codeの拡張機能更新
以前Amazon CodeWhispererをVisual Studio Codeにインストールしているので、VSCodeの再起動・更新を行います。起動後、Amazon Qにログインすれば準備は完了です。

コード生成
試しに前回と同様CloudFormationのコードを生成してみます。生成時の精度などはまだわかりませんが、生成時のメッセージが Amazon Q is generating… に変更されています。

特に問題もなく生成されました。

コードの説明
続いて既存コードに対する機能をいくつか見ていきます。
IDE上でコードを選択して右クリックを押すと、以下のようにいくつかオプションが表示されます。

このうち explain をクリックすると、選択したコードがどんな内容かを説明してくれます。

今回は以下のように出力されました。CloudFormationの各項目について説明してくれるので、初めて見るコードの理解に役立ちそうです。
The code you provided is a CloudFormation template that defines an ECS (Elastic Container Service) Task Definition. The Task Definition is the blueprint for running a Docker container in an ECS cluster.
Here's a breakdown of the key elements in the code:
- ECSTaskDefinition:
- This is the CloudFormation resource that defines the ECS Task Definition.
- The
Typeis set toAWS::ECS::TaskDefinition, which is the CloudFormation resource type for an ECS Task Definition.
- Properties:
RequiresCompatibilities: Specifies the launch type compatibility for the task. In this case, it's set toFARGATE, which means the task will run on AWS Fargate, a serverless compute engine for containers.Cpu: Specifies the number of CPU units used by the task. In this case, it's set to1024, which is equivalent to 1 vCPU.Memory: Specifies the amount of memory (in MiB) used by the task. In this case, it's set to2048MiB, which is 2 GB.NetworkMode: Specifies the Docker networking mode to use for the containers in the task. In this case, it's set toawsvpc, which provides each task with its own elastic network interface.ExecutionRoleArn: Specifies the ARN (Amazon Resource Name) of the IAM role that provides permissions for the ECS task to access other AWS services.ContainerDefinitions: Defines the container(s) that will be part of the task. In this case, there is a single container definition.Name: The name of the container, which is set to the name of the CloudFormation stack.Image: The Docker image to use for the container, which is specified by theECRRepositoryparameter.PortMappings: Defines the port mapping between the container and the host. In this case, the container exposes port 80.LogConfiguration: Configures the log driver and options for the container. In this case, it's set to use theawslogslog driver, which sends logs to CloudWatch Logs.
This CloudFormation template sets up an ECS Task Definition that runs a single container on the Fargate launch type, with specific CPU, memory, and networking configurations, as well as logging settings.
コードのリファクタリング
先ほどと同様にコードを選択して右クリックしたのち、今度は refactor を選択します。今度は選択したコードを修正する場合の選択肢を提示してくれます。

ここでは大きく4か所の修正を提案されました。
ECSTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: Family: !Ref AWS::StackName RequiresCompatibilities: - FARGATE Cpu: 1024 Memory: 2048 NetworkMode: awsvpc ExecutionRoleArn: !GetAtt ECSExecutionRole.Arn TaskRoleArn: !GetAtt ECSTaskRole.Arn ContainerDefinitions: - Name: app Image: !Ref ECRRepository PortMappings: - ContainerPort: 80 LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref AWS::StackName awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs
Here are the changes made in the refactored code:
- Family: I've added the
Familyproperty to theECSTaskDefinitionresource. This property specifies the name of the task definition. In this case, it's set to the name of the CloudFormation stack using the!Ref AWS::StackNameintrinsic function. - TaskRoleArn: I've added the
TaskRoleArnproperty to theECSTaskDefinitionresource. This property specifies the ARN of the IAM role that provides permissions for the ECS task to access other AWS services. In this case, it's set to theECSTaskRoleresource, which should be defined elsewhere in the CloudFormation template. - Container Name: I've changed the container name from the stack name to a more generic "app" name. This makes the task definition more reusable and easier to understand.
- Formatting: I've improved the formatting of the code for better readability, such as aligning the properties and using consistent indentation.
These changes make the task definition more explicit and easier to understand. The Family and TaskRoleArn properties provide more context about the task definition, and the container name change makes the definition more generic and reusable.
Remember, when working with AWS credentials in your code, it's important to fetch them from environment variables instead of hardcoding them directly in the code. This helps maintain better security practices and makes the code more portable.
コードの修正
今度は fix を試してみます。オプションを選択する前に一部コードをわざと変にしておきます。すると、誤った箇所を指摘しつつ、正しい記述を表示してくれました。

ECSTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - FARGATE Cpu: 1024 Memory: 2048 NetworkMode: awsvpc ExecutionRoleArn: !GetAtt ECSExecutionRole.Arn ContainerDefinitions: - Name: !Ref AWS::StackName Image: !Ref ECRRepository PortMappings: - ContainerPort: 80 LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref AWS::StackName awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs
The changes made in this fixed version are:
- Removed
FARGATEFailedfromRequiresCompatibilities: The correct value for theRequiresCompatibilitiesproperty isFARGATE, notFARGATEFailed. - Kept the rest of the code unchanged: The rest of the code, including the
Cpu,Memory,NetworkMode,ExecutionRoleArn,ContainerDefinitions,PortMappings, andLogConfigurationproperties, remains the same as the original code block.
This fixed version of the code should work as expected, creating an ECS Task Definition with the specified configurations.
Remember, when working with AWS credentials in your code, it's important to fetch them from environment variables instead of hardcoding them directly in the code. This helps maintain better security practices and makes the code more portable.
コードの最適化
optimize はコードを最適化し、パフォーマンスの向上などをサポートする機能です。ここでは以下のように4つの提案をされました。

ECSTaskDefinition: Type: AWS::ECS::TaskDefinition Properties: RequiresCompatibilities: - FARGATE Cpu: 1024 Memory: 2048 NetworkMode: awsvpc ExecutionRoleArn: !GetAtt ECSExecutionRole.Arn TaskRoleArn: !GetAtt ECSTaskRole.Arn ContainerDefinitions: - Name: app Image: !Ref ECRRepository PortMappings: - ContainerPort: 80 Environment: - Name: LOG_LEVEL Value: info LogConfiguration: LogDriver: awslogs Options: awslogs-group: !Ref LogGroup awslogs-region: !Ref AWS::Region awslogs-stream-prefix: ecs DependsOn: - LogGroup LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Ref AWS::StackName RetentionInDays: 7
Here are the optimizations made in this version:
- Added
TaskRoleArn: I've added theTaskRoleArnproperty to theECSTaskDefinitionresource. This property specifies the ARN of the IAM role that provides permissions for the ECS task to access other AWS services. In this case, it's set to theECSTaskRoleresource, which should be defined elsewhere in the CloudFormation template. - Changed container name: I've changed the container name from the stack name to a more generic "app" name. This makes the task definition more reusable and easier to understand.
- Added environment variable: I've added an environment variable
LOG_LEVELwith a value ofinfo. This can be used by the application running in the container to control the logging level. - Moved log group to separate resource: I've moved the log group configuration to a separate
LogGroupresource. This makes the code more modular and easier to maintain. TheDependsOnproperty ensures that the log group is created before the task definition. - Improved log group configuration: I've added the
RetentionInDaysproperty to theLogGroupresource, which specifies the number of days to retain the log events. In this case, it's set to 7 days.
These optimizations make the task definition more explicit, reusable, and easier to maintain. The addition of the task role and environment variable provide more flexibility and control over the container's execution. The separation of the log group configuration into a separate resource improves the overall code structure and modularity.
Remember, when working with AWS credentials in your code, it's important to fetch them from environment variables instead of hardcoding them directly in the code. This helps maintain better security practices and makes the code more portable.