ACI Simulatorを使ってNexus-as-Codeのチュートリアルを行う

## 概要
Cisco ACI に対する設定をGUIでポチるのではなく、Terraform を使って設定自動化・構成管理できるようにしたい。DevNet に Nexus-as-Code (NAC) の チュートリアルがあるのでこれを手元の環境で動かしてみて練習する。
https://developer.cisco.com/docs/nexus-as-code/aci-introduction/#introduction

## 環境
- ACI Simulator 6.0(5h)
- Terraform v1.8.5

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/1db999e6-3241-c759-d0f1-d15541e27a31.png)


## Tenant Deployment
このような構成のテナントを新規にデプロイする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/5e79147e-b923-d13b-3c52-c59718733ff0.png)


ディレクトリ構造
```
.
├── data
│   └── tenant_DEV_nac.yaml
├── main.tf
```

main.tf
今回はテナント設定のみを行うためTenant Moduleのみ有効化した。
```
$ cat main.tf
terraform {
  required_providers {
    aci = {
      source = "CiscoDevNet/aci"
    }
  }
}

provider "aci" {
  username = "admin"
  password = "**********"
  url      = "https://{ACI Simulator management IP}"
}

module "aci" {
  source  = "netascode/nac-aci/aci"
  version = "0.9.0"

  yaml_directories = ["data"]

  manage_access_policies    = false
  manage_fabric_policies    = false
  manage_pod_policies       = false
  manage_node_policies      = false
  manage_interface_policies = false
  manage_tenants            = true
}
```

tenant_DEV_nac.yaml
```
$ cat data/tenant_DEV_nac.yaml
---
apic:
  tenants:
    - name: DEV

      vrfs:
        - name: DEV.DEV-VRF

      bridge_domains:
        - name: 10.1.200.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.200.1/24

        - name: 10.1.201.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.201.1/24

        - name: 10.1.202.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.202.1/24

      application_profiles:
        - name: VLANS
          endpoint_groups:
            - name: VLAN200
              bridge_domain: 10.1.200.0_24

            - name: VLAN201
              bridge_domain: 10.1.201.0_24

            - name: VLAN202
              bridge_domain: 10.1.202.0_24
```

最初は何もない状態なので、デプロイすると新規にリソースが作成される。
```
$ terraform init
$ terraform plan
$ terraform apply
(snip)
Apply complete! Resources: 22 added, 0 changed, 0 destroyed.
```

リソースが作成された。このオブジェクトはTerraformによって作成されたので、変更するときはTerraformのみを使うことお勧めしますという注意書きがされている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/8b5b4b7d-da94-0ee7-0854-618f9fa82ff2.png)


## リソースを追加する
L3BD/Subnetを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/3ae8beaa-41b4-1b41-29ee-e9041e6fc13b.png)

10.1.203.0_24というL3BDをYAMLへ追加する。
```
$ cat tenant_DEV_nac.yaml
---
apic:
  tenants:
    - name: DEV

      vrfs:
        - name: DEV.DEV-VRF

      bridge_domains:
        - name: 10.1.200.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.200.1/24

        - name: 10.1.201.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.201.1/24

        - name: 10.1.202.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.202.1/24

        ### Adding additional resources
        - name: 10.1.203.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.203.1/24

      application_profiles:
        - name: VLANS
          endpoint_groups:
            - name: VLAN200
              bridge_domain: 10.1.200.0_24

            - name: VLAN201
              bridge_domain: 10.1.201.0_24

            - name: VLAN202
              bridge_domain: 10.1.202.0_24
```

今回は3つのリソースが作成され、既存のリソースは影響を受けずそのまま残る。
```
$ terraform apply
/snip/
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvBD: Creating...
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvBD: Creation complete after 0s [id=uni/tn-DEV/BD-10.1.203.0_24]
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvRsCtx: Creating...
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvRsCtx: Creation complete after 0s [id=uni/tn-DEV/BD-10.1.203.0_24/rsctx]
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvSubnet["10.1.203.1/24"]: Creating...
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvSubnet["10.1.203.1/24"]: Creation complete after 0s [id=uni/tn-DEV/BD-10.1.203.0_24/subnet-[10.1.203.1/24]]

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

10.1.203.0_24のL3BD/Subnetが追加された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/81ca350c-6d62-513d-03ca-0c8c4b414750.png)

## リソースを削除する
先ほど追加した10.1.203.0_24のL3BD/SubnetをYAMLから削除してapplyしてみる。

```
$ cat tenant_DEV_nac.yaml
---
apic:
  tenants:
    - name: DEV #Make sure there is no existing tenant named DEV

      vrfs:
        - name: DEV.DEV-VRF

      bridge_domains:
        - name: 10.1.200.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.200.1/24

        - name: 10.1.201.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.201.1/24

        - name: 10.1.202.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.202.1/24

      application_profiles:
        - name: VLANS
          endpoint_groups:
            - name: VLAN200
              bridge_domain: 10.1.200.0_24

            - name: VLAN201
              bridge_domain: 10.1.201.0_24

            - name: VLAN202
              bridge_domain: 10.1.202.0_24
```

YAMLから削除したリソースが、実機のリソースとしてもdestroyされた。
```
$ terraform apply
/snip/
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvSubnet["10.1.203.1/24"]: Destroying... [id=uni/tn-DEV/BD-10.1.203.0_24/subnet-[10.1.203.1/24]]
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvSubnet["10.1.203.1/24"]: Destruction complete after 0s
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvRsCtx: Destroying... [id=uni/tn-DEV/BD-10.1.203.0_24/rsctx]
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvRsCtx: Destruction complete after 0s
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvBD: Destroying... [id=uni/tn-DEV/BD-10.1.203.0_24]
module.aci.module.aci_bridge_domain["DEV/10.1.203.0_24"].aci_rest_managed.fvBD: Destruction complete after 0s

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

## Contractを追加する
VLAN200 と VLAN201 間の HTTP および HTTPS トラフィックを許可するContractを追加してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/bfcf4835-87c6-feab-31be-4db1d79935ad.png)

```
$ cat tenant_DEV_nac.yaml
---
apic:
  tenants:
    - name: DEV

      vrfs:
        - name: DEV.DEV-VRF

      bridge_domains:
        - name: 10.1.200.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.200.1/24

        - name: 10.1.201.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.201.1/24

        - name: 10.1.202.0_24
          vrf: DEV.DEV-VRF
          subnets:
          - ip: 10.1.202.1/24

      application_profiles:
        - name: VLANS
          endpoint_groups:
            - name: VLAN200
              bridge_domain: 10.1.200.0_24
              contracts:
                consumers:
                  - PERMIT-TO-VLAN201

            - name: VLAN201
              bridge_domain: 10.1.201.0_24
              contracts:
                providers:
                  - PERMIT-TO-VLAN201

            - name: VLAN202
              bridge_domain: 10.1.202.0_24

      filters:
        - name: TCP-SRC-ANY-TO-DST-80
          entries:
            - name: SRC-ANY-TO-DST-80
              destination_from_port: 80
              destination_to_port: 80
        - name: TCP-SRC-ANY-TO-DST-443
          entries:
            - name: SRC-ANY-TO-DST-443
              destination_from_port: 443
              destination_to_port: 443

      contracts:
        - name: PERMIT-TO-VLAN201
          subjects:
            - name: TCP-ENTRIES
              filters:
                - filter: TCP-SRC-ANY-TO-DST-80
                - filter: TCP-SRC-ANY-TO-DST-443
```

VLAN200 と VLAN201 間のContractが追加されたことが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/05813d4f-0868-329f-58e6-31e39bce825e.png)

## 本来はやらないが手動で設定を削除してみる
GUI画面上からContractを削除する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3359374/86fb9cf8-4a3e-125f-7be0-4c5bd47f2532.png)

Terraformは構成のドリフトを検出することができて、YAMLが正ならば改めてapplyすれば解消できる。
```
$ terraform apply
/snip/
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzBrCP: Creating...
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzBrCP: Creation complete after 0s [id=uni/tn-DEV/brc-PERMIT-TO-VLAN201]
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzSubj["TCP-ENTRIES"]: Creating...
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzSubj["TCP-ENTRIES"]: Creation complete after 1s [id=uni/tn-DEV/brc-PERMIT-TO-VLAN201/subj-TCP-ENTRIES]
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzRsSubjFiltAtt["TCP-ENTRIES-TCP-SRC-ANY-TO-DST-80"]: Creating...
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzRsSubjFiltAtt["TCP-ENTRIES-TCP-SRC-ANY-TO-DST-443"]: Creating...
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzRsSubjFiltAtt["TCP-ENTRIES-TCP-SRC-ANY-TO-DST-443"]: Creation complete after 0s [id=uni/tn-DEV/brc-PERMIT-TO-VLAN201/subj-TCP-ENTRIES/rssubjFiltAtt-TCP-SRC-ANY-TO-DST-443]
module.aci.module.aci_contract["DEV/PERMIT-TO-VLAN201"].aci_rest_managed.vzRsSubjFiltAtt["TCP-ENTRIES-TCP-SRC-ANY-TO-DST-80"]: Creation complete after 0s [id=uni/tn-DEV/brc-PERMIT-TO-VLAN201/subj-TCP-ENTRIES/rssubjFiltAtt-TCP-SRC-ANY-TO-DST-80]

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

## 片付け
```
$ terraform destroy
/snip/
Destroy complete! Resources: 32 destroyed.
```