昨今話題の terraformer で自作Providerのリソースをimportするところ（不完全）までできたのでやったことを書いてみる

## はじめに

[こちら](https://qiita.com/shogomuranushi/items/98cf2c9800187f51e982) の記事で [terraformer](https://github.com/GoogleCloudPlatform/terraformer) というものを知ることができたので（ありがとうございます）すが、実際に自作Provider相当のリソースををこの `terraformer` 経由で引っこ抜くためにはどうすれば良いのかを具体的に知りたく、実際にやってみました。

その内容について書いてみたいと思います。

## 本記事の前提

- 自分たちが作ったProvider: https://github.com/nttcom/terraform-provider-ecl
- 自分が `terraformer` をいじっているリポジトリ(のブランチ): https://github.com/keiichi-hikita/terraformer/tree/nttcom_enterprise_cloud_support

## おおよそのやることまとめ

### 1. `terraformer/cmd` にファイルを足す

ここに自分のプロバイダ用のコマンドを足し込む。
今回は `ecl.go` としてます。
実際のファイルは [こちら](https://github.com/keiichi-hikita/terraformer/blob/nttcom_enterprise_cloud_support/cmd/ecl.go)。


### 2. `terraform/cmd/import.go` にエントリを足す

上記で作成した `cmd/ecl.go` へのつなぎを、[こんな感じ](https://github.com/keiichi-hikita/terraformer/blob/nttcom_enterprise_cloud_support/cmd/import.go#L63) で足してあげます。

### 3. `terraformer/providers/ecl` を足す

ここに(今回は) `ECLProvider` という struct を足し、然るべきメソッドを実装していきます。
これを上記のcmd経由で呼び出していく形になります。

その際、各リソースに対応した `Generator` を定義し、それが `[]terraform_utils.Resource` を返せば良いようです。
おおよそどのリソースも同じ感じの実装で行ける感じです。
最終的に生成されるStateは本物の(Terraform側の)ProviderのReadメソッドに従って作成されるようです。
その際、形状がどうしても本来のtf定義と合わないような場合に、 `PostConvertHook()` を使って変更を仕込むことができるようです。

実際のファイルは、[こちら](https://github.com/keiichi-hikita/terraformer/tree/nttcom_enterprise_cloud_support/providers/ecl)。

### 4. `terraformer/providers/ecl/provider.go` にリソース群を追加する

別に `provider.go` というファイル名には全く意味はありませんが、結局 [ここ](https://github.com/keiichi-hikita/terraformer/blob/nttcom_enterprise_cloud_support/cmd/ecl.go#L32) で呼ばれる子が、 `map[string]terraform_utils.ServiceGenerator` を返す際に、リソース名とGeneratorの対を返せるようにエントリを追加していく必要があります。
[こんな](https://github.com/keiichi-hikita/terraformer/blob/nttcom_enterprise_cloud_support/providers/ecl/ecl_provider.go#L79-L82） イメージです。

## コンパイルして動作確認

あとは公式通りにコンパイルして実行すればOKです。

OpenStack利用しているサービスなので、通常の`gophercloud(僕らの場合はeclcloud)`で必要な環境変数とは別に、`expor OS_DOMAIN_ID` しないと動きませんでしたが、

```
./terraformer import ecl --resources=computeServer,computeKeypair,networkNetwork,networkSubnet --connect=true --regions=jp4
```

な感じで、無事 `generated` フォルダに `.tf` とか `terraform.state` とかエクスポートはされました。



## 問題点

まだリソース間の参照関係が正しくエクスポートされないようです。
例えば、 `subnet.network_id => network.id` というような参照関係があるときに、いわゆる Interpolation Syntax に置き換わってくれません。

### こうなってしまう

```
resource "ecl_network_subnet_v2" "subnet_1" {
  allocation_pools {
    end   = "192.168.1.254"
    start = "192.168.1.2"
  }

  cidr        = "192.168.1.0/24"
  enable_dhcp = true
  gateway_ip  = "192.168.1.1"
  ip_version  = "4"
  name        = "subnet_1"
  network_id  = "09a0222f-245d-4694-8c2c-00ccfc9c8917"
  no_gateway  = false
  region      = "jp4"
  tags        {}
  tenant_id   = "9ee80f2a926c49f88f166af47df4e9f5"
}
```

### 本当はこうなってほしい

```
resource "ecl_network_subnet_v2" "subnet_1" {
  allocation_pools {
    end   = "192.168.1.254"
    start = "192.168.1.2"
  }

  cidr        = "192.168.1.0/24"
  enable_dhcp = true
  gateway_ip  = "192.168.1.1"
  ip_version  = "4"
  name        = "subnet_1"
  network_id  = "${ecl_network_network_v2.net_1.id}"
  no_gateway  = false
  region      = "jp4"
  tags        {}
  tenant_id   = "9ee80f2a926c49f88f166af47df4e9f5"
}
```

gcpでnetwork/subnetworkつくって試したらちゃんと上記のようになるんですよね。

何かが悪いのだと思うのでちょっとコードを読み込んでみようかと。

また分かったらこちらに追記します。