Skip to content

Commit

Permalink
Add vcd_org_vdc_template resource and data source (vmware#1276)
Browse files Browse the repository at this point in the history
Signed-off-by: abarreiro <[email protected]>
  • Loading branch information
adambarreiro authored Jun 21, 2024
1 parent f05da65 commit 3fcac89
Show file tree
Hide file tree
Showing 17 changed files with 1,891 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .changes/v3.13.0/1276-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* **New Resource:** `vcd_org_vdc_template` to manage VDC Templates [GH-1276]
* **New Data Source:** `vcd_org_vdc_template` to read VDC Templates [GH-1276]
1 change: 1 addition & 0 deletions .changes/v3.13.0/1276-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Data source `vcd_resource_list` can list VDC Templates [GH-1276]
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ go 1.22.3

require (
github.com/davecgh/go-spew v1.1.1
github.com/google/uuid v1.6.0
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.34.0
github.com/kr/pretty v0.3.1
github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.13
github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.14
)

require (
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
Expand Down Expand Up @@ -148,8 +150,8 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.13 h1:KPiMTxbyHMNKUIeaH43Qh2eHYetH9crpwGUu2SNYiUI=
github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.13/go.mod h1:vbuNYzuADDBFhi9i2dIKWeNxMK1VFF0dACq01amYBIM=
github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.14 h1:yHY0U8bweiVqhCR3OP0ItNdMSLPXeE7uudpXeDZbH/8=
github.com/vmware/go-vcloud-director/v2 v2.25.0-alpha.14/go.mod h1:vbuNYzuADDBFhi9i2dIKWeNxMK1VFF0dACq01amYBIM=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
Expand Down
247 changes: 247 additions & 0 deletions vcd/datasource_vcd_org_vdc_template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package vcd

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

func datasourceVcdOrgVdcTemplate() *schema.Resource {
return &schema.Resource{
ReadContext: datasourceVcdVdcTemplateRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the VDC Template as seen by the System administrator",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the VDC Template as seen by the System administrator",
},
"tenant_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the VDC Template as seen by the tenants (organizations)",
},
"tenant_description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the VDC Template as seen by the tenants (organizations)",
},
"provider_vdc": {
Type: schema.TypeSet,
Computed: true,
Description: "A Provider VDC that the VDCs instantiated from this template use",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
Description: "ID of Provider VDC",
},
"external_network_id": {
Type: schema.TypeString,
Computed: true,
Description: "ID of the External network that the VDCs instantiated from this template use",
},
"gateway_edge_cluster_id": {
Type: schema.TypeString,
Computed: true,
Description: "ID of the Edge Cluster that the VDCs instantiated from this template use with the NSX-T Gateway",
},
"services_edge_cluster_id": {
Type: schema.TypeString,
Computed: true,
Description: "ID of the Edge Cluster that the VDCs instantiated from this template use for services",
},
},
},
},
"allocation_model": {
Type: schema.TypeString,
Computed: true,
Description: "Allocation model that the VDCs instantiated from this template use",
},
"compute_configuration": {
Type: schema.TypeList,
Computed: true,
Description: "The compute configuration for the VDCs instantiated from this template",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cpu_allocated": {
Type: schema.TypeInt,
Computed: true,
Description: "The maximum amount of CPU, in MHz, available to the VMs running within the VDC that is instantiated from this template",
},
"cpu_limit": {
Type: schema.TypeInt,
Computed: true,
Description: "The limit amount of CPU, in MHz, of the VDC that is instantiated from this template. 0 means unlimited",
},
"cpu_guaranteed": {
Type: schema.TypeInt,
Computed: true,
Description: "The percentage of the CPU guaranteed to be available to VMs running within the VDC instantiated from this template",
},
"cpu_speed": {
Type: schema.TypeInt,
Computed: true,
Description: "Specifies the clock frequency, in MHz, for any virtual CPU that is allocated to a VM",
},
"memory_allocated": {
Type: schema.TypeInt,
Computed: true,
Description: "The maximum amount of Memory, in MB, available to the VMs running within the VDC that is instantiated from this template",
},
"memory_limit": {
Type: schema.TypeInt,
Computed: true,
Description: "The limit amount of Memory, in MB, of the VDC that is instantiated from this template. 0 means unlimited",
},
"memory_guaranteed": {
Type: schema.TypeInt,
Computed: true,
Description: "The percentage of the Memory guaranteed to be available to VMs running within the VDC instantiated from this template",
},
"elasticity": {
Type: schema.TypeBool,
Computed: true,
Description: "True if compute capacity can grow or shrink based on demand",
},
"include_vm_memory_overhead": {
Type: schema.TypeBool,
Computed: true,
Description: "True if the instantiated VDC includes memory overhead into its accounting for admission control",
},
},
},
},
"storage_profile": {
Type: schema.TypeSet,
Computed: true,
Description: "Storage profiles that the VDCs instantiated from this template use",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of Provider VDC storage profile to use for the VDCs instantiated from this template",
},
"default": {
Type: schema.TypeBool,
Computed: true,
Description: "True if this is default storage profile for the VDCs instantiated from this template",
},
"limit": {
Type: schema.TypeInt,
Computed: true,
Description: "Storage limit of the VDCs instantiated from this template, in Megabytes. 0 means unlimited",
},
},
},
},
"enable_fast_provisioning": {
Type: schema.TypeBool,
Computed: true,
Description: "If 'true', the VDCs instantiated from this template have Fast provisioning enabled",
},
"enable_thin_provisioning": {
Type: schema.TypeBool,
Computed: true,
Description: "If 'true', the VDCs instantiated from this template have Thin provisioning enabled",
},
"edge_gateway": {
Type: schema.TypeList,
Computed: true,
Description: "VDCs instantiated from this template create a new Edge Gateway with the provided setup",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the Edge Gateway",
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the Edge Gateway",
},
"ip_allocation_count": {
Type: schema.TypeInt,
Computed: true,
Description: "Storage used in MB",
},
"routed_network_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the routed network to create with the Edge Gateway",
},
"routed_network_description": {
Type: schema.TypeString,
Computed: true,
Description: "Description of the routed network to create with the Edge Gateway",
},
"routed_network_gateway_cidr": {
Type: schema.TypeString,
Computed: true,
Description: "CIDR of the Edge Gateway for the routed network created with the Edge Gateway",
},
"static_ip_pool": {
Type: schema.TypeSet,
Computed: true,
Description: "IP ranges used for the network created with the Edge Gateway. Only required if the 'edge_gateway' block is used",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"start_address": {
Type: schema.TypeString,
Computed: true,
Description: "Start address of the IP range",
},
"end_address": {
Type: schema.TypeString,
Computed: true,
Description: "End address of the IP range",
},
},
},
},
},
},
},
"network_pool_id": {
Type: schema.TypeString,
Computed: true,
Description: "The Network pool of the instantiated VDCs. If empty, means that it is automatically chosen",
},
"nic_quota": {
Type: schema.TypeInt,
Computed: true,
Description: "Quota of the NICs of the instantiated VDCs. 0 means unlimited",
},
"vm_quota": {
Type: schema.TypeInt,
Computed: true,
Description: "Quota for the VMs of the instantiated VDCs. 0 means unlimited",
},
"provisioned_network_quota": {
Type: schema.TypeInt,
Computed: true,
Description: "Quota for the provisioned networks of the instantiated VDCs. 0 means unlimited",
},
"readable_by_org_ids": {
Type: schema.TypeSet,
Computed: true,
Description: "IDs of the Organizations that will be able to view and instantiate this VDC template. This attribute is not available for tenants",
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func datasourceVcdVdcTemplateRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
return genericVcdVdcTemplateRead(ctx, d, meta, "datasource")
}
48 changes: 48 additions & 0 deletions vcd/datasource_vcd_resource_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,52 @@ func vappNetworkList(d *schema.ResourceData, vnt vappNetworkType, meta interface
return genericResourceList(d, "vcd_vapp_network", []string{org.Org.Name, vdc.Vdc.Name, vappName}, items)
}

func vdcTemplateList(d *schema.ResourceData, meta interface{}) (list []string, err error) {
client := meta.(*VCDClient)

parentOrg := d.Get("parent").(string)
isSystemOrg := parentOrg == "" || strings.ToLower(parentOrg) == "system"
if isSystemOrg && !client.Client.IsSysAdmin {
return nil, fmt.Errorf("'parent' is not set or is 'System': Only an administrator can list all VDC Templates from System")
}

var items []resourceRef
var ancestors []string
if isSystemOrg {
adminVdcTemplates, err := client.QueryAdminVdcTemplates()
if err != nil {
return nil, err
}
for _, adminVdcTemplate := range adminVdcTemplates {
items = append(items, resourceRef{
name: adminVdcTemplate.Name,
id: extractUuid(adminVdcTemplate.HREF),
href: adminVdcTemplate.HREF,
parent: "System",
})
}
} else {
org, err := client.GetOrg(parentOrg)
if err != nil {
return nil, err
}
vdcTemplates, err := org.QueryVdcTemplates()
if err != nil {
return nil, err
}
for _, vdcTemplate := range vdcTemplates {
items = append(items, resourceRef{
name: vdcTemplate.Name,
id: extractUuid(vdcTemplate.HREF),
href: vdcTemplate.HREF,
parent: org.Org.Name,
})
}
ancestors = []string{org.Org.Name}
}
return genericResourceList(d, "vcd_org_vdc_template", ancestors, items)
}

func genericResourceList(d *schema.ResourceData, resType string, ancestors []string, refs []resourceRef) (list []string, err error) {
listMode := d.Get("list_mode").(string)
nameIdSeparator := d.Get("name_id_separator").(string)
Expand Down Expand Up @@ -1427,6 +1473,8 @@ func datasourceVcdResourceListRead(_ context.Context, d *schema.ResourceData, me
list, err = globalRolesList(d, meta)
case "vcd_library_certificate":
list, err = libraryCertificateList(d, meta)
case "vcd_org_vdc_template":
list, err = vdcTemplateList(d, meta)

//// place holder to remind of what needs to be implemented
// case "edgegateway_vpn",
Expand Down
5 changes: 5 additions & 0 deletions vcd/datasource_vcd_resource_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ func TestAccVcdDatasourceResourceList(t *testing.T) {
{name: "user", resourceType: "vcd_org_user"},
}

if usingSysAdmin() {
lists = append(lists, listDef{name: "admin-vdc-template", resourceType: "vcd_org_vdc_template"})
}

knownNetworkPool1 := testConfig.VCD.ProviderVdc.NetworkPool
if knownNetworkPool1 != "" && usingSysAdmin() {
lists = append(lists, listDef{name: "network_pool", resourceType: "vcd_network_pool", knownItem: knownNetworkPool1})
Expand Down Expand Up @@ -82,6 +86,7 @@ func TestAccVcdDatasourceResourceList(t *testing.T) {
} else {
fmt.Print("`Nsxt.Vdc` value isn't configured, datasource test using this will be skipped\n")
}
lists = append(lists, listDef{name: "vdc-template", resourceType: "vcd_org_vdc_template", parent: testConfig.VCD.Org})
} else {
fmt.Print("`VCD.Org` value isn't configured, datasource test will be skipped\n")
}
Expand Down
2 changes: 2 additions & 0 deletions vcd/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ var globalDataSourceMap = map[string]*schema.Resource{
"vcd_solution_landing_zone": datasourceVcdSolutionLandingZone(), // 3.13
"vcd_solution_add_on": datasourceVcdSolutionAddon(), // 3.13
"vcd_org_oidc": datasourceVcdOrgOidc(), // 3.13
"vcd_org_vdc_template": datasourceVcdOrgVdcTemplate(), // 3.13
}

var globalResourceMap = map[string]*schema.Resource{
Expand Down Expand Up @@ -271,6 +272,7 @@ var globalResourceMap = map[string]*schema.Resource{
"vcd_solution_landing_zone": resourceVcdSolutionLandingZone(), // 3.13
"vcd_solution_add_on": resourceVcdSolutionAddon(), // 3.13
"vcd_org_oidc": resourceVcdOrgOidc(), // 3.13
"vcd_org_vdc_template": resourceVcdOrgVdcTemplate(), // 3.13
}

// Provider returns a terraform.ResourceProvider.
Expand Down
Loading

0 comments on commit 3fcac89

Please sign in to comment.