Snowflake×TerraformCloud 試してみた


## 背景

社内で使っているSnowflakeのリソースをTerraformで管理したいと思い、
Terraformは初心者のため、まずはテスト環境で試してみることにしました.

## Terraform Cloudとは

Terraform Cloudは、Terraformを使ったインフラストラクチャの管理をより効率的に行うためのクラウドベースのサービスです。
主な機能としては、下記があります。
- Terraformの状態ファイル（state file）をリモートで保存し、共有管理できる
- GitHubやGitLabなどのリポジトリと連携し、コードの変更をバージョン管理できる。プルリクエストがマージされると、自動的にデプロイされるように設定できる。
- コードの変更があった際に、Terraformのプランを自動的に実行し、その結果をレビューしてからアプライすることができる。これにより、変更が実際にどのような影響を与えるかを事前に確認できる

イメージとしては、Terraform + Github Action + ステート管理(S3など)の形でやっていたものを、Terraform Cloudを使うことでよりシンプルな形にできるのかなと思いました。

## 環境

- M2 Macbook
- OSSonoma 14.4
- Terraform v1.9.0
- Terraform Cloud

今回は下記の構成で試していきます。
![スクリーンショット 2024-07-05 19.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/9a2734cf-669e-abca-3ac5-70cb821d7133.png)

## 事前準備

- Githubリポジトリを作成しておく
- ローカルにterraformをインストールしておく


```shell: homebrewでいれる場合
$ brew tap hashicorp/tap 
$ brew install hashicorp/tap/terraform    
```
```shell:asdfでいれる場合
$ asdf plugin add terraform
$ asdf install terraform latest 
$ asdf list  
$ asdf global terraform 1.9.0  
$ asdf current 
```

## Snowflake環境作成

Snowflakeのトライアル環境を作成します。
トライアルを申し込むと、400ドルのクレジットが含まれる環境が30日間使えるようになります。

https://www.googleadservices.com/pagead/aclk?sa=L&ai=DChcSEwip_NWPxYyHAxXqxUwCHQ4YCngYABAAGgJ0bQ&co=1&ase=2&gclid=Cj0KCQjw7ZO0BhDYARIsAFttkCg8xoXMt4OZKDW0KmzY7SWg6GGZdSUZLudN341rOhxv29Yqy_dKVUcaAp1rEALw_wcB&ohost=www.google.com&cid=CAESVuD2yKXBdcplCpuFnrzOvUNnKF0Squ3HAPvXp2ZbEViRzUu9behxyO8oTClq54yw-DDp8sWit0mrnhGMyW2n2k09QojnkUQAU5MZkMV74T8gCZF38tJk&sig=AOD64_0nbnnKthalCbRY1NYY24weVqWPnw&q&nis=4&adurl&ved=2ahUKEwig5NCPxYyHAxU8lFYBHV-ND2AQ0Qx6BAgIEAE

名前、メールアドレス、会社名、ロール、国を選択したら、次へ進むをクリックします.

<img width="300" alt="スクリーンショット 2024-07-04 13.25.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/e2fb05c8-fe18-5dee-9e90-e55afa17ac39.png">

Editionはデフォルトのエンタープライズにして、AWSのAsia Pacificを選択します。
「はじめる」をクリックすると、アンケートが表示されます。答えてもスキップしてもOKです。
<img width="300" alt="スクリーンショット 2024-07-04 13.27.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/cfca1b90-5b2e-71dd-36f2-244ce0a8d621.png">

完了すると、数分後にメールが届くので、リンクをクリックして有効化しておきます。

## Terraform用ユーザーの作成

Snowflakeにログインしたら、Terraform用のユーザーを作成しておきます。
```sql:sql worksheet
-- Terraform用に使用するユーザーとロールとウェアハウスの準備

USE ROLE SECURITYADMIN;

-- 新規ユーザーの作成
CREATE USER TOOL_TERRAFORM PASSWORD='StrongPassword' MUST_CHANGE_PASSWORD=TRUE;

-- ロールの作成
CREATE ROLE TERRAFORM;
GRANT ROLE TERRAFORM TO USER TOOL_TERRAFORM;
GRANT ROLE SECURITYADMIN TO ROLE TERRAFORM;
GRANT ROLE SYSADMIN TO ROLE TERRAFORM;

-- WHの作成
USE ROLE SYSADMIN;

CREATE WAREHOUSE TERRAFORM_WH
WITH WAREHOUSE_SIZE = 'XSMALL'
     AUTO_RESUME = TRUE
     AUTO_SUSPEND = 60
     INITIALLY_SUSPENDED = TRUE
     STATEMENT_TIMEOUT_IN_SECONDS = 300
     COMMENT = 'for terraform';


-- WHの権限付与
grant USAGE on warehouse terraform_wh to role terraform;
grant USAGE on warehouse terraform_wh to role securityadmin;
grant USAGE on warehouse terraform_wh to role sysadmin;
grant USAGE on warehouse terraform_wh to role useradmin;
```

完了したら、一度サインアウトして、上記で作成したアカウントでログインします。
パスワードの変更が求められるので、変更完了したらOKです。


## Terraform CloudのアカウントとOrganization作成

下記のリンクから、TerraformCloudのアカウントを作成し、Organizationを作成します。

https://app.terraform.io/public/signup/account

Terraform Cloudのアカウント作成等は下記を参考にしました。

https://zenn.dev/chario/books/tfc-aws-introductory-book/viewer/04_tfc_create_org_user

Organizationの作成が完了すると下記の画面になります。
Workspaceを作成していきます。
![スクリーンショット 2024-07-04 13.23.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/455d5883-5668-4bfe-76f6-6732597ec5f7.png)

Githubと連携するため、「Version Control Workflow」を選択します。
Githubと接続し、Advanced optionsを設定していきます。
下記を参考にしました。

https://zenn.dev/i_do/articles/5bb18d1fe8088a


Githubリポジトリをgit cloneし、ターミナルからterraformにログインします。
```
$ terraform login
```
表示される内容にしたがい、トークンを作成>ターミナルにコピペで認証完了されます。


## 環境変数の設定

認証情報を安全に管理・保持しておくためにVariablesを設定します。

`Configure Variables`を押下し、
![スクリーンショット 2024-07-05 11.08.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/3cece280-b554-96fd-634c-15a2b9aaacb0.png)

`Add variable`から下記の認証情報を1つずつ追加します。
パスワードは**Sensitiveフラグをオン**にしてください。
(登録時はダブルクオーテーションは不要)

```shell
snowflake_account="AB12345.ap-northeast-1.aws"
snowflake_username="TOOL_TERRAFORM"
snowflake_password="StrongPassword" # change this
snowflake_warehouse="TERRAFORM_WH"
```
:::note info
account locatorは、Snowflake画面の左下のユーザー名>アカウント>リンクをコピーして取得できます。

![スクリーンショット 2024-07-04 18.41.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/118bbf2b-1bf7-e3c3-e576-7e9e013c17ee.png)
▼正しくはアカウント名ではなく、アカウントロケーターです
![スクリーンショット 2024-07-04 18.49.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/0677de04-5394-d43e-b5d3-eab80040c274.png)
※Regionはdeplicateになったようです。現在はAccountパラメータにリージョンも含めるでOK.
:::


## ウェアハウスを作ってみる

下記のファイルを作成します。
- terraform.tf
- vafriables.tf
- warehouse.tf


```terraform.tf
terraform {
  required_providers {
    snowflake = {
      source  = "Snowflake-Labs/snowflake"
      version = "~> 0.61"
    }
  }
}

provider "snowflake" {
  alias    = "sysadmin"
  role     = "SYSADMIN"
  user = var.snowflake_username
  password = var.snowflake_password
  account  = var.snowflake_account
  warehouse = var.snowflake_warehouse
}
```

```variables.tf
variable "snowflake_username" {
  description = "The username for Snowflake"
  type        = string
}

variable "snowflake_password" {
  description = "The password for Snowflake"
  type        = string
  sensitive   = true
}

variable "snowflake_account" {
  description = "The account name for Snowflake"
  type        = string
}

variable "snowflake_warehouse" {
  description = "The warehouse for Snowflake"
  type        = string
}

```

```warehouse.tf
resource "snowflake_warehouse" "op_wh" {
  provider            = snowflake.sysadmin
  name                = "OP_WH"
  comment             = "Operational Warehouse"
  warehouse_size      = "XSMALL"
  auto_suspend        = 60 # 60sec
  auto_resume         = true
  initially_suspended = true
  max_cluster_count   = 1
  min_cluster_count   = 1
  scaling_policy      = "STANDARD"
}
```

terraform init して、プロバイダをインストールしたりモジュールのダウンロードなどをします。

```
$ terraform init
```

pushしてプルリクを作成します。
planが成功しました🎉
![スクリーンショット 2024-07-05 16.13.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/ecd5963d-8291-b123-a30f-5e5aacaf855d.png)
mainにマージし、terraform Cloudで[Confirm&apply]します。

![スクリーンショット 2024-07-05 18.51.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/2a8d0008-da83-bea5-1bc3-47a113a9cb60.png)

作成完了しました。

![スクリーンショット 2024-07-05 18.54.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/9fe1f92c-3a6d-aeb0-3bb9-0dc5c6102b90.png)

snowflakeで下記のSQLを実行し、作成されていることを確認します。
```sql
show warehouses like 'op_wh';
```
![スクリーンショット 2024-07-05 18.55.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506559/9c1b8b5d-b798-44af-3c5e-42390ffc881d.png)
無事作成されていました。

## 感想

Github ActionやState管理を別で行う必要がないので、かなり楽にリソース管理できそうですね。
今回TerraformとTerraform Cloudを1から学んだので、思ったよりかなり時間がかかってしまいましたが、一度流れがつかめればスムーズに管理できるのではないかと思います。
しばらくいろいろリソースを作ってみて慣れようと思います。

## 参考

https://zenn.dev/i_do/articles/5bb18d1fe8088a

https://qiita.com/hiro-wa/items/4aeb1c7346714d6b5e53

https://zenn.dev/isosa/articles/ca44f2efbfe36b

https://qiita.com/hiyanger/items/e60ed7600d0cda120482

https://zenn.dev/mnagaa/books/3d668d2dfc657e

https://zenn.dev/yamnaku/articles/6f1d45640125b2

https://zenn.dev/chario/books/tfc-aws-introductory-book