Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NSX-T ALB Virtual Service Transparent mode and Pool Firewall Group membership (VCD 10.4.1+) #1024

Merged
merged 15 commits into from
Mar 27, 2023
4 changes: 4 additions & 0 deletions .changes/v3.9.0/1024-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
* Resource and data source `vcd_nsxt_alb_virtual_service` add support for Transparent mode in VCD
10.4.1+ via field `is_transparent_mode_enabled` [GH-1024]
* Resource and data source `vcd_nsxt_alb_pool` add support for Pool Group Membership via field
`member_group_id` [GH-1024]
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ require (
google.golang.org/grpc v1.51.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
)

replace github.com/vmware/go-vcloud-director/v2 => github.com/Didainius/go-vcloud-director/v2 v2.17.0-alpha.2.0.20230322053717-0f7472794ecd

//replace github.com/vmware/go-vcloud-director/v2 => ../go-vcloud-director
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Didainius/go-vcloud-director/v2 v2.17.0-alpha.2.0.20230322053717-0f7472794ecd h1:W/M0ufY6z8qtoWk1pIn25nsvOOj3P44RqJKEaklSuo0=
github.com/Didainius/go-vcloud-director/v2 v2.17.0-alpha.2.0.20230322053717-0f7472794ecd/go.mod h1:QPxGFgrUcSyzy9IlpwDE4UNT3tsOy2047tJOPEJ4nlw=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
Expand Down Expand Up @@ -196,8 +198,6 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/vmware/go-vcloud-director/v2 v2.20.0-alpha.8 h1:1lnGP2ce3JHGWpzs705YqSd7hAZ9fTRpREPNaxRjisU=
github.com/vmware/go-vcloud-director/v2 v2.20.0-alpha.8/go.mod h1:QPxGFgrUcSyzy9IlpwDE4UNT3tsOy2047tJOPEJ4nlw=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down
2 changes: 2 additions & 0 deletions scripts/skip-upgrade-tests.txt
adezxc marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,5 @@ vcd.TestAccVcdVAppVmMulti.tf v3.7.0 "vApp network removal from powered on vApp i
vcd.ResourceSchema-vcd_nsxt_alb_settings.tf v3.8.2 "New fields to support latest ALB features"
vcd.ResourceSchema-vcd_vapp_org_network.tf v3.8.2 "New field 'reboot_vapp_on_removal'"
vcd.ResourceSchema-vcd_vapp_network.tf v3.8.2 "New field 'reboot_vapp_on_removal'"
vcd.ResourceSchema-vcd_nsxt_alb_virtual_service.tf v3.8.2 "New field 'is_transparent_mode_enabled'"
vcd.ResourceSchema-vcd_nsxt_alb_pool.tf v3.8.2 "New field 'member_group_id'"
1 change: 1 addition & 0 deletions vcd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ type TestConfig struct {
NsxtAlbControllerUser string `json:"nsxtAlbControllerUser"`
NsxtAlbControllerPassword string `json:"nsxtAlbControllerPassword"`
NsxtAlbImportableCloud string `json:"nsxtAlbImportableCloud"`
NsxtAlbServiceEngineGroup string `json:"nsxtAlbServiceEngineGroup"`
RoutedNetwork string `json:"routedNetwork"`
IsolatedNetwork string `json:"isolatedNetwork"`
DirectNetwork string `json:"directNetwork"`
Expand Down
5 changes: 5 additions & 0 deletions vcd/datasource_vcd_nsxt_alb_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ func datasourceVcdAlbPool() *schema.Resource {
},
},
},
"member_group_id": {
Type: schema.TypeString,
Computed: true,
Description: "ID of Firewall Group to use for pool Membership (VCD 10.4.1+)",
lvirbalas marked this conversation as resolved.
Show resolved Hide resolved
},
"health_monitor": {
Type: schema.TypeSet,
Computed: true,
Expand Down
5 changes: 5 additions & 0 deletions vcd/datasource_vcd_nsxt_alb_virtual_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ func datasourceVcdAlbVirtualService() *schema.Resource {
},
},
},
"is_transparent_mode_enabled": {
Type: schema.TypeBool,
Computed: true,
Description: "Preserves Client IP on a Virtual Service when enabled",
adambarreiro marked this conversation as resolved.
Show resolved Hide resolved
},
},
}
}
Expand Down
207 changes: 203 additions & 4 deletions vcd/remove_leftovers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package vcd

import (
"fmt"
"github.com/vmware/go-vcloud-director/v2/govcd"
"github.com/vmware/go-vcloud-director/v2/types/v56"
"net/url"
"regexp"
"strings"

"github.com/vmware/go-vcloud-director/v2/govcd"
"github.com/vmware/go-vcloud-director/v2/types/v56"
)

// This file contains routines that clean up the test suite after failed tests
Expand Down Expand Up @@ -87,16 +89,24 @@ var alsoDelete = entityList{
var isTest = regexp.MustCompile(`^[Tt]est`)

// alwaysShow lists the resources that will always be shown
var alwaysShow = []string{"vcd_org", "vcd_catalog", "vcd_org_vdc"}
var alwaysShow = []string{"vcd_org", "vcd_catalog", "vcd_org_vdc", "vcd_nsxt_alb_controller"}

func removeLeftovers(govcdClient *govcd.VCDClient, verbose bool) error {
if verbose {
fmt.Printf("Start leftovers removal\n")
}

// NSX-T ALB configuration Hierarchical cleanup is separate from main hierarchy as even if the
// Org is going to be deleted - NSX-T ALB configuration must be cleaned up first
err := removeLeftoversNsxtAlb(govcdClient, verbose)
Didainius marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return fmt.Errorf("error removing NSX-T ALB leftovers: %s", err)
}

// traverses the VCD hierarchy, starting at the Org level
orgs, err := govcdClient.GetOrgList()
if err != nil {
return fmt.Errorf("error retrieving orgs list: %s", err)
return fmt.Errorf("error retrieving Orgs list: %s", err)
}
// --------------------------------------------------------------
// organizations
Expand Down Expand Up @@ -291,6 +301,195 @@ func removeLeftovers(govcdClient *govcd.VCDClient, verbose bool) error {
return nil
}

// removeLeftoversNsxtAlb is responsible for cleanup up NSX-T ALB leftovers
// Note. Due to the fact that we need to test Controller creation and deletion - there should never
// remain any NSX-T ALB leftovers after the test.
//
// Hierarchy of NSX-T ALB Configurations is:
// Provider part (Infrastructure configuration)
// 1. NSX-T ALB Controller (vcd_nsxt_alb_controller)
// 2. NSX-T Clouds (vcd_nsxt_alb_cloud)
// 3. NSX-T Service Engine Groups (vcd_nsxt_alb_service_engine_group)
// Tenant part (Edge Gateway children)
// 4. Edge Gateway settings (vcd_nsxt_alb_settings)
// 5. Edge Gateway Service Engine Group assignment (vcd_nsxt_alb_edgegateway_service_engine_group)
// 6. NSX-T ALB Pools (vcd_nsxt_alb_pool)
// 7. NSX-T ALB Virtual Services (vcd_nsxt_alb_virtual_service)
// This structure must be cleaned up in reverse order (starting from 7 and ending
// with 1) so that no dependency constraints are violated
func removeLeftoversNsxtAlb(govcdClient *govcd.VCDClient, verbose bool) error {
// --------------------------------------------------------------
// vcd_nsxt_alb_controller
// --------------------------------------------------------------
albControllers, err := govcdClient.GetAllAlbControllers(nil)
if err != nil {
return fmt.Errorf("error retrieving NSX-T ALB Controllers list: %s", err)
}
for _, albController := range albControllers {
albControllertoBeDeleted := shouldDeleteEntity(alsoDelete, doNotDelete, albController.NsxtAlbController.Name, "vcd_nsxt_alb_controller", 0, verbose)

// --------------------------------------------------------------
// vcd_nsxt_alb_cloud
// --------------------------------------------------------------
albClouds, err := govcdClient.GetAllAlbClouds(nil)
if err != nil {
return fmt.Errorf("error retrieving NSX-T ALB Clouds list: %s", err)
}
for _, albCloud := range albClouds {
albCloudToBeDeleted := shouldDeleteEntity(alsoDelete, doNotDelete, albCloud.NsxtAlbCloud.Name, "vcd_nsxt_alb_cloud", 1, verbose)

// --------------------------------------------------------------
// vcd_nsxt_alb_service_engine_group
// --------------------------------------------------------------
albServiceEngineGroups, err := govcdClient.GetAllAlbServiceEngineGroups("", nil)

if err != nil {
return fmt.Errorf("error retrieving NSX-T ALB Service Engine Groups list: %s", err)
}
for _, albServiceEngineGroup := range albServiceEngineGroups {
albServiceEngineGroupToBeDeleted := shouldDeleteEntity(alsoDelete, doNotDelete, albServiceEngineGroup.NsxtAlbServiceEngineGroup.Name, "vcd_nsxt_alb_service_engine_group", 2, verbose)
if albServiceEngineGroupToBeDeleted {

// --------------------------------------------------------------
// NSX-T ALB Tenant Configuration cleanup
// --------------------------------------------------------------
err = removeLeftoversNsxtAlbTenant(govcdClient, verbose)
if err != nil {
return fmt.Errorf("error removing NSX-T ALB Tenant leftovers: %s", err)
}

// vcd_nsxt_alb_service_engine_group deletion
err = albServiceEngineGroup.Delete()
if err != nil {
return fmt.Errorf("error deleting NSX-T ALB Service Engine Group '%s': %s", albServiceEngineGroup.NsxtAlbServiceEngineGroup.Name, err)
}
}
}

// vcd_nsxt_alb_cloud deletion
if albCloudToBeDeleted {
err = albCloud.Delete()
if err != nil {
return fmt.Errorf("error deleting NSX-T ALB Cloud '%s': %s", albCloud.NsxtAlbCloud.Name, err)
}
}
}

// vcd_nsxt_alb_controller deletion
if albControllertoBeDeleted {
err = albController.Delete()
if err != nil {
return fmt.Errorf("error deleting NSX-T ALB Controller '%s': %s", albController.NsxtAlbController.Name, err)
}
}
}
return nil
}

// removeLeftoversNsxtAlbTenant is responsible for cleanup up NSX-T ALB leftovers in Edge Gateways
// (tenant configuration)
// 1. Edge Gateway settings (vcd_nsxt_alb_settings)
// 2. Edge Gateway Service Engine Group assignment (vcd_nsxt_alb_edgegateway_service_engine_group)
// 3. NSX-T ALB Pools (vcd_nsxt_alb_pool)
// 4. NSX-T ALB Virtual Services (vcd_nsxt_alb_virtual_service)
func removeLeftoversNsxtAlbTenant(govcdClient *govcd.VCDClient, verbose bool) error {
// Iterate over Edge Gateways and ensure no tenant ALB configurations remain
edgeGateways, err := govcdClient.GetAllNsxtEdgeGateways(nil)
if err != nil {
return fmt.Errorf("error retrieving NSX-T Edge Gateway list: %s", err)
}

for _, edgeGateway := range edgeGateways {

// --------------------------------------------------------------
// vcd_nsxt_alb_settings
// --------------------------------------------------------------
albSetting, err := edgeGateway.GetAlbSettings()
if err != nil {
return fmt.Errorf("error retrieving NSX-T ALB Edge Gateway settings: %s", err)
}

if albSetting.Enabled {
// Real name of Edge Gateway would not be matched, but ALB needs to be deleted therefore adding a prefix Test
edgeNameWithPrefix := "Test" + edgeGateway.EdgeGateway.Name
toBeDisabledAlbSettings := shouldDeleteEntity(alsoDelete, doNotDelete, edgeNameWithPrefix, "vcd_nsxt_alb_settings", 3, verbose)
adambarreiro marked this conversation as resolved.
Show resolved Hide resolved

// --------------------------------------------------------------
// vcd_nsxt_alb_edgegateway_service_engine_group
// --------------------------------------------------------------
filterOnEdgeGateway := url.Values{}
filterOnEdgeGateway.Add("filter", fmt.Sprintf("(gatewayRef.id==%s)", edgeGateway.EdgeGateway.ID))
albEdgeGatewayServiceEngineGroups, err := govcdClient.GetAllAlbServiceEngineGroupAssignments(filterOnEdgeGateway)
if err != nil {
return fmt.Errorf("error retrieving NSX-T ALB Edge Gateway Service Engine Group assignments list: %s", err)
}

for _, albEdgeGatewayServiceEngineGroup := range albEdgeGatewayServiceEngineGroups {
// Edge Gateay Service Engine Group Assignment does not have names, therefore we use
adambarreiro marked this conversation as resolved.
Show resolved Hide resolved
// Service Engine Group name as a name for the resource
edgeServiceEngineGroupAssignmentName := albEdgeGatewayServiceEngineGroup.NsxtAlbServiceEngineGroupAssignment.ServiceEngineGroupRef.Name
toBeDeletedAlbEdgeGatewayServiceEngineGroup := shouldDeleteEntity(alsoDelete, doNotDelete, edgeServiceEngineGroupAssignmentName, "vcd_nsxt_alb_edgegateway_service_engine_group", 4, verbose)

// --------------------------------------------------------------
// vcd_nsxt_alb_pool
// --------------------------------------------------------------
albPools, err := govcdClient.GetAllAlbPools(edgeGateway.EdgeGateway.ID, nil)
if err != nil {
return fmt.Errorf("error retrieving NSX-T ALB Pools list: %s", err)
}

for _, albPool := range albPools {
toBeDeletedAlbPool := shouldDeleteEntity(alsoDelete, doNotDelete, albPool.NsxtAlbPool.Name, "vcd_nsxt_alb_pool", 5, verbose)

// --------------------------------------------------------------
// vcd_nsxt_alb_virtual_service
// --------------------------------------------------------------
albVirtualServices, err := govcdClient.GetAllAlbVirtualServices(edgeGateway.EdgeGateway.ID, nil)
if err != nil {
return fmt.Errorf("error retrieving NSX-T ALB Virtual Services list: %s", err)
}

for _, albVs := range albVirtualServices {
toBeDeleted := shouldDeleteEntity(alsoDelete, doNotDelete, albVs.NsxtAlbVirtualService.Name, "vcd_nsxt_alb_virtual_service", 6, verbose)
if toBeDeleted {
err = albVs.Delete()
if err != nil {
return fmt.Errorf("error deleting NSX-T ALB Virtual Service '%s': %s", albVs.NsxtAlbVirtualService.Name, err)
}
}
}

// vcd_nsxt_alb_pool deletion
if toBeDeletedAlbPool {
err = albPool.Delete()
if err != nil {
return fmt.Errorf("error deleting NSX-T ALB Pool '%s': %s", albPool.NsxtAlbPool.Name, err)
}
}
}

// vcd_nsxt_alb_edgegateway_service_engine_group deletion
if toBeDeletedAlbEdgeGatewayServiceEngineGroup {
err = albEdgeGatewayServiceEngineGroup.Delete()
if err != nil {
return fmt.Errorf("error deleting NSX-T ALB Edge Gateway Service Engine Group assignment '%s': %s", edgeServiceEngineGroupAssignmentName, err)
}
}
}

// vcd_nsxt_alb_settings
if toBeDisabledAlbSettings {
err = edgeGateway.DisableAlb()
if err != nil {
return fmt.Errorf("error disabling NSX-T ALB Edge Gateway settings: %s", err)
}
}
}
}

return nil
}

// shouldDeleteEntity checks whether a given entity is to be deleted, either by its name
// or by its inclusion in one of the entity lists
func shouldDeleteEntity(alsoDelete, doNotDelete entityList, name, entityType string, level int, verbose bool) bool {
Expand Down
24 changes: 20 additions & 4 deletions vcd/resource_vcd_nsxt_alb_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,17 @@ func resourceVcdAlbPool() *schema.Resource {
Default: 1,
},
"member": {
Type: schema.TypeSet,
Optional: true,
Elem: nsxtAlbPoolMember,
Description: "ALB Pool Members",
Type: schema.TypeSet,
Optional: true,
Elem: nsxtAlbPoolMember,
Description: "ALB Pool Members",
ConflictsWith: []string{"member_group_id"},
},
"member_group_id": {
Type: schema.TypeString,
Optional: true,
Description: "ID of Firewall Group to use for pool Membership (VCD 10.4.1+)",
lvirbalas marked this conversation as resolved.
Show resolved Hide resolved
ConflictsWith: []string{"member"},
},
"health_monitor": {
Type: schema.TypeSet,
Expand Down Expand Up @@ -399,6 +406,11 @@ func getNsxtAlbPoolType(d *schema.ResourceData) (*types.NsxtAlbPool, error) {
}
albPoolConfig.Members = poolMembers

// Member group
if memberGroupId := d.Get("member_group_id").(string); memberGroupId != "" {
albPoolConfig.MemberGroupRef = &types.OpenApiReference{ID: memberGroupId}
}

persistenceProfile, err := getNsxtAlbPoolPersistenceProfileType(d)
if err != nil {
return nil, fmt.Errorf("error defining persistence profile: %s", err)
Expand Down Expand Up @@ -436,6 +448,10 @@ func setNsxtAlbPoolData(d *schema.ResourceData, albPool *types.NsxtAlbPool) erro
return fmt.Errorf("error storing ALB Pool Members: %s", err)
}

if albPool.MemberGroupRef != nil {
dSet(d, "member_group_id", albPool.MemberGroupRef.ID)
}

err = setNsxtAlbPoolPersistenceProfileData(d, albPool.PersistenceProfile)
if err != nil {
return fmt.Errorf("error storing ALB Pool Persistence Profile: %s", err)
Expand Down
5 changes: 3 additions & 2 deletions vcd/resource_vcd_nsxt_alb_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func TestAccVcdNsxtAlbPool(t *testing.T) {

// String map to fill the template
var params = StringMap{
"TestName": t.Name(),
"PoolName": t.Name(),
"ControllerName": t.Name(),
"ControllerUrl": testConfig.Nsxt.NsxtAlbControllerUrl,
Expand Down Expand Up @@ -685,7 +686,7 @@ resource "vcd_nsxt_alb_controller" "first" {
}

resource "vcd_nsxt_alb_cloud" "first" {
name = "nsxt-cloud"
name = "{{.TestName}}-alb-cloud"
description = "first alb cloud"

controller_id = vcd_nsxt_alb_controller.first.id
Expand All @@ -694,7 +695,7 @@ resource "vcd_nsxt_alb_cloud" "first" {
}

resource "vcd_nsxt_alb_service_engine_group" "first" {
name = "first-se"
name = "{{.TestName}}-se-group"
alb_cloud_id = vcd_nsxt_alb_cloud.first.id
importable_service_engine_group_name = "Default-Group"
reservation_model = "{{.ReservationModel}}"
Expand Down
Loading