Terraform で ACI 上に Route Leak 設定を含む Tenant を作成する

Terraform を使って Cisco ACI に「Route Leak 構成の Tenant を作成する」サンプルをメモしておきます。

構成

Terraform で以下の構成を設定します。

file

Terraform の設定ファイル

Terraform の設定ファイルは以下の通りです。

  1. variables.tf
  2. main.tf
  3. aci.tf

variables.tf

variable "aci_url" { default = "https://10.0.0.1" }
variable "aci_username" { default = "admin" }
variable "aci_password" { default = "password" }
variable "tenant" { default = "Tenant1" }
variable "vrf1" { default = "1_VRF" }
variable "vrf2" { default = "2_VRF" }
variable "contract1" { default = "CT" }

variable "bd1" { default = "VL101_BD" }
variable "bd1_subnet" { default = "10.0.101.254/24" }
variable "bd2" { default = "VL102_BD" }
variable "bd2_subnet" { default = "10.0.102.254/24" }

variable "ap1" { default = "AP" }
variable "physdom" { default = "PhysDom" }
variable "epg1" { default = "VL101_EPG" }
variable "egp1_port1_tdn" { default = "topology/pod-1/paths-201/pathep-[eth1/1]" }
variable "egp1_port1_vlan" { default = "vlan-101" }
variable "epg1_contract1_type" { default = "consumer" }
variable "epg2" { default = "VL102_EPG" }
variable "egp2_port1_tdn" { default = "topology/pod-1/paths-201/pathep-[eth1/2]" }
variable "egp2_port1_vlan" { default = "vlan-102" }
variable "epg2_contract1_type" { default = "provider" }

main.tf

terraform {
  required_providers {
    aci = {
      source  = "CiscoDevNet/aci"
      version = "0.5.4"
    }
  }
}

provider "aci" {
  username = var.aci_username
  password = var.aci_password
  url      = var.aci_url
  insecure = true
}

aci.tf

Route Leak 設定を行うには Application EPG に Subnet を設定しますが、現時点の Terraform には Application EPG Subnet を定義する Resource が有りません。 その為、Application EPG Subnet は aci_rest を使って設定します。

# Tenant
resource "aci_tenant" "tenant" {
  name = var.tenant
}

# VRF
resource "aci_vrf" "vrf1" {
  tenant_dn = aci_tenant.tenant.id
  name      = var.vrf1
}

resource "aci_vrf" "vrf2" {
  tenant_dn = aci_tenant.tenant.id
  name      = var.vrf2
}

# Contract / Subject / Filter
resource "aci_filter" "any" {
    tenant_dn = aci_tenant.tenant.id
    name      = "any_Filt"
}

resource "aci_filter_entry" "entry1" {
    name        = "0010"
    filter_dn   = aci_filter.any.id
    ether_t     = "unspecified"
}

resource "aci_contract" "contract1" {
    tenant_dn = aci_tenant.tenant.id
    name      = var.contract1
  scope     = "tenant"
}

resource "aci_contract_subject" "subject1" {
    contract_dn                  = aci_contract.contract1.id
    name                         = "${var.contract1}_Subj"
    relation_vz_rs_subj_filt_att = [aci_filter.any.id]
}

# BD1
resource "aci_bridge_domain" "bd1" {
  tenant_dn                = aci_tenant.tenant.id
  name                     = var.bd1
  relation_fv_rs_ctx       = aci_vrf.vrf1.id
}

resource "aci_subnet" "bd1_subnet" {
  parent_dn = aci_bridge_domain.bd1.id
  ip        = var.bd1_subnet
  scope     = ["private", "shared"]
}

# BD2
resource "aci_bridge_domain" "bd2" {
  tenant_dn                = aci_tenant.tenant.id
  name                     = var.bd2
  relation_fv_rs_ctx       = aci_vrf.vrf2.id
}

resource "aci_subnet" "bd2_subnet" {
  parent_dn = aci_bridge_domain.bd2.id
  ip        = var.bd2_subnet
  scope     = ["private", "shared"]
}

# Application Profile
resource "aci_application_profile" "ap1" {
  tenant_dn = aci_tenant.tenant.id
  name      = var.ap1
}

# Domain
data "aci_physical_domain" "physdom" {
  name = var.physdom
}

# EPG1
resource "aci_application_epg" "epg1" {
  application_profile_dn = aci_application_profile.ap1.id
  name                   = var.epg1
  relation_fv_rs_bd      = aci_bridge_domain.bd1.id
}

resource "aci_epg_to_domain" "epg1_physdom" {
  application_epg_dn = aci_application_epg.epg1.id
  tdn                = data.aci_physical_domain.physdom.id
}

resource "aci_epg_to_static_path" "egp1_port1" {
  application_epg_dn = aci_application_epg.epg1.id
  tdn                = var.egp1_port1_tdn
  encap              = var.egp1_port1_vlan
}

resource "aci_rest" "epg1_subnet" {
  path       = "/api/mo/uni/tn-${var.tenant}/ap-${var.ap1}/epg-${var.epg1}/subnet-[${var.bd1_subnet}].json"
  class_name = "fvSubnet"
  content = {
    ctrl  = "no-default-gateway"
    ip    = var.bd1_subnet
    scope = "private,shared"
  }
  depends_on = [
    aci_subnet.bd1_subnet,
    aci_application_epg.epg1
  ]
}

resource "aci_epg_to_contract" "epg1_contract1" {
    application_epg_dn = aci_application_epg.epg1.id
    contract_dn        = aci_contract.contract1.id
    contract_type      = var.epg1_contract1_type
}

# EPG2
resource "aci_application_epg" "epg2" {
  application_profile_dn = aci_application_profile.ap1.id
  name                   = var.epg2
  relation_fv_rs_bd      = aci_bridge_domain.bd2.id
}

resource "aci_epg_to_domain" "epg2_physdom" {
  application_epg_dn = aci_application_epg.epg2.id
  tdn                = data.aci_physical_domain.physdom.id
}

resource "aci_epg_to_static_path" "egp2_port1" {
  application_epg_dn = aci_application_epg.epg2.id
  tdn                = var.egp2_port1_tdn
  encap              = var.egp2_port1_vlan
}

resource "aci_rest" "epg2_subnet" {
  path       = "/api/mo/uni/tn-${var.tenant}/ap-${var.ap1}/epg-${var.epg2}/subnet-[${var.bd2_subnet}].json"
  class_name = "fvSubnet"
  content = {
    ctrl  = "no-default-gateway"
    ip    = var.bd2_subnet
    scope = "private,shared"
  }
  depends_on = [
    aci_subnet.bd2_subnet,
    aci_application_epg.epg2
  ]
}

resource "aci_epg_to_contract" "epg2_contract1" {
    application_epg_dn = aci_application_epg.epg2.id
    contract_dn        = aci_contract.contract1.id
    contract_type      = var.epg2_contract1_type
}

コメント

タイトルとURLをコピーしました