本記事は
初夏のAWSアワードエンジニア祭り
4日目の記事です。
🍦
3日目
▶▶ 本記事 ▶▶
5日目
💻
こんにちは!最近、息子がよく言う「へー、そうなんやー」が好きすぎて、大人が「そうなんや」って言っててもニヤニヤしてる志水です。
今年から初めてAWS Ambassadorsとして選出頂きました。他のAmbassadorの方を見ているとまだまだ力不足であり、更に今回退任された佐々木さんには全く及びませんが、ネットコムは佐々木さん・上野さんだけじゃないぞ、というのを自分なりに頑張って証明していきたいと思います。その一歩として僕の大好きなCDKとChatGPTに関する話をしようと思います。
はじめに
以前CDK Importの記事を公開してから二週間も経たないうちにCDK v2.20.0でcdk importコマンドがプレビュー版としてリリースされました。ちょっと引きました。
以前の記事はCloudFormation resource importsを利用してCDKコードに取り込む方法を紹介しましたが、v2.20.0以降はcdk importコマンドを利用して取り込むことが可能になりました。そのため、CFn resource importsを経由せずに、cdkのコマンドだけで取り込むことができるようになりました。しかし、リソースの設定に合わせてコードを修正する必要があり、この部分がなかなか大変です。Terraformでも同様の問題がありますが、それを解決したTerraformerというツールがあるため、Terraformだと楽に取り込むことができます。
そして時は流れ、最近ではChatGPTが登場しCDKのコーディングを助けてくれるようになりました。以前私が発表したCDKとChatGPTに関するスライドは以下のリンクから参照できます。CDKとChatGPTの関係性を知りたい方は、ぜひご覧ください。
ChatGPTがCDKコーディングを助けてくれるなら、TerraformのTerraformerのような役割をChatGPTが果たせないか、ということを今回試してみました。
ChatGPTでインポート
本来のユースケースとは異なり、正解データとの比較を行いたいため、以下の手順で対象のリソースと正解のCDKコードを用意し、ChatGPTを利用してCDKコードを生成してみます。使用する言語はPythonです。
- CDKコードで対象を作成
- デプロイ後、CDKからリソースを削除
- 削除ポリシーを保持に設定して削除
- コードからリソースの関連付けを解除してリソースを保持
- aws cliを使用してリソースの情報を取得
- 取得した情報をChatGPTに入力
- ChatGPTから出力されたCDKコードを正解データと比較
1. CDKコードで対象を作成
対象のリソースは今回DynamoDBとします。今回は基本的にデフォルトのものを利用するコードとしています。
table = dynamodb.Table( self, "MyTable", partition_key=dynamodb.Attribute( name="id", type=dynamodb.AttributeType.STRING ), table_name="manual_table", removal_policy=RemovalPolicy.RETAIN )
今回はこちらがCDKの正解コードとして利用します。
2. デプロイ後、CDKからリソースを削除
上記コードをデプロイし、テーブル作成します。
その後対象リソースをコメントアウトなりして削除すると、削除ポリシーにRemovalPolicy.RETAIN
を指定しているのでコードと関連が外れます。
出来たリソースが今回のChatGPTを利用してインポートしたいものと考えます。
3. aws cliを使用してリソースの情報を取得
$ aws dynamodb describe-table --table-name manual_table { "Table": { "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" } ], "TableName": "manual_table", "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" } ], "TableStatus": "ACTIVE", "CreationDateTime": "2023-05-18T04:03:18.450000+00:00", "ProvisionedThroughput": { "NumberOfDecreasesToday": 0, "ReadCapacityUnits": 5, "WriteCapacityUnits": 5 }, "TableSizeBytes": 0, "ItemCount": 0, "TableArn": "arn:aws:dynamodb:ap-northeast-1:XXXXXXXXXXXX:table/manual_table", "TableId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "DeletionProtectionEnabled": false } }
4. 取得した情報をChatGPTに入力
3で得た情報をChatGPTに入力し、CDKコードを生成してもらいます。ChatGPTに入力した内容は下記です。
下記がaws cliで情報取得した結果です。この結果を元に同じものを作るようにPythonでCDKコードを作成して。ChatGPTで作ったことがわかるようにコードやリソース名も修正して。
3の内容をコピー
5. ChatGPTから出力されたCDKコードを正解データと比較
4で出力されたコードから必要な部分を抜き出したものは下記になります。
table = ddb.Table( self, "ChatGPTTable", partition_key=ddb.Attribute( name="id", type=ddb.AttributeType.STRING ), table_name="chatgpt_table_replica", # Replace with your new table name billing_mode=ddb.BillingMode.PROVISIONED, # Provisioned mode read_capacity=5, # Read capacity units write_capacity=5, # Write capacity units removal_policy=core.RemovalPolicy.RETAIN # NOT recommended for production code )
モジュール名や固有名の部分を除き、CDK v1系で出力してるために付いているcoreの部分を除くと、今回の正解データと違うのは下記になります。
billing_mode=ddb.BillingMode.PROVISIONED, # Provisioned mode read_capacity=5, # Read capacity units write_capacity=5, # Write capacity units
こちらはCDKドキュメントを確認すると、全てデフォルトの値で明示的に入れているだけなので、結果的に差分はありませんでした。
検証結果
上記の検証結果から、aws cliの出力から問題なくCDKコードが生成できることが確認できました。検証を進める上でいくつか注意点があったので、それらを共有します。
入力情報以外は不安定
まず、cliから取得した内容以外の情報は必ずしも正確ではないことがありました。これは当然と言えば当然で、入力した情報に含まれていないため、ChatGPTがそれを解釈することはできません。しかし、ChatGPTは自動的に解釈して補完してくれるため、多くの場合、デプロイ可能な状態になっています。今回の場合、 removal_policy
はDynamoDBの情報ではなく、CDKやCloudFormation側の情報になるため、出力のタイミングで頻繁に変化していました。そのため、特定の値を固定したい場合は、ChatGPTへの入力時にその要件を追加すると、結果のブレが少なくなります。
先生ではなく副操縦士
以前の発表でも述べたように、ChatGPTはあくまでコーディングパートナーとして利用するのが最適です。そのため、ChatGPTへの入力結果が動作しない場合でもすぐに諦めるのはもったいないと思います。エラー内容をINPUTとして後続の会話に利用したり、cdk v1のコードを手動で修正したりと、一緒にコーディングするという視点を忘れないことが重要です。
コマンド作成の負荷
また、今回は情報取得のコマンドが少なく、CDKコードも簡単に作成できるDynamoDBを対象としました。当初はS3を考えていたのですが、S3の情報取得のAPIは多く、aws s3apiのリファレンスを見ると、バケットの情報取得のコマンドは21個もあります。そのため、ChatGPTに渡すためのコマンドも21個のコマンド内容と結果が必要になり、結果的には手間がかかります。そのため、情報取得のためのコストが増えます。
ただし、これらのコマンドもChatGPTに作成してもらうことは可能です。以下は、ChatGPTに頑張って作成してもらったときの会話の一部です。
最終的には下記のようなスクリプトができました。
#!/bin/bash # Define the bucket name BUCKET_NAME="my-bucket" # Use the bucket name in AWS CLI commands echo "Getting bucket accelerate configuration..." aws s3api get-bucket-accelerate-configuration --bucket $BUCKET_NAME echo "Getting bucket ACL..." aws s3api get-bucket-acl --bucket $BUCKET_NAME echo "Getting bucket CORS..." aws s3api get-bucket-cors --bucket $BUCKET_NAME echo "Getting bucket encryption..." aws s3api get-bucket-encryption --bucket $BUCKET_NAME echo "Getting bucket lifecycle configuration..." aws s3api get-bucket-lifecycle-configuration --bucket $BUCKET_NAME echo "Getting bucket location..." aws s3api get-bucket-location --bucket $BUCKET_NAME echo "Getting bucket logging..." aws s3api get-bucket-logging --bucket $BUCKET_NAME echo "Getting bucket notification configuration..." aws s3api get-bucket-notification-configuration --bucket $BUCKET_NAME echo "Getting bucket ownership controls..." aws s3api get-bucket-ownership-controls --bucket $BUCKET_NAME echo "Getting bucket policy..." aws s3api get-bucket-policy --bucket $BUCKET_NAME echo "Getting bucket policy status..." aws s3api get-bucket-policy-status --bucket $BUCKET_NAME echo "Getting bucket replication..." aws s3api get-bucket-replication --bucket $BUCKET_NAME echo "Getting bucket request payment..." aws s3api get-bucket-request-payment --bucket $BUCKET_NAME echo "Getting bucket tagging..." aws s3api get-bucket-tagging --bucket $BUCKET_NAME echo "Getting bucket versioning..." aws s3api get-bucket-versioning --bucket $BUCKET_NAME echo "Getting bucket website..." aws s3api get-bucket-website --bucket $BUCKET_NAME echo "Getting public access block..." aws s3api get-public-access-block --bucket $BUCKET_NAME
おわりに
今回の検証では、aws cliで情報を取得し、それをChatGPTに入力してCDKコードを生成し、その後cdk importで既存リソースと紐付けるという流れで、既存リソースをCDKで取り込むことができました。これは非常に有用です。 ただし、どの段階においても、我々はLLMの世界にいるため、不確実性が高いものとなります。そのため、生成されたコードが問題ないかどうかは適宜検証することが重要です。 また、この記事を書いている時点でのCDKの最新バージョンはv2.79.1で、cdk importはまだプレビュー版であり、インポート後のドリフト検知はまだ多少不安定な部分があります。そのため、GA(一般利用可能)になると挙動が変わる可能性があります。もしかしたら、この記事を公開してから2週間も経たないうちにGAになるかもしれませんが、その時はまた新たな記事を泣きながら書きたいと思います。