Skip to content

Commit

Permalink
Merge pull request #572 from vmware/bgp-lm
Browse files Browse the repository at this point in the history
Support bgp config resource for Local Manager
  • Loading branch information
annakhm authored Feb 9, 2021
2 parents 99f78ed + e84a55d commit 81d41e8
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 106 deletions.
16 changes: 16 additions & 0 deletions nsxt/gateway_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,3 +554,19 @@ func parseGatewayInterfacePolicyPath(path string) (bool, string, string, string)

return isT0, gwID, localeServiceID, interfaceID
}

func getComputedLocaleServiceIDSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeString,
Description: "NSX ID of associated Gateway Locale Service",
Computed: true,
}
}

func getComputedGatewayIDSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeString,
Description: "NSX ID of associated Tier0 Gateway",
Computed: true,
}
}
17 changes: 0 additions & 17 deletions nsxt/policy_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/vmware/vsphere-automation-sdk-go/runtime/bindings"
"github.com/vmware/vsphere-automation-sdk-go/runtime/protocol/client"
gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/realized_state"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)
Expand Down Expand Up @@ -110,22 +109,6 @@ func setPolicyTagsInSchema(d *schema.ResourceData, tags []model.Tag) {
setCustomizedPolicyTagsInSchema(d, tags, "tag")
}

func getPolicyGlobalManagerTagsFromSchema(d *schema.ResourceData) []gm_model.Tag {
tags := d.Get("tag").(*schema.Set).List()
var tagList []gm_model.Tag
for _, tag := range tags {
data := tag.(map[string]interface{})
tagScope := data["scope"].(string)
tagTag := data["tag"].(string)
elem := gm_model.Tag{
Scope: &tagScope,
Tag: &tagTag}

tagList = append(tagList, elem)
}
return tagList
}

func getPathListFromMap(data map[string]interface{}, attrName string) []string {
pathList := interface2StringList(data[attrName].(*schema.Set).List())
if len(pathList) == 0 {
Expand Down
137 changes: 85 additions & 52 deletions nsxt/resource_nsxt_policy_bgp_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
gm_locale_services "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/global_infra/tier_0s/locale_services"
gm_model "github.com/vmware/vsphere-automation-sdk-go/services/nsxt-gm/model"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/infra/tier_0s/locale_services"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
)

// Note: this resource is supported for global manager only
// TODO: consider supporting it for local manager and deprecating bgp config on T0 gateway
func resourceNsxtPolicyBgpConfig() *schema.Resource {
bgpSchema := getPolicyBGPConfigSchema()
bgpSchema["gateway_path"] = getPolicyPathSchema(true, true, "Gateway for this BGP config")
bgpSchema["site_path"] = getPolicyPathSchema(true, true, "Site Path for this BGP config")
bgpSchema["site_path"] = getPolicyPathSchema(false, true, "Site Path for this BGP config")
bgpSchema["gateway_id"] = getComputedGatewayIDSchema()
bgpSchema["locale_service_id"] = getComputedLocaleServiceIDSchema()

return &schema.Resource{
Create: resourceNsxtPolicyBgpConfigCreate,
Expand All @@ -30,32 +31,35 @@ func resourceNsxtPolicyBgpConfig() *schema.Resource {
}

func resourceNsxtPolicyBgpConfigRead(d *schema.ResourceData, m interface{}) error {
if !isPolicyGlobalManager(m) {
return globalManagerOnlyError()
}
connector := getPolicyConnector(m)

gwPath := d.Get("gateway_path").(string)
gwID := getPolicyIDFromPath(gwPath)
sitePath := d.Get("site_path").(string)
if !isPolicyGlobalManager(m) {
return fmt.Errorf("This resource is not supported for local manager")
}

serviceID, err := findTier0LocaleServiceForSite(connector, gwID, sitePath)
if err != nil {
return err
}
client := gm_locale_services.NewDefaultBgpClient(connector)
gmObj, err := client.Get(gwID, serviceID)
if err != nil {
return handleReadError(d, "BGP Config", serviceID, err)
}
lmObj, convErr := convertModelBindingType(gmObj, gm_model.BgpRoutingConfigBindingType(), model.BgpRoutingConfigBindingType())
if convErr != nil {
return convErr
isT0, gwID := parseGatewayPolicyPath(gwPath)
if !isT0 {
return fmt.Errorf("Tier0 Gateway path expected, got %s", gwPath)
}
serviceID := d.Get("locale_service_id").(string)
var lmRoutingConfig model.BgpRoutingConfig
if isPolicyGlobalManager(m) {

client := gm_locale_services.NewDefaultBgpClient(connector)
gmObj, err := client.Get(gwID, serviceID)
if err != nil {
return handleReadError(d, "BGP Config", serviceID, err)
}
lmObj, convErr := convertModelBindingType(gmObj, gm_model.BgpRoutingConfigBindingType(), model.BgpRoutingConfigBindingType())
if convErr != nil {
return convErr
}
lmRoutingConfig = lmObj.(model.BgpRoutingConfig)
} else {
var err error
client := locale_services.NewDefaultBgpClient(connector)
lmRoutingConfig, err = client.Get(gwID, serviceID)
if err != nil {
return handleReadError(d, "BGP Config", serviceID, err)
}
}
lmRoutingConfig := lmObj.(model.BgpRoutingConfig)

data := initPolicyTier0BGPConfigMap(&lmRoutingConfig)

Expand All @@ -66,7 +70,7 @@ func resourceNsxtPolicyBgpConfigRead(d *schema.ResourceData, m interface{}) erro
return nil
}

func resourceNsxtPolicyBgpConfigToStruct(d *schema.ResourceData) (*gm_model.BgpRoutingConfig, error) {
func resourceNsxtPolicyBgpConfigToStruct(d *schema.ResourceData) (*model.BgpRoutingConfig, error) {
ecmp := d.Get("ecmp").(bool)
enabled := d.Get("enabled").(bool)
interSrIbgp := d.Get("inter_sr_ibgp").(bool)
Expand All @@ -75,16 +79,16 @@ func resourceNsxtPolicyBgpConfigToStruct(d *schema.ResourceData) (*gm_model.BgpR
restartMode := d.Get("graceful_restart_mode").(string)
restartTimer := int64(d.Get("graceful_restart_timer").(int))
staleTimer := int64(d.Get("graceful_restart_stale_route_timer").(int))
tags := getPolicyGlobalManagerTagsFromSchema(d)
tags := getPolicyTagsFromSchema(d)

var aggregationStructs []gm_model.RouteAggregationEntry
var aggregationStructs []model.RouteAggregationEntry
routeAggregations := d.Get("route_aggregation").([]interface{})
if len(routeAggregations) > 0 {
for _, agg := range routeAggregations {
data := agg.(map[string]interface{})
prefix := data["prefix"].(string)
summary := data["summary_only"].(bool)
elem := gm_model.RouteAggregationEntry{
elem := model.RouteAggregationEntry{
Prefix: &prefix,
SummaryOnly: &summary,
}
Expand All @@ -93,17 +97,17 @@ func resourceNsxtPolicyBgpConfigToStruct(d *schema.ResourceData) (*gm_model.BgpR
}
}

restartTimerStruct := gm_model.BgpGracefulRestartTimer{
restartTimerStruct := model.BgpGracefulRestartTimer{
RestartTimer: &restartTimer,
StaleRouteTimer: &staleTimer,
}

restartConfigStruct := gm_model.BgpGracefulRestartConfig{
restartConfigStruct := model.BgpGracefulRestartConfig{
Mode: &restartMode,
Timer: &restartTimerStruct,
}

routeStruct := gm_model.BgpRoutingConfig{
routeStruct := model.BgpRoutingConfig{
Ecmp: &ecmp,
Enabled: &enabled,
RouteAggregations: aggregationStructs,
Expand All @@ -118,58 +122,87 @@ func resourceNsxtPolicyBgpConfigToStruct(d *schema.ResourceData) (*gm_model.BgpR
}

func resourceNsxtPolicyBgpConfigCreate(d *schema.ResourceData, m interface{}) error {
if !isPolicyGlobalManager(m) {
return globalManagerOnlyError()
}
// This is not a create operation on NSX, since BGP config us auto created
connector := getPolicyConnector(m)

gwPath := d.Get("gateway_path").(string)
gwID := getPolicyIDFromPath(gwPath)
isT0, gwID := parseGatewayPolicyPath(gwPath)
if !isT0 {
return fmt.Errorf("Tier0 Gateway path expected, got %s", gwPath)
}
sitePath := d.Get("site_path").(string)

obj, err := resourceNsxtPolicyBgpConfigToStruct(d)
if err != nil {
return handleCreateError("BgpRoutingConfig", gwID, err)
}

serviceID, err := findTier0LocaleServiceForSite(connector, gwID, sitePath)
if err != nil {
return handleCreateError("BgpRoutingConfig", gwID, err)
}
var localeServiceID string
if isPolicyGlobalManager(m) {
serviceID, err1 := findTier0LocaleServiceForSite(connector, gwID, sitePath)
if err1 != nil {
return handleCreateError("BgpRoutingConfig", gwID, err1)
}

client := gm_locale_services.NewDefaultBgpClient(connector)
err = client.Patch(gwID, serviceID, *obj, nil)
localeServiceID = serviceID

gmObj, convErr := convertModelBindingType(obj, model.BgpRoutingConfigBindingType(), gm_model.BgpRoutingConfigBindingType())
if convErr != nil {
return convErr
}
gmRoutingConfig := gmObj.(gm_model.BgpRoutingConfig)

client := gm_locale_services.NewDefaultBgpClient(connector)
err = client.Patch(gwID, serviceID, gmRoutingConfig, nil)
} else {
localeService, err1 := getPolicyTier0GatewayLocaleServiceWithEdgeCluster(gwID, connector)
if err1 != nil {
return fmt.Errorf("Tier0 Gateway path with configured edge cluster expected, got %s", gwPath)
}
localeServiceID = *localeService.Id

client := locale_services.NewDefaultBgpClient(connector)
err = client.Patch(gwID, localeServiceID, *obj, nil)
}
if err != nil {
return handleCreateError("BgpRoutingConfig", gwID, err)
}

d.SetId(newUUID())
d.Set("gateway_id", gwID)
d.Set("locale_service_id", localeServiceID)

return resourceNsxtPolicyBgpConfigRead(d, m)
}

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

gwPath := d.Get("gateway_path").(string)
gwID := getPolicyIDFromPath(gwPath)
sitePath := d.Get("site_path").(string)
revision := int64(d.Get("revision").(int))
gwPath := d.Get("gateway_path").(string)
_, gwID := parseGatewayPolicyPath(gwPath)
serviceID := d.Get("locale_service_id").(string)

obj, err := resourceNsxtPolicyBgpConfigToStruct(d)
if err != nil {
return handleUpdateError("BgpRoutingConfig", gwID, err)
}

serviceID, err := findTier0LocaleServiceForSite(connector, gwID, sitePath)
if err != nil {
return handleUpdateError("BgpRoutingConfig", gwID, err)
}

obj.Revision = &revision
if isPolicyGlobalManager(m) {
gmObj, convErr := convertModelBindingType(obj, model.BgpRoutingConfigBindingType(), gm_model.BgpRoutingConfigBindingType())
if convErr != nil {
return convErr
}
gmRoutingConfig := gmObj.(gm_model.BgpRoutingConfig)

client := gm_locale_services.NewDefaultBgpClient(connector)
_, err = client.Update(gwID, serviceID, gmRoutingConfig, nil)
} else {
client := locale_services.NewDefaultBgpClient(connector)
_, err = client.Update(gwID, serviceID, *obj, nil)
}

client := gm_locale_services.NewDefaultBgpClient(connector)
_, err = client.Update(gwID, serviceID, *obj, nil)
if err != nil {
return handleUpdateError("BgpRoutingConfig", gwID, err)
}
Expand Down
44 changes: 18 additions & 26 deletions nsxt/resource_nsxt_policy_bgp_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func TestAccResourceNsxtPolicyBgpConfig_basic(t *testing.T) {
testResourceName := "nsxt_policy_bgp_config.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccOnlyGlobalManager(t); testAccPreCheck(t) },
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Expand Down Expand Up @@ -85,7 +85,7 @@ func TestAccResourceNsxtPolicyBgpConfig_minimalistic(t *testing.T) {
testResourceName := "nsxt_policy_bgp_config.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccOnlyGlobalManager(t); testAccPreCheck(t) },
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Expand All @@ -107,15 +107,11 @@ func testAccNsxtPolicyBgpConfigTemplate(createFlow bool) string {
} else {
attrMap = accTestPolicyBgpConfigUpdateAttributes
}
return testAccNsxtPolicyGMGatewayDeps() + fmt.Sprintf(`
resource "nsxt_policy_tier0_gateway" "test" {
display_name = "terraform-bgp-test"
locale_service {
edge_cluster_path = data.nsxt_policy_edge_cluster.ec_site1.path
}
}
extraConfig := ""
if testAccIsGlobalManager() {
extraConfig = `site_path = data.nsxt_policy_site.test.path`
}
return testAccNsxtPolicyEdgeClusterReadTemplate(getEdgeClusterName()) + testAccNsxtPolicyTier0WithEdgeClusterTemplate("test", false) + fmt.Sprintf(`
resource "nsxt_policy_bgp_config" "test" {
enabled = %s
inter_sr_ibgp = %s
Expand All @@ -132,7 +128,7 @@ resource "nsxt_policy_bgp_config" "test" {
graceful_restart_stale_route_timer = %s
gateway_path = nsxt_policy_tier0_gateway.test.path
site_path = data.nsxt_policy_site.site1.path
%s
tag {
scope = "scope1"
tag = "tag1"
Expand All @@ -142,28 +138,24 @@ resource "nsxt_policy_bgp_config" "test" {
data "nsxt_policy_realization_info" "bgp_realization_info" {
path = nsxt_policy_bgp_config.test.path
site_path = data.nsxt_policy_site.site1.path
}`, attrMap["enabled"], attrMap["inter_sr_ibgp"], attrMap["local_as_num"], attrMap["multipath_relax"], attrMap["prefix"], attrMap["summary_only"], attrMap["graceful_restart_mode"], attrMap["graceful_restart_timer"], attrMap["graceful_restart_stale_route_timer"])
%s
}`, attrMap["enabled"], attrMap["inter_sr_ibgp"], attrMap["local_as_num"], attrMap["multipath_relax"], attrMap["prefix"], attrMap["summary_only"], attrMap["graceful_restart_mode"], attrMap["graceful_restart_timer"], attrMap["graceful_restart_stale_route_timer"], extraConfig, extraConfig)
}

func testAccNsxtPolicyBgpConfigMinimalistic() string {
return testAccNsxtPolicyGMGatewayDeps() + `
resource "nsxt_policy_tier0_gateway" "test" {
display_name = "terraform-bgp-test"
locale_service {
edge_cluster_path = data.nsxt_policy_edge_cluster.ec_site1.path
}
}
extraConfig := ""
if testAccIsGlobalManager() {
extraConfig = `site_path = data.nsxt_policy_site.test.path`
}
return testAccNsxtPolicyEdgeClusterReadTemplate(getEdgeClusterName()) + testAccNsxtPolicyTier0WithEdgeClusterTemplate("test", false) + fmt.Sprintf(`
resource "nsxt_policy_bgp_config" "test" {
gateway_path = nsxt_policy_tier0_gateway.test.path
site_path = data.nsxt_policy_site.site1.path
%s
local_as_num = 65001
}
data "nsxt_policy_realization_info" "realization_info" {
path = nsxt_policy_bgp_config.test.path
site_path = data.nsxt_policy_site.site1.path
}`
%s
}`, extraConfig, extraConfig)
}
11 changes: 2 additions & 9 deletions nsxt/resource_nsxt_policy_ospf_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,8 @@ func getPolicyOspfConfigSchema() map[string]*schema.Schema {
},
},
},
"locale_service_id": {
Type: schema.TypeString,
Description: "Id of associated Gateway Locale Service on NSX",
Computed: true,
},
"gateway_id": {
Type: schema.TypeString, Description: "Id of associated Tier0 Gateway on NSX",
Computed: true,
},
"locale_service_id": getComputedLocaleServiceIDSchema(),
"gateway_id": getComputedGatewayIDSchema(),
}
}

Expand Down
Loading

0 comments on commit 81d41e8

Please sign in to comment.