Terraformを使ってIBM Cloud Code Engineを爆速ビルド

# はじめに
IBM CloudにもコンテナをサクッとデプロイできるIBM Cloud Code Engineというサービスがあります。また、IaCツールのTerraformでも環境を構築できます。今回、Terraform使ってCode Engineを構築してみたので、その方法について書きたいと思います。

# Terraform
## 前提
TerraformのCLIはインストールしている前提で進めます。
私はMac環境で、homebrewを使ってインストールしました。

ここ参照です。
[Install Terraform | Terraform | HashiCorp Developer](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)

## 準備

まず、IBM Cloudのリソースを作れるようにするために、providerとversionを設定します。
```ts:provider.ts
variable "ibmcloud_api_key" {}
variable "region" {}

provider "ibm" {
    ibmcloud_api_key   = var.ibmcloud_api_key
    region = var.region
    }
```
```ts:versions.ts
terraform {
    required_providers {
        ibm = {
        source = "IBM-Cloud/ibm"
        version = "1.60.1"
        }
    }
}
```

今回は、できるだけ新しいバージョンにしました。

参考
[Releases · IBM-Cloud/terraform-provider-ibm](https://github.com/IBM-Cloud/terraform-provider-ibm/releases)

変数は、こんな感じで設定します。
```ts:terraform.tfvars
ibmcloud_api_key = ""
region = "us-south"
code_engine_project_id = ""
```

ibmcloud_api_keyはIAMの設定画面から作りました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/182036b2-d306-77b0-05f9-75ed77016b04.png)

プロジェクトのID（`code_engine_project_id`）は後から使います。
Code Engineのプロジェクト画面から取得しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/c7de4496-1efc-46a2-1d25-271e81b93d65.png)


上記ファイルがあるフォルダにて、コマンドを実行していきます。

```
% terraform --version
Terraform v1.6.5
% which terraform
/opt/homebrew/bin/terraform
1 % terraform providers

Providers required by configuration:
.
└── provider[registry.terraform.io/ibm-cloud/ibm] 1.60.1

```

```
% terraform init

Initializing the backend...

Initializing provider plugins...
- Finding ibm-cloud/ibm versions matching "1.60.1"...
- Installing ibm-cloud/ibm v1.60.1...
- Installed ibm-cloud/ibm v1.60.1 (self-signed, key ID xxxx)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```

これで、準備できました。

ちなみに、`version.ts`を設定しないと以下のようなエラーが出て実行できませんでした。

```
% terraform init     

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/ibm...
╷
│ Error: Failed to query available provider packages
│ 
│ Could not retrieve the list of available versions for provider hashicorp/ibm: provider registry registry.terraform.io does not have a provider named
│ registry.terraform.io/hashicorp/ibm
│ 
│ All modules should specify their required_providers so that external consumers will get the correct providers when using a module. To see which modules are
│ currently depending on hashicorp/ibm, run the following command:
│     terraform providers
```

## リソース

今回、プロジェクトはすでに構築している前提で、下記リソース定義を準備します。
imageはテスト用にオープンになっているハローワールドのイメージを指定しています。
環境変数も簡単なものを準備しています。

```ts:main.ts
variable "code_engine_project_id" {}

resource "ibm_code_engine_app" "code_engine_app_instance" {
  project_id      = var.code_engine_project_id
  name            = "my-app"
  image_reference = "icr.io/codeengine/helloworld"

  run_env_variables {
    type  = "literal"
    name  = "name"
    value = "value"
  }
}
```

GUIから構築されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/80c1e256-47dd-a0aa-f201-0359cc41db52.png)

GUIからアドレスを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/9c56f0ae-9759-762f-1746-90621a0a20a2.png)

アクセスするとブラウザからこんな画面を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/0d323804-6dae-87b4-9d88-b86adfff2373.png)

かなり、シンプルに構築できたかなと思います。

他のパラメータについては下記をみながら設定すれば良さそうです。
[Docs overview | IBM-Cloud/ibm | Terraform | Terraform Registry](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs)

## 削除
最後に消しとこうと思います。
こんな感じで削除します。

```
% terraform destroy -target=ibm_code_engine_app.code_engine_app_instance    
ibm_code_engine_app.code_engine_app_instance: Refreshing state... [id=xxxx/my-app]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # ibm_code_engine_app.code_engine_app_instance will be destroyed
  - resource "ibm_code_engine_app" "code_engine_app_instance" {
      - app_id                        = "xxxx" -> null
      - created_at                    = "2023-12-14T14:35:07Z" -> null
      - endpoint                      = "https://my-app.xx.us-south.codeengine.appdomain.cloud" -> null
      - endpoint_internal             = "http://my-app.xx.svc.cluster.local" -> null
      - entity_tag                    = "xx" -> null
      - etag                          = "xx" -> null
      - href                          = "https://api.us-south.codeengine.cloud.ibm.com/v2/projects/xxxx/apps/my-app" -> null
      - id                            = "xxxx/my-app" -> null
      - image_port                    = 8080 -> null
      - image_reference               = "icr.io/codeengine/helloworld" -> null
      - managed_domain_mappings       = "local_public" -> null
      - name                          = "my-app" -> null
      - project_id                    = "xxxx" -> null
      - resource_type                 = "app_v2" -> null
      - run_arguments                 = [] -> null
      - run_commands                  = [] -> null
      - run_service_account           = "default" -> null
      - scale_concurrency             = 100 -> null
      - scale_cpu_limit               = "1" -> null
      - scale_ephemeral_storage_limit = "400M" -> null
      - scale_initial_instances       = 1 -> null
      - scale_max_instances           = 10 -> null
      - scale_memory_limit            = "4G" -> null
      - scale_min_instances           = 0 -> null
      - scale_request_timeout         = 300 -> null
      - status                        = "ready" -> null
      - status_details                = [
          - {
              - latest_created_revision = "my-app-00001"
              - latest_ready_revision   = "my-app-00001"
              - reason                  = ""
            },
        ] -> null

      - run_env_variables {
          - name  = "name" -> null
          - type  = "literal" -> null
          - value = "value" -> null
        }
      - run_env_variables {
          - name  = "CE_SUBDOMAIN" -> null
          - type  = "literal" -> null
          - value = "1asjmd55euy0" -> null
        }
      - run_env_variables {
          - name  = "CE_APP" -> null
          - type  = "literal" -> null
          - value = "my-app" -> null
        }
      - run_env_variables {
          - name  = "CE_DOMAIN" -> null
          - type  = "literal" -> null
          - value = "us-south.codeengine.appdomain.cloud" -> null
        }
    }

Plan: 0 to add, 0 to change, 1 to destroy.
╷
│ Warning: Resource targeting is in effect
│ 
│ You are creating a plan with the -target option, which means that the result of this plan may not represent all of the changes requested by the
│ current configuration.
│ 
│ The -target option is not for routine use, and is provided only for exceptional situations such as recovering from errors or mistakes, or when
│ Terraform specifically suggests to use it as part of an error message.
╵

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

ibm_code_engine_app.code_engine_app_instance: Destroying... [id=xxxx/my-app]
ibm_code_engine_app.code_engine_app_instance: Destruction complete after 1s
╷
│ Warning: Applied changes may be incomplete
│ 
│ The plan was created with the -target option in effect, so some changes requested in the configuration may have been ignored and the output values
│ may not be fully updated. Run the following command to verify that no other changes are pending:
│     terraform plan
│ 
│ Note that the -target option is not suitable for routine use, and is provided only for exceptional situations such as recovering from errors or
│ mistakes, or when Terraform specifically suggests to use it as part of an error message.
╵

Destroy complete! Resources: 1 destroyed.
```

# おわりに
今まで、少し気が重くてTerraform使えてなかったのですが、やってみると思ったより簡単でした。これからは、ガンガン使っていこうと思います。

# 参考
[IBM Cloud Code Engine入門 | IBM Cloud 資料](https://cloud.ibm.com/docs/codeengine?topic=codeengine-getting-started)
[Terraform for Code Engine のセットアップ | IBM Cloud 資料](https://cloud.ibm.com/docs/codeengine?topic=codeengine-terraform-setup-ce)
[Getting started with Terraform on IBM Cloud | IBM Cloud 資料](https://cloud.ibm.com/docs/ibm-cloud-provider-for-terraform?topic=ibm-cloud-provider-for-terraform-getting-started)
[Docs overview | IBM-Cloud/ibm | Terraform | Terraform Registry](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs)