はじめに
Terraform から AAP (厳密には Automation Controller)の設定を操作する ansible/aap
プロバイダー 1.0.0
が 2024/05/01 にリリースされました。
これまでも、Terraform から Playbook を呼び出す ansible/ansible
プロバイダーや、逆に Ansible から Terraform を呼び出す cloud.terraform
コレクションがありました。
今回リリースされた Terraform の ansible/aap
プロバイダーは既存のものとは別用途で、 Automation Controller の設定を Terraform から行うものです。Ansiblle でいうと ansible.controller
/ awx.awx
コレクションにあたるものかなと思います。
簡単ですが、ためしてみます。
- 環境
- ansible/aap プロバイダー 1.0.0
- Automation Controller 4.1.0
- Terraform v1.8.2
ansible/aap
プロバイダーの機能
バージョン 1.0.0
での機能は以下のとおりです。現在のところは限定的です。
おためし
構成
インベントリーを1つ作り、その中にグループ、その中に1つのホストを作ります。
インベントリー network_devices グループ ios ホスト ios01
tf ファイル
一通り tf ファイルを作成します。
terraform.tf
terraform { required_providers { aap = { source = "ansible/aap" version = "1.0.0" } } }
providers.tf
provider "aap" { host = "https://192.168.1.99" # Automation Controller の アドレス insecure_skip_verify = true }
ほか、本プロバイダーの provider
ブロックでは、username
や password
も指定できます。
ベタ書きを避けるため、ここではそれぞれ環境変数 AAP_USERNAME
と AAP_PASSWORD
を利用します。この方法は 1.0.0
現在、ドキュメント上には README.md の Acceptance tests でのみ記載があります。
もっと一般的な方法としては、別途 variable
を定義して export TF_VAR_変数名="値"
で設定しておき username = 変数名
のようにしておくのも良いかなと思います。
main.tf
各種リソースの定義をします。
resource "aap_inventory" "network_devices" { name = "network_devices" description = "Managed by Terraform" } resource "aap_group" "ios" { name = "ios" description = "Managed by Terraform" inventory_id = aap_inventory.network_devices.id variables = jsonencode( { "ansible_network_os" : "cisco.ios.ios" } ) } resource "aap_host" "ios01" { name = "ios01" description = "Managed by Terraform" inventory_id = aap_inventory.network_devices.id groups = [aap_group.ios.id] variables = jsonencode( { "ansible_host" : "192.168.1.11" } ) } data "aap_inventory" "network_devices" { id = aap_inventory.network_devices.id }
aap_inventory
リソースで、organization
を指定していませんが、その場合はデフォルトの組織になるそうです。
最後の aap_inventory
データソースはあまり意味はないですが、どんな情報が得られるか確認するために定義します。id
は インベントリー ID を指定します。今回は Terraform 管理化のインベントリーの情報を参照しているため、〜.id
という形で指定しています。Terraform 管理外のものの場合はあらかじめ ID を調べておく必要があります。
outputs.tf
おまけ的に定義した aap_inventory
データーソースで得られる情報の中身を確認するため、output
ブロックも定義します。
output "inventory_details" { value = data.aap_inventory.network_devices }
認証情報の設定
provider
ブロックで直接 username
や password
を指定しなかった代わりに、環境変数を指定しています。
export AAP_USERNAME="admin" export AAP_PASSWORD="dummy_password_xxx"
init
% terraform init Initializing the backend... Initializing provider plugins... - Finding ansible/aap versions matching "1.0.0"... - Installing ansible/aap v1.0.0... - Installed ansible/aap v1.0.0 (self-signed, key ID 41F01D0480007165) ...(略)... Terraform has been successfully initialized! ...(略)...
plan
% terraform plan Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create <= read (data resources) Terraform will perform the following actions: # data.aap_inventory.network_devices will be read during apply # (config refers to values not yet known) <= data "aap_inventory" "network_devices" { + description = (known after apply) + id = (known after apply) + name = (known after apply) + organization = (known after apply) + url = (known after apply) + variables = (known after apply) } # aap_group.ios will be created + resource "aap_group" "ios" { + description = "Managed by Terraform" + id = (known after apply) + inventory_id = (known after apply) + name = "ios" + url = (known after apply) + variables = jsonencode( { + ansible_network_os = "cisco.ios.ios" } ) } # aap_host.ios01 will be created + resource "aap_host" "ios01" { + description = "Managed by Terraform" + enabled = true + groups = [ + (known after apply), ] + id = (known after apply) + inventory_id = (known after apply) + name = "ios01" + url = (known after apply) + variables = jsonencode( { + ansible_host = "192.168.1.11" } ) } # aap_inventory.network_devices will be created + resource "aap_inventory" "network_devices" { + description = "Managed by Terraform" + id = (known after apply) + name = "network_devices" + organization = (known after apply) + url = (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy. Changes to Outputs: + inventory_details = { + description = (known after apply) + id = (known after apply) + name = (known after apply) + organization = (known after apply) + url = (known after apply) + variables = (known after apply) } ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
apply
% terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create <= read (data resources) Terraform will perform the following actions: # data.aap_inventory.network_devices will be read during apply # (config refers to values not yet known) <= data "aap_inventory" "network_devices" { + description = (known after apply) + id = (known after apply) + name = (known after apply) + organization = (known after apply) + url = (known after apply) + variables = (known after apply) } # aap_group.ios will be created + resource "aap_group" "ios" { + description = "Managed by Terraform" + id = (known after apply) + inventory_id = (known after apply) + name = "ios" + url = (known after apply) + variables = jsonencode( { + ansible_network_os = "cisco.ios.ios" } ) } # aap_host.ios01 will be created + resource "aap_host" "ios01" { + description = "Managed by Terraform" + enabled = true + groups = [ + (known after apply), ] + id = (known after apply) + inventory_id = (known after apply) + name = "ios01" + url = (known after apply) + variables = jsonencode( { + ansible_host = "192.168.1.11" } ) } # aap_inventory.network_devices will be created + resource "aap_inventory" "network_devices" { + description = "Managed by Terraform" + id = (known after apply) + name = "network_devices" + organization = (known after apply) + url = (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy. Changes to Outputs: + inventory_details = { + description = (known after apply) + id = (known after apply) + name = (known after apply) + organization = (known after apply) + url = (known after apply) + variables = (known after apply) } 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 aap_inventory.network_devices: Creating... aap_inventory.network_devices: Creation complete after 0s [name=network_devices] data.aap_inventory.network_devices: Reading... aap_group.ios: Creating... data.aap_inventory.network_devices: Read complete after 0s [name=network_devices] aap_group.ios: Creation complete after 0s [name=ios] aap_host.ios01: Creating... aap_host.ios01: Creation complete after 1s [name=ios01] Apply complete! Resources: 3 added, 0 changed, 0 destroyed. Outputs: inventory_details = { "description" = "Managed by Terraform" "id" = 4 "name" = "network_devices" "organization" = 1 "url" = "/api/v2/inventories/4/" "variables" = tostring(null) }
処理はすぐに終わりました。
Outputs:
には aap_inventory
データソースで取得したインベントリの値が表示されました。
確認
無事に、インベントリー、グループ、ホストが作成されていました。
destroy
% terraform destroy aap_inventory.network_devices: Refreshing state... [name=network_devices] data.aap_inventory.network_devices: Reading... aap_group.ios: Refreshing state... [name=ios] data.aap_inventory.network_devices: Read complete after 0s [name=network_devices] aap_host.ios01: Refreshing state... [name=ios01] 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: # aap_group.ios will be destroyed - resource "aap_group" "ios" { - description = "Managed by Terraform" -> null - id = 3 -> null - inventory_id = 4 -> null - name = "ios" -> null - url = "/api/v2/groups/3/" -> null - variables = jsonencode( { - ansible_network_os = "cisco.ios.ios" } ) -> null } # aap_host.ios01 will be destroyed - resource "aap_host" "ios01" { - description = "Managed by Terraform" -> null - enabled = true -> null - groups = [ - 3, ] -> null - id = 4 -> null - inventory_id = 4 -> null - name = "ios01" -> null - url = "/api/v2/hosts/4/" -> null - variables = jsonencode( { - ansible_host = "192.168.1.11" } ) -> null } # aap_inventory.network_devices will be destroyed - resource "aap_inventory" "network_devices" { - description = "Managed by Terraform" -> null - id = 4 -> null - name = "network_devices" -> null - organization = 1 -> null - url = "/api/v2/inventories/4/" -> null } Plan: 0 to add, 0 to change, 3 to destroy. Changes to Outputs: - inventory_details = { - description = "Managed by Terraform" - id = 4 - name = "network_devices" - organization = 1 - url = "/api/v2/inventories/4/" - variables = null } -> null 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 aap_host.ios01: Destroying... [name=ios01] aap_host.ios01: Destruction complete after 1s aap_group.ios: Destroying... [name=ios] aap_group.ios: Destruction complete after 0s aap_inventory.network_devices: Destroying... [name=network_devices] aap_inventory.network_devices: Destruction complete after 0s Destroy complete! Resources: 3 destroyed.
画面を確認すると、無事にインベントリー、グループ、ホストが削除されていました。もちろん、今回作成する前に存在していたその他のリソースは残ったままです。
おわりに
簡単ですが、Terraform の ansible/aap
プロバイダーを使って、インベントリー、グループ、ホストの作成と削除をためしてみました。
バージョン 1.0.0
がリリースされたばかりということで、クレデンシャルやジョブテンプレートの管理には対応していなくて、まだまだ機能は限定的です。ですが、Automation Controller の設定と Terraform の使用感は相性がいいようにも思いました。たとえば、インベントリーとグループ、ホストの関係を、暗黙的な依存で表現でき、かつ tf ファイルの記述順自体は意識しなくてよい点です。
今後も ansible/aap
プロバイダーには注目したいと思います。
今のところ、Automation Controller / AWX を設定の自動化は、機能が充実している Ansible の ansible.controller
/ awx.awx
コレクションを使うのが良いと思います。