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

Add DHCP binding support for NSX-T Org Networks (vcd_nsxt_network_dhcp_binding) #1039

Merged
merged 11 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changes/v3.9.0/1039-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* **New Resource:** `vcd_nsxt_network_dhcp_binding` to manage NSX-T DHCP Bindings [GH-1039]
* **New Data Source:** `vcd_nsxt_network_dhcp_binding` to read NSX-T DHCP Bindings [GH-1039]
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1
github.com/kr/pretty v0.2.1
github.com/vmware/go-vcloud-director/v2 v2.20.0-alpha.11
github.com/vmware/go-vcloud-director/v2 v2.20.0-alpha.12
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,8 @@ 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.11 h1:0TNeCF30HtOodx3pQKR9PHSKHDBEYqQ8zMsVhxsa7pM=
github.com/vmware/go-vcloud-director/v2 v2.20.0-alpha.11/go.mod h1:QPxGFgrUcSyzy9IlpwDE4UNT3tsOy2047tJOPEJ4nlw=
github.com/vmware/go-vcloud-director/v2 v2.20.0-alpha.12 h1:Wz0AGbLTVCMAeoFFWXXQxk/gvV3l2vk6CKPbL0kOMK8=
github.com/vmware/go-vcloud-director/v2 v2.20.0-alpha.12/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
10 changes: 10 additions & 0 deletions vcd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,16 @@ func (cli *VCDClient) unLockParentEdgeGtw(d *schema.ResourceData) {
vcdMutexKV.kvUnlock(edgeGtwIdValue)
}

func (cli *VCDClient) lockParentOrgNetwork(d *schema.ResourceData) {
orgNetworkId := d.Get("org_network_id").(string)
vcdMutexKV.kvLock(orgNetworkId)
}

func (cli *VCDClient) unLockParentOrgNetwork(d *schema.ResourceData) {
orgNetworkId := d.Get("org_network_id").(string)
vcdMutexKV.kvUnlock(orgNetworkId)
}

func (cli *VCDClient) getOrgName(d *schema.ResourceData) string {
orgName := d.Get("org").(string)
if orgName == "" {
Expand Down
7 changes: 7 additions & 0 deletions vcd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,13 @@ func importStateIdOrgNsxtVdcGroupObject(vdcGroupName, objectName string) resourc
}
}

// importCustomObject accepts a path and joins it using ImportSeparator
func importCustomObject(path []string) resource.ImportStateIdFunc {
return func(*terraform.State) (string, error) {
return strings.Join(path, ImportSeparator), nil
}
}

// importStateIdNsxtManagerObject can be used by all entities that depend on NSX-T manager name + objectName
func importStateIdNsxtManagerObject(objectName string) resource.ImportStateIdFunc {
return func(*terraform.State) (string, error) {
Expand Down
139 changes: 139 additions & 0 deletions vcd/datasource_vcd_nsxt_network_dhcp_binding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package vcd

import (
"context"

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

func datasourceVcdNsxtDhcpBinding() *schema.Resource {
return &schema.Resource{
ReadContext: datasourceVcdNsxtDhcpBindingRead,

Schema: map[string]*schema.Schema{
"org": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
adambarreiro marked this conversation as resolved.
Show resolved Hide resolved
Description: "The name of organization to use, optional if defined at provider " +
"level. Useful when connected as sysadmin working across different organizations",
},
"org_network_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
adambarreiro marked this conversation as resolved.
Show resolved Hide resolved
Description: "Parent Org VDC network ID",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of DHCP binding",
},
"ip_address": {
Type: schema.TypeString,
Computed: true,
Description: "IP address of the DHCP binding",
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
Description: "MAC address of the DHCP binding",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of DHCP binding",
},
"binding_type": {
Type: schema.TypeString,
Computed: true,
Description: "Binding type 'IPV4' or 'IPV6'",
},
"dns_servers": {
Type: schema.TypeList,
Computed: true,
Description: "DNS server IPs",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"lease_time": {
Type: schema.TypeInt,
Computed: true,
Description: "Lease time in seconds",
},
"dhcp_v4_config": {
Type: schema.TypeList,
Computed: true,
Description: "IPv4 specific DHCP Binding configuration",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"gateway_ip_address": {
Computed: true,
Type: schema.TypeString,
Description: "Gateway IP address to be used by the DHCP client",
},
"hostname": {
Computed: true,
Type: schema.TypeString,
Description: "Hostname to be used by the DHCP client",
},
},
},
},
"dhcp_v6_config": {
Type: schema.TypeList,
Computed: true,
Description: "IPv6 specific DHCP Binding configuration",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"sntp_servers": {
Computed: true,
Type: schema.TypeSet,
Description: "List of SNTP servers to be used by the DHCP client",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"dns_servers": {
Computed: true,
Type: schema.TypeSet,
Description: "List of DNS servers to be used by the DHCP client",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
},
}
}

func datasourceVcdNsxtDhcpBindingRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
vcdClient := meta.(*VCDClient)
org, err := vcdClient.GetOrgFromResource(d)
if err != nil {
return diag.Errorf("[NSX-T DHCP binding DS read] error retrieving Org: %s", err)
}

orgNetworkId := d.Get("org_network_id").(string)
orgVdcNet, err := org.GetOpenApiOrgVdcNetworkById(orgNetworkId)
if err != nil {
return diag.Errorf("[NSX-T DHCP binding DS read] error retrieving Org VDC network with ID '%s': %s", orgNetworkId, err)
}

dhcpBindingName := d.Get("name").(string)
dhcpBinding, err := orgVdcNet.GetOpenApiOrgVdcNetworkDhcpBindingByName(dhcpBindingName)
if err != nil {
return diag.Errorf("[NSX-T DHCP binding DS read] error retrieving DHCP binding with Name '%s' for Org VDC network with ID '%s': %s",
dhcpBindingName, orgNetworkId, err)
}
d.SetId(dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding.ID)

if err := setOpenApiOrgVdcNetworkDhcpBindingData(d, dhcpBinding.OpenApiOrgVdcNetworkDhcpBinding); err != nil {
return diag.Errorf("[NSX-T DHCP binding DS read] error setting DHCP binding data: %s", err)
}
return nil
}
2 changes: 2 additions & 0 deletions vcd/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ var globalDataSourceMap = map[string]*schema.Resource{
"vcd_rde_interface": datasourceVcdRdeInterface(), // 3.9
"vcd_rde_type": datasourceVcdRdeType(), // 3.9
"vcd_rde": datasourceVcdRde(), // 3.9
"vcd_nsxt_network_dhcp_binding": datasourceVcdNsxtDhcpBinding(), // 3.9
}

var globalResourceMap = map[string]*schema.Resource{
Expand Down Expand Up @@ -199,6 +200,7 @@ var globalResourceMap = map[string]*schema.Resource{
"vcd_rde_interface": resourceVcdRdeInterface(), // 3.9
"vcd_rde_type": resourceVcdRdeType(), // 3.9
"vcd_rde": resourceVcdRde(), // 3.9
"vcd_nsxt_network_dhcp_binding": resourceVcdNsxtDhcpBinding(), // 3.9
}

// Provider returns a terraform.ResourceProvider.
Expand Down
14 changes: 7 additions & 7 deletions vcd/resource_vcd_nsxt_network_dhcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,11 @@ func resourceVcdOpenApiDhcpCreate(ctx context.Context, d *schema.ResourceData, m
return diag.Errorf("[NSX-T DHCP pool set] error setting DHCP pool for Org VDC network ID '%s': %s",
orgNetworkId, err)
}
// ID is in fact Org VDC network ID because DHCP pools do not have their own ID, only Org Network ID in API path
// ID is in fact Org VDC network ID because DHCP pools do not have their own IDs, only Org
// Network ID in API path.
// Note. Do not change this ID to something else, because it is convenient to use it for
// implicit dependency management in vcd_nsxt_network_dhcp_binding resource (because DHCP
// bindings require DHCP to be enabled)
d.SetId(orgNetworkId)

return resourceVcdOpenApiDhcpRead(ctx, d, meta)
Expand Down Expand Up @@ -220,7 +224,7 @@ func resourceVcdOpenApiDhcpImport(_ context.Context, d *schema.ResourceData, met
}

if !vdcOrVdcGroup.IsNsxt() {
return nil, fmt.Errorf("[NSX-T DHCP pool import] DHCP configuration is only supported for Routed NSX-T networks: %s", err)
return nil, fmt.Errorf("[NSX-T DHCP pool import] DHCP configuration is only supported for NSX-T networks: %s", err)
}

dSet(d, "org", orgName)
Expand Down Expand Up @@ -259,11 +263,7 @@ func getOpenAPIOrgVdcNetworkDhcpType(d *schema.ResourceData) *types.OpenApiOrgVd

dnsServers, ok := d.GetOk("dns_servers")
if ok {
dnsServerSet := make([]string, len(dnsServers.([]interface{})))
for i, v := range dnsServers.([]interface{}) {
dnsServerSet[i] = v.(string)
}
orgVdcNetDhcp.DnsServers = dnsServerSet
orgVdcNetDhcp.DnsServers = convertTypeListToSliceOfStrings(dnsServers.([]interface{}))
}

if leaseTime, isLeaseTimeSet := d.GetOk("lease_time"); isLeaseTimeSet {
Expand Down
Loading