oci cliのconfigファイルでTerraformへプロバイダ情報を渡す

2019/12/18 新規作成
2021/09/07 いただいたコメントを本文へ組み込み

# やりたいこと
- Terraformでoracle cloud(oci)を管理する際に、プロバイダ情報を変数で渡さずにoci cliのconfigファイルの情報を使わせる

※ Terraformのdocに書いてあったのでやってみた。

```
Using the SDK and CLI Configuration FileIt is possible to define the required provider values 
in the same ~/.oci/config file that the SDKs and CLI support. For details on setting up this 
configuration see SDK and CLI Configuration File.

Note: only the [default] profile is supported, and the parameter names are slightly different. 
Provider block from terraform config can be completely removed if all API Key based 
authentication required values are provided as environment variables, in a *.tfvars file or 
~/.oci/config. When using empty provider block, private_key_password if required should to be 
set in ~/.oci/config.
```
https://www.terraform.io/docs/providers/oci/index.html

:::note info
OCIのマニュアルにも記載されたようです。
https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformproviderconfiguration.htm

（@Bacalhau さんから教えていただいた情報）
:::



# 一応できた方法

## oci cliのconfigを作る

既にある場合は編集は不要。

```config
[DEFAULT]
user=ocid1.user.oc1..xxxx
fingerprint=xx:xx:xx:xx:xx:xx
key_file=XXX\oci_api_key.pem
tenancy=ocid1.tenancy.oc1..xxxx
region=us-ashburn-1
```

・[DEFAULT]のみ使える
・デフォルトのパス、ファイルのみ使える（~/.oci/config）
・Terraform用の設定は不要（Terraformの変数名で記載する必要なし）
・鍵にパスフレーズを使っている場合はconfigファイルに書いてある必要がある

:::note info
現在は、「config_file_profile」を使用して、[DEFAULT]以外のプロファイルも指定できるとのこと（未検証）。
https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformproviderconfiguration.htm

（@Bacalhau さんから教えていただいた情報）
:::


## providerブロックは普通に書く

```provider.tf
provider "oci" {
  tenancy_ocid = var.tenancy_ocid
  user_ocid = var.user_ocid
  fingerprint = var.fingerprint
  private_key_path = var.private_key_path
  region = var.region
}
```

:::note info
providerブロックに、config_file_profileを含めることでプロファイルを指定できるとのこと（未検証）。
provider "oci" {
  tenancy_ocid = var.tenancy_ocid
  config_file_profile= var.config_file_profile
}
https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformproviderconfiguration.htm

（@Bacalhau さんから教えていただいた情報）
:::


## 変数の定義もする

```provider-var.tf
variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "region" {}
```

:::note info
変数の定義を{default=""}とすることで、後の出力例で出てくる変数の値を聞かれる問題を解決できるとのこと（未検証）。


（@Bacalhau さんから教えていただいた情報）
:::


## 適当なリソースを作る

```drg.tf
resource "oci_core_drg" "test_drg" {
    compartment_id = "ocid1.tenancy.oc1..xxxx"
    display_name = "ocidrg"
}
```

## 実行

- terraform planの実行例


```shell
> terraform plan
var.fingerprint
  Enter a value: <--★ 聞かれるけど無視

var.private_key_path
  Enter a value: <--★ 聞かれるけど無視

var.region
  Enter a value: <--★ 聞かれるけど無視

var.tenancy_ocid
  Enter a value: <--★ 聞かれるけど無視

var.user_ocid
  Enter a value: <--★ 聞かれるけど無視

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # oci_core_drg.test_drg will be created
  + resource "oci_core_drg" "test_drg" {
      + compartment_id = "ocid1.tenancy.oc1..xxxx"
      + defined_tags   = (known after apply)
      + display_name   = "ocidrg"
      + freeform_tags  = (known after apply)
      + id             = (known after apply)
      + state          = (known after apply)
      + time_created   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
```


- terraform applyの実行例


```
> terraform apply
var.fingerprint
  Enter a value: <--★ 聞かれるけど無視

var.private_key_path
  Enter a value: <--★ 聞かれるけど無視

var.region
  Enter a value: <--★ 聞かれるけど無視

var.tenancy_ocid
  Enter a value: <--★ 聞かれるけど無視

var.user_ocid
  Enter a value: <--★ 聞かれるけど無視


An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # oci_core_drg.test_drg will be created
  + resource "oci_core_drg" "test_drg" {
      + compartment_id = "ocid1.tenancy.oc1..xxxx"
      + defined_tags   = (known after apply)
      + display_name   = "ocidrg"
      + freeform_tags  = (known after apply)
      + id             = (known after apply)
      + state          = (known after apply)
      + time_created   = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

oci_core_drg.test_drg: Creating...
oci_core_drg.test_drg: Creation complete after 9s [id=ocid1.drg.oc1.iad.xxxx]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

環境変数やファイルで変数を指定していないのに（oci cliのconfigファイルがあるというだけで）実行できた！

が、いちいち変数の値を聞かれるの**とてもうっとうしい**。
なんとかしたい（未解決）
（けど、変数指定し忘れで勝手にconfig使われるのも怖いか…）

# 試したこと

## oci cliのconfigファイルが無い場合

ちゃんと怒られる。(=やっぱりoci cliのconfig見に行ってくれたんだ）

```shell
> terraform plan
var.fingerprint
  Enter a value:

var.private_key_path
  Enter a value:

var.region
  Enter a value:

var.tenancy_ocid
  Enter a value:

var.user_ocid
  Enter a value:

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


Error: can not create client, bad configuration: did not find a proper configuration for tenancy

  on provider.tf line 2, in provider "oci":
   2: provider "oci" {
```

## oci cliのconfigを変数ファイルとして指定した場合

Terraformとしては想定してない文字列の連続なので、エラー（当然）

```shell
> terraform plan -var-file xxx\.oci\config

Error: Argument or block definition required

  on xxx\.oci\config line 1:
   1: [DEFAULT]

An argument or block definition is required here.
（略）
```


## コンパートメントのOCIDも変数だった場合（oci_cli_rcを使ってくれるか）

結論：ダメだった

drg.tfのコンパートメントOCIDをしている箇所を変数に変更

```drg.tf
resource "oci_core_drg" "test_drg" {
    compartment_id = var.compid
    display_name = "ocidrg"
}
```

変数を定義

```var.tf
variable "compid" {
}
```

oci_cli_rcでコンパートメントのOCIDを定義

```
[DEFAULT]
compartment-id = ocid1.compartment.oc1..xxxx
```

実行

```
> terraform plan
var.compid
  Enter a value: <--★ ちゃんと聞かれてる。無視。

var.fingerprint
  Enter a value:

var.private_key_path
  Enter a value:

var.region
  Enter a value:

var.tenancy_ocid
  Enter a value:

var.user_ocid
  Enter a value:

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

oci_core_drg.test_drg: Refreshing state... [id=ocid1.drg.oc1.iad.xxxx]

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # oci_core_drg.test_drg will be updated in-place
  ~ resource "oci_core_drg" "test_drg" {
      - compartment_id = "ocid1.tenancy.oc1..xxxx" -> null ★nullになっちゃった！
        defined_tags   = {}
        display_name   = "ocidrg"
        freeform_tags  = {}
        id             = "ocid1.drg.oc1.iad.xxxx"
        state          = "AVAILABLE"
        time_created   = "2019-12-17 15:37:19.027 +0000 UTC"
    }

Plan: 0 to add, 1 to change, 0 to destroy.

------------------------------------------------------------------------
```

# 使い道
- あんまりなさそう。
- oci cliの入っている環境で、最短距離でterraform実行まで行きたいとき、くらい？
- [DEFAULT]以外のプロファイルを指定できるようになったら使い道が出てくる（terraformのworkspaceの代替？）


:::note info
[DEFAULT] 以外のプロファイルも指定できるようになったとのことなので、それなりに使い道は出てきそうです。（世の中に落ちてるterraformテンプレートのサンプルをさくっと自環境で試したい時など）
:::