APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

Geminiを使って手書きの構成図からTerraformファイルを作ろうとしてみた

こんにちは!ACSD松崎です。この記事は、Googleの新しい生成AIモデル、Geminiを使って手書きの構成図からTerraformの定義ファイルを作ろうとした際のメモになります。

Geminiとは

2023年12月7日に発表されたmade by Googleの生成AIです。2023年12月末現在、Gemini Ultra / Pro / Nanoの3タイプが存在し、そのうちGemini ProをGoogle Bardから利用することができます。

Gemini - Google DeepMind

やりたかったこと

  • Azureのラフな手書き構成図からterrraformファイルを作ってもらう。
  • terraform fileの品質としては、terraform validateをエラーなしで通過する状態を目指す

試した結果

試した結果は以下となりました。マルチモーダルな処理には満足なのですが、terraform fileの作成の精度に課題という結果ですね。

  • 手書きの画像をもとに、システム構成をGeminiに理解してもらう → OK
  • 理解したシステム構成をもとに、terraform validateをパスするterraformファイルを生成させる → NG

検証メモ

Geminiに読み込ませてみる

まずはGoogle Bardを使って、バックエンドで動いているGeminiに作ってみた手書きの構成図を読み込ませてみます。果たしてGeminiは内容を理解することができますでしょうか...?

回答が返ってきました!Azure Databaseと記述していた部分がAzure Database for PostgreSQLに置き換えられていますが、概ね正しく内容を理解しているように見えます。いい感じですね。 ※アウトプットが長いので、一部省略しています

Terraformファイルを作ってもらう

理解したシステム構成を元に、Google Geminiにterraformファイルを生成してみます。

出力結果は以下となりました。これを terraform validate してみましょう。 ※provider部分はあらかじめ別に用意しておいたものを使っていますので、割愛します。

resource "azurerm_resource_group" "default" {
  name = "terraform-demo"
  location = "japaneast"
}

resource "azurerm_virtual_network" "default" {
  name = "terraform-demo-network"
  location = azurerm_resource_group.default.location
  address_space = ["10.0.0.0/16"]
}

resource "azurerm_subnet" "default" {
  name = "terraform-demo-subnet"
  virtual_network_id = azurerm_virtual_network.default.id
  address_prefix = "10.0.1.0/24"
}

resource "azurerm_network_interface" "default" {
  name = "terraform-demo-nic"
  location = azurerm_resource_group.default.location
  virtual_network_id = azurerm_virtual_network.default.id
  subnet_id = azurerm_subnet.default.id
}

resource "azurerm_public_ip" "default" {
  name = "terraform-demo-ip"
  location = azurerm_resource_group.default.location
  resource_group_name = azurerm_resource_group.default.name
  allocation_method = "Static"
}

resource "azurerm_virtual_machine" "default" {
  name = "terraform-demo-vm"
  location = azurerm_resource_group.default.location
  resource_group_name = azurerm_resource_group.default.name
  network_interface_ids = [azurerm_network_interface.default.id]
  vm_size = "Standard_D2s_v3"
  os_type = "Linux"
  os_disk_size_gb = 128
  admin_username = "azureuser"
  admin_password = "Pa$$w0rd"
  public_ip_address_id = azurerm_public_ip.default.id
}

resource "azurerm_postgresql_server" "default" {
  name = "terraform-demo-postgres"
  location = azurerm_resource_group.default.location
  resource_group_name = azurerm_resource_group.default.name
  sku = "Standard_D2s_v3"
  version = "13"
  admin_username = "postgres"
  admin_password = "Pa$$w0rd"
}

resource "azurerm_postgresql_database" "default" {
  name = "terraform-demo"
  server_id = azurerm_postgresql_server.default.id
}

terraform validate の実行結果ですが、以下のように Missing required argument Unsupported argument を中心に、多数(合計19)のエラーが出ました。terraformのリソース定義に従った形で、Geminiがterraformファイルを作ってくれなかったということですね。

│ Error: Missing required argument
│
│   on main.tf line 6, in resource "azurerm_virtual_network" "default":
│    6: resource "azurerm_virtual_network" "default" {
│
│ The argument "resource_group_name" is required, but no definition was found.

│ Error: Unsupported argument
│
│   on main.tf line 14, in resource "azurerm_subnet" "default":
│   14:   virtual_network_id = azurerm_virtual_network.default.id
│
│ An argument named "virtual_network_id" is not expected here.

(※他に17のErr MSGが出たが長くなるので割愛)

ここで終わるのは悔しいので、ChatGPT(GPT4)を使って、terraformファイルの修正を試みてみましょう。プロンプトは以下となります。

以下のTerraformファイルをterraform validateしたところエラーを検出しました。エラーの内容を踏まえ、terraformファイルを修正してください。

# terraform file
[Geminiに生成されたterraformファイル]

# Err Msg
[terraform validate実行時のエラー]

ChatGPT(GPT4)の生成結果ですが、以下のように不足していたパラメーターが全体的に補完されています。これを再び terraform validate してみます。

resource "azurerm_resource_group" "default" {
  name     = "terraform-demo"
  location = "japaneast"
}
resource "azurerm_virtual_network" "default" {
  name                = "terraform-demo-network"
  location            = azurerm_resource_group.default.location
  resource_group_name = azurerm_resource_group.default.name
  address_space       = ["10.0.0.0/16"]
}
resource "azurerm_subnet" "default" {
  name                 = "terraform-demo-subnet"
  resource_group_name  = azurerm_resource_group.default.name
  virtual_network_name = azurerm_virtual_network.default.name
  address_prefixes     = ["10.0.1.0/24"]
}
resource "azurerm_network_interface" "default" {
  name                = "terraform-demo-nic"
  location            = azurerm_resource_group.default.location
  resource_group_name = azurerm_resource_group.default.name
  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.default.id
    private_ip_address_allocation = "Dynamic"
  }
}
resource "azurerm_public_ip" "default" {
  name                = "terraform-demo-ip"
  location            = azurerm_resource_group.default.location
  resource_group_name = azurerm_resource_group.default.name
  allocation_method   = "Static"
}
resource "azurerm_virtual_machine" "default" {
  name                  = "terraform-demo-vm"
  location              = azurerm_resource_group.default.location
  resource_group_name   = azurerm_resource_group.default.name
  network_interface_ids = [azurerm_network_interface.default.id]
  vm_size               = "Standard_D2s_v3"
  os_type               = "Linux"
  os_disk_size_gb       = 128
  admin_username        = "azureuser"
  admin_password        = "Pa$$w0rd"
  public_ip_address_id  = azurerm_public_ip.default.id
}
resource "azurerm_postgresql_server" "default" {
  name                = "terraform-demo-postgres"
  location            = azurerm_resource_group.default.location
  resource_group_name = azurerm_resource_group.default.name
  sku_name            = "GP_Gen5_2"
  version             = "13"
  ssl_enforcement_enabled = true
  administrator_login = "postgres"
  administrator_login_password = "Pa$$w0rd"
}
resource "azurerm_postgresql_database" "default" {
  name                = "terraform-demo"
  resource_group_name = azurerm_resource_group.default.name
  server_name         = azurerm_postgresql_server.default.name
  charset             = "UTF8"
  collation           = "English_United States.1252"
}

エラーの総数が19→7まで減りましたが、逆にいうと0にはできませんでした。うーん、やはり「生成AIで完動するファイルを簡単に生成」とまではいきませんね。もう少し頑張ってみたい気持ちもありますが、今回の検証はここまでにしたいと思います。

│ Error: Insufficient storage_os_disk blocks
│
│   on main.tf line 33, in resource "azurerm_virtual_machine" "default":
│   33: resource "azurerm_virtual_machine" "default" {
│
│ At least 1 "storage_os_disk" blocks are required.
╵
╷
│ Error: Unsupported argument
│
│   on main.tf line 39, in resource "azurerm_virtual_machine" "default":
│   39:   os_type               = "Linux"
│
│ An argument named "os_type" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│   on main.tf line 40, in resource "azurerm_virtual_machine" "default":
│   40:   os_disk_size_gb       = 128
│
│ An argument named "os_disk_size_gb" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│   on main.tf line 41, in resource "azurerm_virtual_machine" "default":
│   41:   admin_username        = "azureuser"
│
│ An argument named "admin_username" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│   on main.tf line 42, in resource "azurerm_virtual_machine" "default":
│   42:   admin_password        = "Pa$$w0rd"
│
│ An argument named "admin_password" is not expected here.
╵
╷
│ Error: Unsupported argument
│
│   on main.tf line 43, in resource "azurerm_virtual_machine" "default":
│   43:   public_ip_address_id  = azurerm_public_ip.default.id
│
│ An argument named "public_ip_address_id" is not expected here.
╵
╷
│ Error: expected version to be one of [9.5 9.6 11 10 10.0], got 13
│
│   with azurerm_postgresql_server.default,
│   on main.tf line 50, in resource "azurerm_postgresql_server" "default":
│   50:   version             = "13"

終わりに

生成AIによるIaCファイルの自動生成はまだまだ課題が多そうという結果になりました。残念ではありますが、技術的なニーズのある分野だと思いますので、今回の結果を踏まえつつ、もう少しベターなやり方がないか引き続き考えてみたいと思います。

私達ACS事業部はAzure・AKSなどのクラウドネイティブ技術を活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。

www.ap-com.co.jp

また、一緒に働いていただける仲間も募集中です!
今年もまだまだ組織規模拡大中なので、ご興味持っていただけましたらぜひお声がけください。

www.ap-com.co.jp

本記事の投稿者: Shin Matsuzaki
個人ブログ