Skip to content

Commit

Permalink
Support bridge confguration on segment
Browse files Browse the repository at this point in the history
Add policy_bridge_profile data source and bridge_config clause
on segments.

Signed-off-by: Anna Khmelnitsky <akhmelnitsky@vmware.com>
  • Loading branch information
annakhm committed Sep 21, 2022
1 parent 350f08f commit e8bff0f
Show file tree
Hide file tree
Showing 9 changed files with 354 additions and 0 deletions.
32 changes: 32 additions & 0 deletions nsxt/data_source_nsxt_policy_bridge_profile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Copyright © 2022 VMware, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceNsxtPolicyBridgeProfile() *schema.Resource {
return &schema.Resource{
Read: dataSourceNsxtPolicyBridgeProfileRead,

Schema: map[string]*schema.Schema{
"id": getDataSourceIDSchema(),
"display_name": getDataSourceExtendedDisplayNameSchema(),
"description": getDataSourceDescriptionSchema(),
"path": getPathSchema(),
},
}
}

func dataSourceNsxtPolicyBridgeProfileRead(d *schema.ResourceData, m interface{}) error {
connector := getPolicyConnector(m)

_, err := policyDataSourceResourceRead(d, connector, isPolicyGlobalManager(m), "L2BridgeEndpointProfile", nil)
if err != nil {
return err
}

return nil
}
95 changes: 95 additions & 0 deletions nsxt/data_source_nsxt_policy_bridge_profile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* Copyright © 2022 VMware, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"fmt"
"testing"

"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
ep "github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/sites/enforcement_points"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)

func TestAccDataSourceNsxtPolicyBridgeProfile_basic(t *testing.T) {
name := getAccTestDataSourceName()
testResourceName := "data.nsxt_policy_bridge_profile.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccOnlyLocalManager(t) },
Providers: testAccProviders,
CheckDestroy: func(state *terraform.State) error {
return testAccDataSourceNsxtPolicyBridgeProfileDeleteByName(name)
},
Steps: []resource.TestStep{
{
PreConfig: func() {
if err := testAccDataSourceNsxtPolicyBridgeProfileCreate(name); err != nil {
panic(err)
}
},
Config: testAccNsxtPolicyBridgeProfileReadTemplate(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(testResourceName, "display_name", name),
resource.TestCheckResourceAttr(testResourceName, "description", name),
resource.TestCheckResourceAttrSet(testResourceName, "path"),
),
},
},
})
}

func testAccDataSourceNsxtPolicyBridgeProfileCreate(name string) error {
connector, err := testAccGetPolicyConnector()
if err != nil {
return fmt.Errorf("Error during test client initialization: %v", err)
}

displayName := name
description := name
obj := model.L2BridgeEndpointProfile{
Description: &description,
DisplayName: &displayName,
}

// Generate a random ID for the resource
uuid, _ := uuid.NewRandom()
id := uuid.String()

client := ep.NewEdgeBridgeProfilesClient(connector)
err = client.Patch(defaultSite, defaultEnforcementPoint, id, obj)

if err != nil {
return fmt.Errorf("Error during Bridge Profile creation: %v", err)
}
return nil
}

func testAccDataSourceNsxtPolicyBridgeProfileDeleteByName(name string) error {
connector, err := testAccGetPolicyConnector()
if err != nil {
return fmt.Errorf("Error during test client initialization: %v", err)
}

// Find the object by name
objID, err := testGetObjIDByName(name, "L2BridgeEndpointProfile")
if err != nil {
return nil
}
client := ep.NewEdgeBridgeProfilesClient(connector)
err = client.Delete(defaultSite, defaultEnforcementPoint, objID)
if err != nil {
return fmt.Errorf("Error during Bridge Profile deletion: %v", err)
}
return nil
}

func testAccNsxtPolicyBridgeProfileReadTemplate(name string) string {
return fmt.Sprintf(`
data "nsxt_policy_bridge_profile" "test" {
display_name = "%s"
}`, name)
}
1 change: 1 addition & 0 deletions nsxt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ func Provider() *schema.Provider {
"nsxt_policy_bfd_profile": dataSourceNsxtPolicyBfdProfile(),
"nsxt_policy_intrusion_service_profile": dataSourceNsxtPolicyIntrusionServiceProfile(),
"nsxt_policy_lb_service": dataSourceNsxtPolicyLbService(),
"nsxt_policy_bridge_profile": dataSourceNsxtPolicyBridgeProfile(),
},

ResourcesMap: map[string]*schema.Resource{
Expand Down
96 changes: 96 additions & 0 deletions nsxt/resource_nsxt_policy_segment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,69 @@ func TestAccResourceNsxtPolicySegment_withProfiles(t *testing.T) {
})
}

var testAccSegmentBridgeProfileName = getAccTestResourceName()

func TestAccResourceNsxtPolicySegment_withBridge(t *testing.T) {
name := getAccTestResourceName()
testResourceName := "nsxt_policy_segment.test"
tzName := getOverlayTransportZoneName()
vlanTzName := getVlanTransportZoneName()
vlan := "12"
vlanUpdated := "20"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t); testAccOnlyLocalManager(t) },
Providers: testAccProviders,
CheckDestroy: func(state *terraform.State) error {
err := testAccNsxtPolicySegmentCheckDestroy(state, name)
if err != nil {
return err
}

return testAccDataSourceNsxtPolicyBridgeProfileDeleteByName(testAccSegmentBridgeProfileName)
},
Steps: []resource.TestStep{
{
PreConfig: func() {
if err := testAccDataSourceNsxtPolicyBridgeProfileCreate(testAccSegmentBridgeProfileName); err != nil {
panic(err)
}
},
Config: testAccNsxtPolicySegmentWithBridgeTemplate(tzName, vlanTzName, name, vlan),
Check: resource.ComposeTestCheckFunc(
testAccNsxtPolicySegmentExists(testResourceName),
resource.TestCheckResourceAttr(testResourceName, "display_name", name),
resource.TestCheckResourceAttr(testResourceName, "bridge_config.#", "1"),
resource.TestCheckResourceAttrSet(testResourceName, "bridge_config.0.profile_path"),
resource.TestCheckResourceAttrSet(testResourceName, "bridge_config.0.transport_zone_path"),
resource.TestCheckResourceAttr(testResourceName, "bridge_config.0.vlan_ids.#", "1"),
resource.TestCheckResourceAttr(testResourceName, "bridge_config.0.vlan_ids.0", vlan),
),
},
{
Config: testAccNsxtPolicySegmentWithBridgeTemplate(tzName, vlanTzName, name, vlanUpdated),
Check: resource.ComposeTestCheckFunc(
testAccNsxtPolicySegmentExists(testResourceName),
resource.TestCheckResourceAttr(testResourceName, "display_name", name),
resource.TestCheckResourceAttr(testResourceName, "bridge_config.#", "1"),
resource.TestCheckResourceAttrSet(testResourceName, "bridge_config.0.profile_path"),
resource.TestCheckResourceAttrSet(testResourceName, "bridge_config.0.transport_zone_path"),
resource.TestCheckResourceAttr(testResourceName, "bridge_config.0.vlan_ids.#", "1"),
resource.TestCheckResourceAttr(testResourceName, "bridge_config.0.vlan_ids.0", vlanUpdated),
),
},
{
Config: testAccNsxtPolicySegmentWithBridgeRemoveAll(tzName, name),
Check: resource.ComposeTestCheckFunc(
testAccNsxtPolicySegmentExists(testResourceName),
resource.TestCheckResourceAttr(testResourceName, "display_name", name),
resource.TestCheckResourceAttr(testResourceName, "bridge_config.#", "0"),
),
},
},
})
}

func TestAccResourceNsxtPolicySegment_withDhcp(t *testing.T) {
name := getAccTestResourceName()
testResourceName := "nsxt_policy_segment.test"
Expand Down Expand Up @@ -569,6 +632,39 @@ resource "nsxt_policy_segment" "test" {
`, name)
}

func testAccNsxtPolicySegmentWithBridgeTemplate(tzName string, bridgeTzName string, name string, vlan string) string {
return testAccNsxtPolicySegmentDeps(tzName) + fmt.Sprintf(`
data "nsxt_policy_bridge_profile" "test" {
display_name = "%s"
}
data "nsxt_policy_transport_zone" "bridge" {
display_name = "%s"
}
resource "nsxt_policy_segment" "test" {
display_name = "%s"
transport_zone_path = data.nsxt_policy_transport_zone.test.path
bridge_config {
profile_path = data.nsxt_policy_bridge_profile.test.path
transport_zone_path = data.nsxt_policy_transport_zone.bridge.path
vlan_ids = ["%s"]
}
}
`, testAccSegmentBridgeProfileName, bridgeTzName, name, vlan)
}

func testAccNsxtPolicySegmentWithBridgeRemoveAll(tzName string, name string) string {
return testAccNsxtPolicySegmentDeps(tzName) + fmt.Sprintf(`
resource "nsxt_policy_segment" "test" {
display_name = "%s"
transport_zone_path = data.nsxt_policy_transport_zone.test.path
}
`, name)
}

func testAccNsxtPolicySegmentBasicAdvConfigTemplate(tzName string, name string) string {
return testAccNsxtPolicySegmentDeps(tzName) + fmt.Sprintf(`
Expand Down
86 changes: 86 additions & 0 deletions nsxt/segment_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,28 @@ func getPolicySegmentSubnetSchema() *schema.Resource {
}
}

func getPolicySegmentBridgeConfigSchema() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"profile_path": getPolicyPathSchema(true, false, "profile path"),
"uplink_teaming_policy": {
Type: schema.TypeString,
Optional: true,
},
"vlan_ids": {
Type: schema.TypeList,
Description: "VLAN specification for bridge endpoint",
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validateVLANIdOrRange,
},
Required: true,
},
"transport_zone_path": getPolicyPathSchema(true, false, "vlan transport zone path"),
},
}
}

func getPolicySegmentL2ExtensionConfigurationSchema() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
Expand Down Expand Up @@ -328,6 +350,12 @@ func getPolicyCommonSegmentSchema(vlanRequired bool, isFixed bool) map[string]*s
Default: model.Segment_REPLICATION_MODE_MTEP,
ValidateFunc: validation.StringInSlice(replicationModeValues, false),
},
"bridge_config": {
Type: schema.TypeList,
Description: "Bridge configuration",
Elem: getPolicySegmentBridgeConfigSchema(),
Optional: true,
},
}

if isFixed {
Expand Down Expand Up @@ -808,6 +836,10 @@ func policySegmentResourceToInfraStruct(id string, d *schema.ResourceData, isVla
}
}

if !isGlobalManager {
setBridgeConfigInStruct(d, &obj)
}

childSegment := model.ChildSegment{
Segment: &obj,
ResourceType: "ChildSegment",
Expand Down Expand Up @@ -863,6 +895,40 @@ func resourceNsxtPolicySegmentExists(gwPath string, isFixed bool) func(id string
}
}

func setBridgeConfigInStruct(d *schema.ResourceData, segment *model.Segment) {

configs := d.Get("bridge_config").([]interface{})
if len(configs) == 0 {
return
}

for _, config := range configs {
bridgeConfig := config.(map[string]interface{})
profilePath := bridgeConfig["profile_path"].(string)
policyName := bridgeConfig["uplink_teaming_policy"].(string)
tzPath := bridgeConfig["transport_zone_path"].(string)
vlanIds := interfaceListToStringList(bridgeConfig["vlan_ids"].([]interface{}))

profile := model.BridgeProfileConfig{
BridgeProfilePath: &profilePath,
}

if len(policyName) > 0 {
profile.UplinkTeamingPolicyName = &policyName
}
if len(tzPath) > 0 {
profile.VlanTransportZonePath = &tzPath
}

if len(vlanIds) > 0 {
profile.VlanIds = vlanIds
}

segment.BridgeProfiles = append(segment.BridgeProfiles, profile)

}
}

func nsxtPolicySegmentProfilesSetInStruct(d *schema.ResourceData, segment *model.Segment) error {
var children []*data.StructValue

Expand Down Expand Up @@ -1230,6 +1296,22 @@ func nsxtPolicySegmentProfilesRead(d *schema.ResourceData, m interface{}) error
return nil
}

func setSegmentBridgeConfigInSchema(d *schema.ResourceData, obj *model.Segment) {
var configs []map[string]interface{}

for _, profile := range obj.BridgeProfiles {
config := make(map[string]interface{})
config["profile_path"] = profile.BridgeProfilePath
config["uplink_teaming_policy"] = profile.UplinkTeamingPolicyName
config["vlan_ids"] = profile.VlanIds
config["transport_zone_path"] = profile.VlanTransportZonePath

configs = append(configs, config)
}

d.Set("bridge_config", configs)
}

func nsxtPolicyLocalManagerGetSegment(connector *client.RestConnector, id string, gwPath string, isFixed bool) (model.Segment, error) {
if !isFixed {
return infra.NewSegmentsClient(connector).Get(id)
Expand Down Expand Up @@ -1386,6 +1468,10 @@ func nsxtPolicySegmentRead(d *schema.ResourceData, m interface{}, isVlan bool, i
}
}

if !isPolicyGlobalManager(m) {
setSegmentBridgeConfigInSchema(d, &obj)
}

return nil
}

Expand Down
1 change: 1 addition & 0 deletions nsxt/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const edgeClusterDefaultName string = "edgecluster1"
const vlanTransportZoneName string = "transportzone2"
const overlayTransportZoneNamePrefix string = "1-transportzone"
const macPoolDefaultName string = "DefaultMacPool"
const defaultEnforcementPoint string = "default"

const realizationResourceName string = "data.nsxt_policy_realization_info.realization_info"
const defaultTestResourceName string = "terraform-acctest"
Expand Down
Loading

0 comments on commit e8bff0f

Please sign in to comment.