Skip to content

Commit a6af00e

Browse files
committed
Add support for project VPCs in network data source
Network datasource has a capability to find a network which belongs to NSX default project. But VPC subnets can be nested under different project, and as network names are not unique, it is required to use the project id as part of the network identification. Signed-off-by: Kobi Samoray <kobi.samoray@broadcom.com>
1 parent 5467cb6 commit a6af00e

File tree

5 files changed

+66
-6
lines changed

5 files changed

+66
-6
lines changed

docs/data-sources/network.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ The following arguments are supported:
6262
* `network_type`: This is required if you have multiple port groups with the same name. This will be one of `DistributedVirtualPortgroup` for distributed port groups, `Network` for standard (host-based) port groups, or `OpaqueNetwork` for networks managed externally, such as those managed by NSX.
6363
* `retry_timeout` - (Optional) The timeout duration in seconds for the data source to retry read operations.
6464
* `retry_interval` - (Optional) The interval in milliseconds to retry the read operation if `retry_timeout` is set. Default: 500.
65+
* `project_id` - (Optional) Select a project scope for retrieval of VPC subnets.
6566
* `vpc_id` - (Optional) Select a VPC scope for retrieval of VPC subnets.
6667
[docs-about-morefs]: /docs/providers/vsphere/index.html#use-of-managed-object-references-by-the-vsphere-provider
6768

vsphere/data_source_vsphere_network.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ func dataSourceVSphereNetwork() *schema.Resource {
4747
Description: "Id of the distributed virtual switch of which the port group is a part of",
4848
Optional: true,
4949
},
50+
"project_id": {
51+
Type: schema.TypeString,
52+
Description: "Id of the project object, which the VPC and network belongs to",
53+
Optional: true,
54+
},
5055
"vpc_id": {
5156
Type: schema.TypeString,
5257
Description: "Id of the VPC which the network belongs to",
@@ -89,6 +94,7 @@ func dataSourceVSphereNetworkRead(d *schema.ResourceData, meta interface{}) erro
8994
name := d.Get("name").(string)
9095
dvSwitchUUID := d.Get("distributed_virtual_switch_uuid").(string)
9196
vpcID := d.Get("vpc_id").(string)
97+
projectID := d.Get("project_id").(string)
9298
var dc *object.Datacenter
9399
if dcID, ok := d.GetOk("datacenter_id"); ok {
94100
var err error
@@ -128,7 +134,7 @@ func dataSourceVSphereNetworkRead(d *schema.ResourceData, meta interface{}) erro
128134
return net, waitForNetworkCompleted, nil
129135
} else if vpcID != "" {
130136
// Handle VPC network
131-
net, err = network.FromNameAndVPCId(client, name, dc, vpcID)
137+
net, err = network.FromNameAndVPCId(client, name, dc, projectID, vpcID)
132138
if err != nil {
133139
var notFoundError *network.NotFoundError
134140
if errors.As(err, &notFoundError) {

vsphere/data_source_vsphere_network_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,32 @@ func TestAccDataSourceVSphereNetwork_vpcNetwork(t *testing.T) {
184184
},
185185
})
186186
}
187+
188+
func testAccDataSourceVSphereNetworkConfigProjectVPCNetwork() string {
189+
return fmt.Sprintf(`
190+
%s
191+
`,
192+
testhelper.CombineConfigs(testhelper.ConfigDataRootDC1(), testhelper.ConfigDataProjectVPCNetwork(), testhelper.ConfigDataRootVMNet()),
193+
)
194+
}
195+
196+
func TestAccDataSourceVSphereNetwork_vpcNetworkAndProject(t *testing.T) {
197+
resource.Test(t, resource.TestCase{
198+
PreCheck: func() {
199+
RunSweepers()
200+
testAccPreCheck(t)
201+
if os.Getenv("TF_VAR_VSPHERE_PROJECT_VPC_SUBNET") == "" || os.Getenv("TF_VAR_VSPHERE_PROJECT_VPC_ID") == "" || os.Getenv("TF_VAR_VSPHERE_PROJECT_ID") == "" {
202+
t.Skipf("This test requires project and VPC settings, please set TF_VAR_VSPHERE_PROJECT_VPC_SUBNET, TF_VAR_VSPHERE_PROJECT_VPC_ID and TF_VAR_VSPHERE_PROJECT_ID environment variables")
203+
}
204+
},
205+
Providers: testAccProviders,
206+
Steps: []resource.TestStep{
207+
{
208+
Config: testAccDataSourceVSphereNetworkConfigProjectVPCNetwork(),
209+
Check: resource.ComposeTestCheckFunc(
210+
resource.TestCheckResourceAttr("data.vsphere_network.vmnet", "type", "Network"),
211+
),
212+
},
213+
},
214+
})
215+
}

vsphere/internal/helper/network/network_helper.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func FromNameAndDVSUuid(client *govmomi.Client, name string, dc *object.Datacent
109109
return nil, NotFoundError{Name: name}
110110
}
111111

112-
func FromNameAndVPCId(client *govmomi.Client, name string, dc *object.Datacenter, vpcID string) (object.NetworkReference, error) {
112+
func FromNameAndVPCId(client *govmomi.Client, name string, dc *object.Datacenter, projectID, vpcID string) (object.NetworkReference, error) {
113113
ctx := context.TODO()
114114
finder := find.NewFinder(client.Client, true)
115115

@@ -127,10 +127,23 @@ func FromNameAndVPCId(client *govmomi.Client, name string, dc *object.Datacenter
127127
for _, network := range networks {
128128
path := network.GetInventoryPath()
129129
pathSplit := strings.Split(path, "/")
130-
131-
vpcIndex := slices.Index(pathSplit, "Virtual Private Clouds")
132-
// Path format is /<datacenter>/network/Virtual Private Clouds/<VPC>/<subnet> ... And could contain folders as well
133-
if vpcIndex != -1 && len(pathSplit) > vpcIndex && pathSplit[vpcIndex+1] == vpcID {
130+
networkVPC := ""
131+
networkProject := ""
132+
if projectID == "" {
133+
vpcIndex := slices.Index(pathSplit, "Virtual Private Clouds")
134+
// Path format is /<datacenter>/network/Virtual Private Clouds/<VPC>/<subnet> ... And could contain folders as well
135+
if vpcIndex != -1 && len(pathSplit) > vpcIndex {
136+
networkVPC = pathSplit[vpcIndex+1]
137+
}
138+
} else {
139+
projectIndex := slices.Index(pathSplit, "NSX Managed Folders")
140+
// Path format is /<datacenter>/network/NSX Managed Folders/<project>/<VPC>/<subnet>
141+
if projectIndex != -1 && len(pathSplit) > projectIndex+1 {
142+
networkProject = pathSplit[projectIndex+1]
143+
networkVPC = pathSplit[projectIndex+2]
144+
}
145+
}
146+
if networkVPC != "" && networkVPC == vpcID && networkProject == projectID {
134147

135148
if network.Reference().Type == "DistributedVirtualPortgroup" {
136149
dvPortGroup := object.NewDistributedVirtualPortgroup(client.Client, network.Reference())

vsphere/internal/helper/testhelper/testing.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,17 @@ data "vsphere_network" "network1" {
207207
`, os.Getenv("TF_VAR_VSPHERE_VPC_SUBNET"), os.Getenv("TF_VAR_VSPHERE_VPC_ID"))
208208
}
209209

210+
func ConfigDataProjectVPCNetwork() string {
211+
return fmt.Sprintf(`
212+
data "vsphere_network" "network1" {
213+
name = "%s"
214+
project_id = "%s"
215+
vpc_id = "%s"
216+
datacenter_id = data.vsphere_datacenter.rootdc1.id
217+
}
218+
`, os.Getenv("TF_VAR_VSPHERE_PROJECT_VPC_SUBNET"), os.Getenv("TF_VAR_VSPHERE_PROJECT_ID"), os.Getenv("TF_VAR_VSPHERE_PROJECT_VPC_ID"))
219+
}
220+
210221
func ConfigDataRootVMNet() string {
211222
return `
212223
data "vsphere_network" "vmnet" {

0 commit comments

Comments
 (0)