Skip to content

Commit

Permalink
Add VPC data source
Browse files Browse the repository at this point in the history
Signed-off-by: Kobi Samoray <kobi.samoray@broadcom.com>
  • Loading branch information
ksamoray committed May 13, 2024
1 parent a8cdeae commit 9cb2338
Show file tree
Hide file tree
Showing 6 changed files with 304 additions and 25 deletions.
12 changes: 6 additions & 6 deletions nsxt/data_source_nsxt_policy_ip_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func testAccDataSourceNsxtPolicyIPBlockBasic(t *testing.T, withContext bool, pre
Steps: []resource.TestStep{
{
PreConfig: func() {
if err := testAccDataSourceNsxtPolicyIPBlockCreate(name); err != nil {
if err := testAccDataSourceNsxtPolicyIPBlockCreate(name, newUUID(), "4001::/64", false); err != nil {
t.Error(err)
}
},
Expand All @@ -57,7 +57,7 @@ func testAccDataSourceNsxtPolicyIPBlockBasic(t *testing.T, withContext bool, pre
})
}

func testAccDataSourceNsxtPolicyIPBlockCreate(name string) error {
func testAccDataSourceNsxtPolicyIPBlockCreate(name, id, cidr string, isPrivate bool) error {
connector, err := testAccGetPolicyConnector()
if err != nil {
return fmt.Errorf("Error during test client initialization: %v", err)
Expand All @@ -66,15 +66,15 @@ func testAccDataSourceNsxtPolicyIPBlockCreate(name string) error {

displayName := name
description := name
cidr := "4001::/64"
obj := model.IpAddressBlock{
Description: &description,
DisplayName: &displayName,
Cidr: &cidr,
}

// Generate a random ID for the resource
id := newUUID()
if isPrivate {
visibility := model.IpAddressBlock_VISIBILITY_PRIVATE
obj.Visibility = &visibility
}

err = client.Patch(id, obj)
if err != nil {
Expand Down
41 changes: 22 additions & 19 deletions nsxt/data_source_nsxt_policy_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,7 @@ func dataSourceNsxtPolicyProject() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"site_info": {
Type: schema.TypeList,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"edge_cluster_paths": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
},
"site_path": {
Type: schema.TypeString,
Optional: true,
},
},
},
Optional: true,
},
"site_info": getSiteInfoSchema(),
"tier0_gateway_paths": {
Type: schema.TypeList,
Elem: &schema.Schema{
Expand All @@ -57,6 +39,27 @@ func dataSourceNsxtPolicyProject() *schema.Resource {
}
}

func getSiteInfoSchema() *schema.Schema {
return &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"edge_cluster_paths": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
},
"site_path": {
Type: schema.TypeString,
Optional: true,
},
},
},
Optional: true,
}
}
func dataSourceNsxtPolicyProjectRead(d *schema.ResourceData, m interface{}) error {
connector := getPolicyConnector(m)
client := infra.NewProjectsClient(connector)
Expand Down
102 changes: 102 additions & 0 deletions nsxt/data_source_nsxt_policy_vpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* Copyright © 2024 Broadcom, Inc. All Rights Reserved.
SPDX-License-Identifier: MPL-2.0 */

package nsxt

import (
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/orgs/projects"
)

func dataSourceNsxtPolicyVPC() *schema.Resource {
return &schema.Resource{
Read: dataSourceNsxtPolicyVPCRead,
Schema: map[string]*schema.Schema{
"id": getDataSourceIDSchema(),
"display_name": getDataSourceDisplayNameSchema(),
"description": getDataSourceDescriptionSchema(),
"path": getPathSchema(),
"context": getContextSchema(),
"site_info": getSiteInfoSchema(),
"default_gateway_path": getPathSchema(),
"short_id": {
Type: schema.TypeString,
Optional: true,
},
},
}
}

func dataSourceNsxtPolicyVPCRead(d *schema.ResourceData, m interface{}) error {
connector := getPolicyConnector(m)
client := projects.NewVpcsClient(connector)

objID := d.Get("id").(string)
objName := d.Get("display_name").(string)
ctx := getSessionContext(d, m)

var obj model.Vpc

if objID != "" {
// Get by id
objGet, err := client.Get(defaultOrgID, ctx.ProjectID, objID)
if err != nil {
return handleDataSourceReadError(d, "VPC", objID, err)
}
obj = objGet
} else if objName == "" {
return fmt.Errorf("error obtaining VPC ID or name during read")
} else {
// Get by full name/prefix
objList, err := client.List(defaultOrgID, ctx.ProjectID, nil, nil, nil, nil, nil, nil)
if err != nil {
return handleListError("VPC", err)
}
// go over the list to find the correct one (prefer a perfect match. If not - prefix match)
var perfectMatch []model.Vpc
var prefixMatch []model.Vpc
for _, objInList := range objList.Results {
if strings.HasPrefix(*objInList.DisplayName, objName) {
prefixMatch = append(prefixMatch, objInList)
}
if *objInList.DisplayName == objName {
perfectMatch = append(perfectMatch, objInList)
}
}
if len(perfectMatch) > 0 {
if len(perfectMatch) > 1 {
return fmt.Errorf("found multiple VPCs with name '%s'", objName)
}
obj = perfectMatch[0]
} else if len(prefixMatch) > 0 {
if len(prefixMatch) > 1 {
return fmt.Errorf("found multiple VPCs with name starting with '%s'", objName)
}
obj = prefixMatch[0]
} else {
return fmt.Errorf("VPC with name '%s' was not found", objName)
}
}

d.SetId(*obj.Id)
d.Set("display_name", obj.DisplayName)
d.Set("description", obj.Description)
d.Set("path", obj.Path)
d.Set("default_gateway_path", obj.DefaultGatewayPath)
d.Set("short_id", obj.ShortId)

var siteInfosList []map[string]interface{}
for _, item := range obj.SiteInfos {
data := make(map[string]interface{})
data["edge_cluster_paths"] = item.EdgeClusterPaths
data["site_path"] = item.SitePath
siteInfosList = append(siteInfosList, data)
}
d.Set("site_info", siteInfosList)

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

package nsxt

import (
"fmt"
"os"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/orgs/projects"
)

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

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccOnlyMultitenancy(t)
testAccPreCheck(t)
testAccNSXVersion(t, "4.1.2")
},
Providers: testAccProviders,
CheckDestroy: func(state *terraform.State) error {
return testAccDataSourceNsxtPolicyVPCDeleteByName(name)
},
Steps: []resource.TestStep{
{
PreConfig: func() {
if err := testAccDataSourceNsxtPolicyVPCCreate(name); err != nil {
t.Error(err)
}
},
Config: testAccNsxtPolicyVPCReadTemplate(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(testResourceName, "display_name", name),
resource.TestCheckResourceAttr(testResourceName, "description", name),
resource.TestCheckResourceAttrSet(testResourceName, "path"),
//resource.TestCheckResourceAttrSet(testResourceName, "default_gateway_path"),
resource.TestCheckResourceAttrSet(testResourceName, "short_id"),
),
},
},
})
}

func testAccDataSourceNsxtPolicyVPCCreate(name string) error {

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

ipBlockID := newUUID()
err = testAccDataSourceNsxtPolicyIPBlockCreate(name, ipBlockID, "192.168.240.0/24", true)
if err != nil {
return err
}

client := projects.NewVpcsClient(connector)
projID := os.Getenv("NSXT_PROJECT_ID")

displayName := name
description := name
addrType := model.Vpc_IP_ADDRESS_TYPE_IPV4
enableDhcp := false
disableGateway := true
obj := model.Vpc{
Description: &description,
DisplayName: &displayName,
IpAddressType: &addrType,
DhcpConfig: &model.DhcpConfig{EnableDhcp: &enableDhcp},
ServiceGateway: &model.ServiceGateway{Disable: &disableGateway},
PrivateIpv4Blocks: []string{fmt.Sprintf("/orgs/default/projects/%s/infra/ip-blocks/%s", projID, ipBlockID)},
}

// Generate a random ID for the resource
id := newUUID()

err = client.Patch(defaultOrgID, projID, id, obj)
if err != nil {
return handleCreateError("VPC", id, err)
}
return nil
}

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

client := projects.NewVpcsClient(connector)
projID := os.Getenv("NSXT_PROJECT_ID")

// Find the object by name
objList, err := client.List(defaultOrgID, projID, nil, nil, nil, nil, nil, nil)
if err != nil {
return handleListError("VPC", err)
}
for _, objInList := range objList.Results {
if *objInList.DisplayName == name {
err := client.Delete(defaultOrgID, projID, *objInList.Id)
if err != nil {
return handleDeleteError("VPC", *objInList.Id, err)
}
return testAccDataSourceNsxtPolicyIPBlockDeleteByName(name)
}
}
return fmt.Errorf("error while deleting VPC '%s': resource not found", name)
}

func testAccNsxtPolicyVPCReadTemplate(name string) string {
context := testAccNsxtPolicyMultitenancyContext()
return fmt.Sprintf(`
data "nsxt_policy_ip_block" "test" {
%s
display_name = "%s"
}
data "nsxt_policy_vpc" "test" {
%s
display_name = "%s"
}`, context, name, context, name)
}
1 change: 1 addition & 0 deletions nsxt/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ func Provider() *schema.Provider {
"nsxt_policy_distributed_flood_protection_profile": dataSourceNsxtPolicyDistributedFloodProtectionProfile(),
"nsxt_policy_gateway_flood_protection_profile": dataSourceNsxtPolicyGatewayFloodProtectionProfile(),
"nsxt_manager_info": dataSourceNsxtManagerInfo(),
"nsxt_policy_vpc": dataSourceNsxtPolicyVPC(),
},

ResourcesMap: map[string]*schema.Resource{
Expand Down
45 changes: 45 additions & 0 deletions website/docs/d/policy_vpc.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
subcategory: "Multitenancy"
layout: "nsxt"
page_title: "NSXT: policy_vpc"
description: Policy VPC data source.
---

# nsxt_policy_vpc

This data source provides information about policy VPC configured on NSX.
This data source is applicable to NSX Policy Manager.

## Example Usage

```hcl
data "nsxt_policy_project" "demoproj" {
display_name = "demoproj"
}
data "nsxt_policy_vpc" "test" {
context {
project_id = data.nsxt_policy_project.demoproj.id
}
display_name = "vpc1"
}
```

## Argument Reference

* `id` - (Optional) The ID of VPC to retrieve. If ID is specified, no additional argument should be configured.
* `display_name` - (Optional) The Display Name prefix of the VPC to retrieve.
* `context` - (Optional) The context which the object belongs to
* `project_id` - (Required) The ID of the project which the object belongs to

## Attributes Reference

In addition to arguments listed above, the following attributes are exported:

* `description` - The description of the resource.
* `path` - The NSX path of the policy resource.
* `short_id` - Defaults to id if id is less than equal to 8 characters or defaults to random generated id if not set.
* `site_info` - Information related to sites applicable for given Project.
* `edge_cluster_paths` - The edge cluster on which the networking elements for the Org will be created.
* `site_path` - This represents the path of the site which is managed by Global Manager. For the local manager, if set, this needs to point to 'default'.
* `default_gateway_path` - The tier 0 has to be pre-created before Project is created.

0 comments on commit 9cb2338

Please sign in to comment.