diff --git a/.changes/v3.5.0/738-features.md b/.changes/v3.5.0/738-features.md new file mode 100644 index 000000000..d9f72d963 --- /dev/null +++ b/.changes/v3.5.0/738-features.md @@ -0,0 +1,4 @@ +* **New Resource:** `vcd_nsxt_alb_edgegateway_service_engine_group` for managing NSX-T ALB Service Engine Groups + assignments to Edge Gateways [GH-738] +* **New Data source:** `vcd_nsxt_alb_edgegateway_service_engine_group` for reading NSX-T ALB Service Engine Groups + assignments to Edge Gateways [GH-738] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 1ed6db75b..fc1fb6ec4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,3 @@ # These owners will be the default owners for everything in the repo. Unless a later match takes -# precedence, @lvirbalas, @dataclouder, and @Didainius will be requested for review when someone -# opens a pull request. -* @lvirbalas @dataclouder @Didainius +# precedence all these users will be requested for review when someone opens a pull request. +* @lvirbalas @dataclouder @Didainius @vbauzysvmware diff --git a/README.md b/README.md index 9e0b7a913..9bd917b8d 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -Terraform vCloud Director Provider +Terraform VMware Cloud Director Provider ================== -The official Terraform provider for [VMware vCloud Director](https://www.vmware.com/products/vcloud-director.html) +The official Terraform provider for [VMware Cloud Director](https://www.vmware.com/products/cloud-director.html) -- Documentation of the latest binary release available at https://www.terraform.io/docs/providers/vcd/index.html +- Documentation of the latest binary release available at https://registry.terraform.io/providers/vmware/vcd/latest/docs - This project is using [go-vcloud-director](https://github.com/vmware/go-vcloud-director) Golang SDK for making API calls to vCD - Join through [VMware {code}](https://code.vmware.com/) to [![Chat](https://img.shields.io/badge/chat-on%20slack-brightgreen.svg)](https://vmwarecode.slack.com/messages/CBBBXVB16) in #vcd-terraform-dev channel @@ -13,8 +13,9 @@ Part of Terraform - Website: https://www.terraform.io - [![Gitter chat](https://badges.gitter.im/hashicorp-terraform/Lobby.png)](https://gitter.im/hashicorp-terraform/Lobby) - Mailing list: [Google Groups](http://groups.google.com/group/terraform-tool) +- [Hashicorp Discuss](https://discuss.hashicorp.com/c/terraform-core/27) - + Requirements ------------ @@ -24,9 +25,10 @@ Requirements Building The Provider (the modules way) -------------------------------------- -**Note.** You *only* need to build the provider plugin if you want to *develop* it. Refer to [documentation](https://www.terraform.io/docs/providers/vcd/) for using it. Terraform will -automatically download officially released binaries of this provider plugin on the first run of -`terraform init` command. +**Note.** You *only* need to build the provider plugin if you want to *develop* it. Refer to +[documentation](https://registry.terraform.io/providers/vmware/vcd/latest/docs) for using it. Terraform will +automatically download officially released binaries of this provider plugin on the first run of `terraform init` +command. Starting with version 2.1 provider started using [Go modules](https://github.com/golang/go/wiki/Modules) This means that it is no longer necessary to be in GOPATH. diff --git a/go.mod b/go.mod index 33483cb48..6a6bc8a46 100644 --- a/go.mod +++ b/go.mod @@ -7,5 +7,5 @@ require ( github.com/hashicorp/go-version v1.3.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.7.0 github.com/kr/pretty v0.2.1 - github.com/vmware/go-vcloud-director/v2 v2.14.0-alpha.2 + github.com/vmware/go-vcloud-director/v2 v2.14.0-alpha.4 ) diff --git a/go.sum b/go.sum index 06403d989..c3278fb64 100644 --- a/go.sum +++ b/go.sum @@ -311,8 +311,8 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/vmware/go-vcloud-director/v2 v2.14.0-alpha.2 h1:yg3+XMstvuGAMe1tc7qkqQ55tN8e2x7SOTAiUMBidyA= -github.com/vmware/go-vcloud-director/v2 v2.14.0-alpha.2/go.mod h1:2BS1yw61VN34WI0/nUYoInFvBc3Zcuf84d4ESiAAl68= +github.com/vmware/go-vcloud-director/v2 v2.14.0-alpha.4 h1:onOig+mUHFd3fcFsRNYW0W/rMd4EWXV+rVS0NBAiFPM= +github.com/vmware/go-vcloud-director/v2 v2.14.0-alpha.4/go.mod h1:2BS1yw61VN34WI0/nUYoInFvBc3Zcuf84d4ESiAAl68= 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.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/vcd/datasource_test.go b/vcd/datasource_test.go index 7ff9f16b9..f09dc2447 100644 --- a/vcd/datasource_test.go +++ b/vcd/datasource_test.go @@ -57,7 +57,7 @@ func testSpecificDataSourceNotFound(t *testing.T, dataSourceName string, vcdClie t.Skip(`No NSX-T configuration detected or not running as System user`) case dataSourceName == "vcd_nsxt_alb_controller" || dataSourceName == "vcd_nsxt_alb_cloud" || dataSourceName == "vcd_nsxt_alb_importable_cloud" || dataSourceName == "vcd_nsxt_alb_service_engine_group" || - dataSourceName == "vcd_nsxt_alb_settings": + dataSourceName == "vcd_nsxt_alb_settings" || dataSourceName == "vcd_nsxt_alb_edgegateway_service_engine_group": skipNoNsxtAlbConfiguration(t) if !usingSysAdmin() { t.Skip(`Works only with system admin privileges`) @@ -159,6 +159,8 @@ func addMandatoryParams(dataSourceName string, mandatoryFields []string, t *test return "" } templateFields = templateFields + `edge_gateway_id = "` + nsxtEdgeGw.EdgeGateway.ID + `"` + "\n" + case "service_engine_group_id": + templateFields = templateFields + `service_engine_group_id = "does-not-exist"` + "\n" case "catalog": templateFields = templateFields + `catalog = "` + testConfig.VCD.Catalog.Name + `"` + "\n" case "vapp_name": diff --git a/vcd/datasource_vcd_nsxt_alb_edgegateway_service_engine_group.go b/vcd/datasource_vcd_nsxt_alb_edgegateway_service_engine_group.go new file mode 100644 index 000000000..892a4f924 --- /dev/null +++ b/vcd/datasource_vcd_nsxt_alb_edgegateway_service_engine_group.go @@ -0,0 +1,88 @@ +package vcd + +import ( + "context" + "fmt" + "net/url" + + "github.com/vmware/go-vcloud-director/v2/govcd" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func datasourceVcdAlbEdgeGatewayServiceEngineGroup() *schema.Resource { + return &schema.Resource{ + ReadContext: datasourceVcdAlbEdgeGatewayServiceEngineGroupRead, + + Schema: map[string]*schema.Schema{ + "org": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name of organization to use, optional if defined at provider " + + "level. Useful when connected as sysadmin working across different organizations", + }, + "vdc": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name of VDC to use, optional if defined at provider level", + }, + "edge_gateway_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Edge Gateway ID in which ALB Service Engine Group should be located", + }, + "service_engine_group_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Edge Gateway ID in which ALB Service Engine Group should be located", + }, + "max_virtual_services": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "Maximum number of virtual services to be used in this Service Engine Group", + }, + "reserved_virtual_services": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "Number of reserved virtual services for this Service Engine Group", + }, + "deployed_virtual_services": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "Number of reserved deployed virtual services for this Service Engine Group", + }, + }, + } +} + +func datasourceVcdAlbEdgeGatewayServiceEngineGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vcdClient := meta.(*VCDClient) + + edgeGatewayId := d.Get("edge_gateway_id").(string) + serviceEngineGroupId := d.Get("service_engine_group_id") + + queryParams := url.Values{} + queryParams.Add("filter", fmt.Sprintf("gatewayRef.id==%s;serviceEngineGroupRef.id==%s", edgeGatewayId, serviceEngineGroupId)) + + edgeAlbServiceEngineAssignments, err := vcdClient.GetAllAlbServiceEngineGroupAssignments(queryParams) + if err != nil { + return diag.Errorf("error reading ALB Service Engine Group assignment to Edge Gateway: %s", err) + } + + if len(edgeAlbServiceEngineAssignments) == 0 { + return diag.FromErr(govcd.ErrorEntityNotFound) + } + + if len(edgeAlbServiceEngineAssignments) > 1 { + return diag.Errorf("more than one Service Engine Group assignment to Edge Gateway found (%d)", len(edgeAlbServiceEngineAssignments)) + } + + setAlbServiceEngineGroupAssignmentData(d, edgeAlbServiceEngineAssignments[0].NsxtAlbServiceEngineGroupAssignment) + d.SetId(edgeAlbServiceEngineAssignments[0].NsxtAlbServiceEngineGroupAssignment.ID) + return nil +} diff --git a/vcd/provider.go b/vcd/provider.go index ab4209bdd..a85e12950 100644 --- a/vcd/provider.go +++ b/vcd/provider.go @@ -29,126 +29,128 @@ func Resources(nameRegexp string, includeDeprecated bool) (map[string]*schema.Re } var globalDataSourceMap = map[string]*schema.Resource{ - "vcd_org": datasourceVcdOrg(), // 2.5 - "vcd_org_user": datasourceVcdOrgUser(), // 3.0 - "vcd_org_vdc": datasourceVcdOrgVdc(), // 2.5 - "vcd_catalog": datasourceVcdCatalog(), // 2.5 - "vcd_catalog_media": datasourceVcdCatalogMedia(), // 2.5 - "vcd_catalog_item": datasourceVcdCatalogItem(), // 2.5 - "vcd_edgegateway": datasourceVcdEdgeGateway(), // 2.5 - "vcd_external_network": datasourceVcdExternalNetwork(), // 2.5 - "vcd_external_network_v2": datasourceVcdExternalNetworkV2(), // 3.0 - "vcd_independent_disk": datasourceVcIndependentDisk(), // 2.5 - "vcd_network_routed": datasourceVcdNetworkRouted(), // 2.5 - "vcd_network_direct": datasourceVcdNetworkDirect(), // 2.5 - "vcd_network_isolated": datasourceVcdNetworkIsolated(), // 2.5 - "vcd_vapp": datasourceVcdVApp(), // 2.5 - "vcd_vapp_vm": datasourceVcdVAppVm(), // 2.6 - "vcd_lb_service_monitor": datasourceVcdLbServiceMonitor(), // 2.4 - "vcd_lb_server_pool": datasourceVcdLbServerPool(), // 2.4 - "vcd_lb_app_profile": datasourceVcdLBAppProfile(), // 2.4 - "vcd_lb_app_rule": datasourceVcdLBAppRule(), // 2.4 - "vcd_lb_virtual_server": datasourceVcdLbVirtualServer(), // 2.4 - "vcd_nsxv_dnat": datasourceVcdNsxvDnat(), // 2.5 - "vcd_nsxv_snat": datasourceVcdNsxvSnat(), // 2.5 - "vcd_nsxv_firewall_rule": datasourceVcdNsxvFirewallRule(), // 2.5 - "vcd_nsxv_dhcp_relay": datasourceVcdNsxvDhcpRelay(), // 2.6 - "vcd_nsxv_ip_set": datasourceVcdIpSet(), // 2.6 - "vcd_vapp_network": datasourceVcdVappNetwork(), // 2.7 - "vcd_vapp_org_network": datasourceVcdVappOrgNetwork(), // 2.7 - "vcd_vm_affinity_rule": datasourceVcdVmAffinityRule(), // 2.9 - "vcd_vm_sizing_policy": datasourceVcdVmSizingPolicy(), // 3.0 - "vcd_nsxt_manager": datasourceVcdNsxtManager(), // 3.0 - "vcd_nsxt_tier0_router": datasourceVcdNsxtTier0Router(), // 3.0 - "vcd_portgroup": datasourceVcdPortgroup(), // 3.0 - "vcd_vcenter": datasourceVcdVcenter(), // 3.0 - "vcd_resource_list": datasourceVcdResourceList(), // 3.1 - "vcd_resource_schema": datasourceVcdResourceSchema(), // 3.1 - "vcd_nsxt_edge_cluster": datasourceVcdNsxtEdgeCluster(), // 3.1 - "vcd_nsxt_edgegateway": datasourceVcdNsxtEdgeGateway(), // 3.1 - "vcd_storage_profile": datasourceVcdStorageProfile(), // 3.1 - "vcd_vm": datasourceVcdStandaloneVm(), // 3.2 - "vcd_network_routed_v2": datasourceVcdNetworkRoutedV2(), // 3.2 - "vcd_network_isolated_v2": datasourceVcdNetworkIsolatedV2(), // 3.2 - "vcd_nsxt_network_imported": datasourceVcdNsxtNetworkImported(), // 3.2 - "vcd_nsxt_network_dhcp": datasourceVcdOpenApiDhcp(), // 3.2 - "vcd_right": datasourceVcdRight(), // 3.3 - "vcd_role": datasourceVcdRole(), // 3.3 - "vcd_global_role": datasourceVcdGlobalRole(), // 3.3 - "vcd_rights_bundle": datasourceVcdRightsBundle(), // 3.3 - "vcd_nsxt_ip_set": datasourceVcdNsxtIpSet(), // 3.3 - "vcd_nsxt_security_group": datasourceVcdNsxtSecurityGroup(), // 3.3 - "vcd_nsxt_app_port_profile": datasourceVcdNsxtAppPortProfile(), // 3.3 - "vcd_nsxt_nat_rule": datasourceVcdNsxtNatRule(), // 3.3 - "vcd_nsxt_firewall": datasourceVcdNsxtFirewall(), // 3.3 - "vcd_nsxt_ipsec_vpn_tunnel": datasourceVcdNsxtIpSecVpnTunnel(), // 3.3 - "vcd_nsxt_alb_importable_cloud": datasourceVcdAlbImportableCloud(), // 3.4 - "vcd_nsxt_alb_controller": datasourceVcdAlbController(), // 3.4 - "vcd_nsxt_alb_cloud": datasourceVcdAlbCloud(), // 3.4 - "vcd_nsxt_alb_service_engine_group": datasourceVcdAlbServiceEngineGroup(), // 3.4 - "vcd_nsxt_alb_settings": datasourceVcdAlbSettings(), // 3.5 - "vcd_library_certificate": datasourceLibraryCertificate(), // 3.5 + "vcd_org": datasourceVcdOrg(), // 2.5 + "vcd_org_user": datasourceVcdOrgUser(), // 3.0 + "vcd_org_vdc": datasourceVcdOrgVdc(), // 2.5 + "vcd_catalog": datasourceVcdCatalog(), // 2.5 + "vcd_catalog_media": datasourceVcdCatalogMedia(), // 2.5 + "vcd_catalog_item": datasourceVcdCatalogItem(), // 2.5 + "vcd_edgegateway": datasourceVcdEdgeGateway(), // 2.5 + "vcd_external_network": datasourceVcdExternalNetwork(), // 2.5 + "vcd_external_network_v2": datasourceVcdExternalNetworkV2(), // 3.0 + "vcd_independent_disk": datasourceVcIndependentDisk(), // 2.5 + "vcd_network_routed": datasourceVcdNetworkRouted(), // 2.5 + "vcd_network_direct": datasourceVcdNetworkDirect(), // 2.5 + "vcd_network_isolated": datasourceVcdNetworkIsolated(), // 2.5 + "vcd_vapp": datasourceVcdVApp(), // 2.5 + "vcd_vapp_vm": datasourceVcdVAppVm(), // 2.6 + "vcd_lb_service_monitor": datasourceVcdLbServiceMonitor(), // 2.4 + "vcd_lb_server_pool": datasourceVcdLbServerPool(), // 2.4 + "vcd_lb_app_profile": datasourceVcdLBAppProfile(), // 2.4 + "vcd_lb_app_rule": datasourceVcdLBAppRule(), // 2.4 + "vcd_lb_virtual_server": datasourceVcdLbVirtualServer(), // 2.4 + "vcd_nsxv_dnat": datasourceVcdNsxvDnat(), // 2.5 + "vcd_nsxv_snat": datasourceVcdNsxvSnat(), // 2.5 + "vcd_nsxv_firewall_rule": datasourceVcdNsxvFirewallRule(), // 2.5 + "vcd_nsxv_dhcp_relay": datasourceVcdNsxvDhcpRelay(), // 2.6 + "vcd_nsxv_ip_set": datasourceVcdIpSet(), // 2.6 + "vcd_vapp_network": datasourceVcdVappNetwork(), // 2.7 + "vcd_vapp_org_network": datasourceVcdVappOrgNetwork(), // 2.7 + "vcd_vm_affinity_rule": datasourceVcdVmAffinityRule(), // 2.9 + "vcd_vm_sizing_policy": datasourceVcdVmSizingPolicy(), // 3.0 + "vcd_nsxt_manager": datasourceVcdNsxtManager(), // 3.0 + "vcd_nsxt_tier0_router": datasourceVcdNsxtTier0Router(), // 3.0 + "vcd_portgroup": datasourceVcdPortgroup(), // 3.0 + "vcd_vcenter": datasourceVcdVcenter(), // 3.0 + "vcd_resource_list": datasourceVcdResourceList(), // 3.1 + "vcd_resource_schema": datasourceVcdResourceSchema(), // 3.1 + "vcd_nsxt_edge_cluster": datasourceVcdNsxtEdgeCluster(), // 3.1 + "vcd_nsxt_edgegateway": datasourceVcdNsxtEdgeGateway(), // 3.1 + "vcd_storage_profile": datasourceVcdStorageProfile(), // 3.1 + "vcd_vm": datasourceVcdStandaloneVm(), // 3.2 + "vcd_network_routed_v2": datasourceVcdNetworkRoutedV2(), // 3.2 + "vcd_network_isolated_v2": datasourceVcdNetworkIsolatedV2(), // 3.2 + "vcd_nsxt_network_imported": datasourceVcdNsxtNetworkImported(), // 3.2 + "vcd_nsxt_network_dhcp": datasourceVcdOpenApiDhcp(), // 3.2 + "vcd_right": datasourceVcdRight(), // 3.3 + "vcd_role": datasourceVcdRole(), // 3.3 + "vcd_global_role": datasourceVcdGlobalRole(), // 3.3 + "vcd_rights_bundle": datasourceVcdRightsBundle(), // 3.3 + "vcd_nsxt_ip_set": datasourceVcdNsxtIpSet(), // 3.3 + "vcd_nsxt_security_group": datasourceVcdNsxtSecurityGroup(), // 3.3 + "vcd_nsxt_app_port_profile": datasourceVcdNsxtAppPortProfile(), // 3.3 + "vcd_nsxt_nat_rule": datasourceVcdNsxtNatRule(), // 3.3 + "vcd_nsxt_firewall": datasourceVcdNsxtFirewall(), // 3.3 + "vcd_nsxt_ipsec_vpn_tunnel": datasourceVcdNsxtIpSecVpnTunnel(), // 3.3 + "vcd_nsxt_alb_importable_cloud": datasourceVcdAlbImportableCloud(), // 3.4 + "vcd_nsxt_alb_controller": datasourceVcdAlbController(), // 3.4 + "vcd_nsxt_alb_cloud": datasourceVcdAlbCloud(), // 3.4 + "vcd_nsxt_alb_service_engine_group": datasourceVcdAlbServiceEngineGroup(), // 3.4 + "vcd_nsxt_alb_settings": datasourceVcdAlbSettings(), // 3.5 + "vcd_nsxt_alb_edgegateway_service_engine_group": datasourceVcdAlbEdgeGatewayServiceEngineGroup(), // 3.5 + "vcd_library_certificate": datasourceLibraryCertificate(), // 3.5 } var globalResourceMap = map[string]*schema.Resource{ - "vcd_network_routed": resourceVcdNetworkRouted(), // 2.0 - "vcd_network_direct": resourceVcdNetworkDirect(), // 2.0 - "vcd_network_isolated": resourceVcdNetworkIsolated(), // 2.0 - "vcd_vapp_network": resourceVcdVappNetwork(), // 2.1 - "vcd_vapp": resourceVcdVApp(), // 1.0 - "vcd_edgegateway": resourceVcdEdgeGateway(), // 2.4 - "vcd_edgegateway_vpn": resourceVcdEdgeGatewayVpn(), // 1.0 - "vcd_edgegateway_settings": resourceVcdEdgeGatewaySettings(), // 3.0 - "vcd_vapp_vm": resourceVcdVAppVm(), // 1.0 - "vcd_org": resourceOrg(), // 2.0 - "vcd_org_vdc": resourceVcdOrgVdc(), // 2.2 - "vcd_org_user": resourceVcdOrgUser(), // 2.4 - "vcd_catalog": resourceVcdCatalog(), // 2.0 - "vcd_catalog_item": resourceVcdCatalogItem(), // 2.0 - "vcd_catalog_media": resourceVcdCatalogMedia(), // 2.0 - "vcd_inserted_media": resourceVcdInsertedMedia(), // 2.1 - "vcd_independent_disk": resourceVcdIndependentDisk(), // 2.1 - "vcd_external_network": resourceVcdExternalNetwork(), // 2.2 - "vcd_lb_service_monitor": resourceVcdLbServiceMonitor(), // 2.4 - "vcd_lb_server_pool": resourceVcdLBServerPool(), // 2.4 - "vcd_lb_app_profile": resourceVcdLBAppProfile(), // 2.4 - "vcd_lb_app_rule": resourceVcdLBAppRule(), // 2.4 - "vcd_lb_virtual_server": resourceVcdLBVirtualServer(), // 2.4 - "vcd_nsxv_dnat": resourceVcdNsxvDnat(), // 2.5 - "vcd_nsxv_snat": resourceVcdNsxvSnat(), // 2.5 - "vcd_nsxv_firewall_rule": resourceVcdNsxvFirewallRule(), // 2.5 - "vcd_nsxv_dhcp_relay": resourceVcdNsxvDhcpRelay(), // 2.6 - "vcd_nsxv_ip_set": resourceVcdIpSet(), // 2.6 - "vcd_vm_internal_disk": resourceVmInternalDisk(), // 2.7 - "vcd_vapp_org_network": resourceVcdVappOrgNetwork(), // 2.7 - "vcd_org_group": resourceVcdOrgGroup(), // 2.9 - "vcd_vapp_firewall_rules": resourceVcdVappFirewallRules(), // 2.9 - "vcd_vapp_nat_rules": resourceVcdVappNetworkNatRules(), // 2.9 - "vcd_vapp_static_routing": resourceVcdVappNetworkStaticRouting(), // 2.9 - "vcd_vm_affinity_rule": resourceVcdVmAffinityRule(), // 2.9 - "vcd_vapp_access_control": resourceVcdAccessControlVapp(), // 3.0 - "vcd_external_network_v2": resourceVcdExternalNetworkV2(), // 3.0 - "vcd_vm_sizing_policy": resourceVcdVmSizingPolicy(), // 3.0 - "vcd_nsxt_edgegateway": resourceVcdNsxtEdgeGateway(), // 3.1 - "vcd_vm": resourceVcdStandaloneVm(), // 3.2 - "vcd_network_routed_v2": resourceVcdNetworkRoutedV2(), // 3.2 - "vcd_network_isolated_v2": resourceVcdNetworkIsolatedV2(), // 3.2 - "vcd_nsxt_network_imported": resourceVcdNsxtNetworkImported(), // 3.2 - "vcd_nsxt_network_dhcp": resourceVcdOpenApiDhcp(), // 3.2 - "vcd_role": resourceVcdRole(), // 3.3 - "vcd_global_role": resourceVcdGlobalRole(), // 3.3 - "vcd_rights_bundle": resourceVcdRightsBundle(), // 3.3 - "vcd_nsxt_ip_set": resourceVcdNsxtIpSet(), // 3.3 - "vcd_nsxt_security_group": resourceVcdSecurityGroup(), // 3.3 - "vcd_nsxt_firewall": resourceVcdNsxtFirewall(), // 3.3 - "vcd_nsxt_app_port_profile": resourceVcdNsxtAppPortProfile(), // 3.3 - "vcd_nsxt_nat_rule": resourceVcdNsxtNatRule(), // 3.3 - "vcd_nsxt_ipsec_vpn_tunnel": resourceVcdNsxtIpSecVpnTunnel(), // 3.3 - "vcd_nsxt_alb_cloud": resourceVcdAlbCloud(), // 3.4 - "vcd_nsxt_alb_controller": resourceVcdAlbController(), // 3.4 - "vcd_nsxt_alb_service_engine_group": resourceVcdAlbServiceEngineGroup(), // 3.4 - "vcd_nsxt_alb_settings": resourceVcdAlbSettings(), // 3.5 - "vcd_library_certificate": resourceLibraryCertificate(), // 3.5 + "vcd_network_routed": resourceVcdNetworkRouted(), // 2.0 + "vcd_network_direct": resourceVcdNetworkDirect(), // 2.0 + "vcd_network_isolated": resourceVcdNetworkIsolated(), // 2.0 + "vcd_vapp_network": resourceVcdVappNetwork(), // 2.1 + "vcd_vapp": resourceVcdVApp(), // 1.0 + "vcd_edgegateway": resourceVcdEdgeGateway(), // 2.4 + "vcd_edgegateway_vpn": resourceVcdEdgeGatewayVpn(), // 1.0 + "vcd_edgegateway_settings": resourceVcdEdgeGatewaySettings(), // 3.0 + "vcd_vapp_vm": resourceVcdVAppVm(), // 1.0 + "vcd_org": resourceOrg(), // 2.0 + "vcd_org_vdc": resourceVcdOrgVdc(), // 2.2 + "vcd_org_user": resourceVcdOrgUser(), // 2.4 + "vcd_catalog": resourceVcdCatalog(), // 2.0 + "vcd_catalog_item": resourceVcdCatalogItem(), // 2.0 + "vcd_catalog_media": resourceVcdCatalogMedia(), // 2.0 + "vcd_inserted_media": resourceVcdInsertedMedia(), // 2.1 + "vcd_independent_disk": resourceVcdIndependentDisk(), // 2.1 + "vcd_external_network": resourceVcdExternalNetwork(), // 2.2 + "vcd_lb_service_monitor": resourceVcdLbServiceMonitor(), // 2.4 + "vcd_lb_server_pool": resourceVcdLBServerPool(), // 2.4 + "vcd_lb_app_profile": resourceVcdLBAppProfile(), // 2.4 + "vcd_lb_app_rule": resourceVcdLBAppRule(), // 2.4 + "vcd_lb_virtual_server": resourceVcdLBVirtualServer(), // 2.4 + "vcd_nsxv_dnat": resourceVcdNsxvDnat(), // 2.5 + "vcd_nsxv_snat": resourceVcdNsxvSnat(), // 2.5 + "vcd_nsxv_firewall_rule": resourceVcdNsxvFirewallRule(), // 2.5 + "vcd_nsxv_dhcp_relay": resourceVcdNsxvDhcpRelay(), // 2.6 + "vcd_nsxv_ip_set": resourceVcdIpSet(), // 2.6 + "vcd_vm_internal_disk": resourceVmInternalDisk(), // 2.7 + "vcd_vapp_org_network": resourceVcdVappOrgNetwork(), // 2.7 + "vcd_org_group": resourceVcdOrgGroup(), // 2.9 + "vcd_vapp_firewall_rules": resourceVcdVappFirewallRules(), // 2.9 + "vcd_vapp_nat_rules": resourceVcdVappNetworkNatRules(), // 2.9 + "vcd_vapp_static_routing": resourceVcdVappNetworkStaticRouting(), // 2.9 + "vcd_vm_affinity_rule": resourceVcdVmAffinityRule(), // 2.9 + "vcd_vapp_access_control": resourceVcdAccessControlVapp(), // 3.0 + "vcd_external_network_v2": resourceVcdExternalNetworkV2(), // 3.0 + "vcd_vm_sizing_policy": resourceVcdVmSizingPolicy(), // 3.0 + "vcd_nsxt_edgegateway": resourceVcdNsxtEdgeGateway(), // 3.1 + "vcd_vm": resourceVcdStandaloneVm(), // 3.2 + "vcd_network_routed_v2": resourceVcdNetworkRoutedV2(), // 3.2 + "vcd_network_isolated_v2": resourceVcdNetworkIsolatedV2(), // 3.2 + "vcd_nsxt_network_imported": resourceVcdNsxtNetworkImported(), // 3.2 + "vcd_nsxt_network_dhcp": resourceVcdOpenApiDhcp(), // 3.2 + "vcd_role": resourceVcdRole(), // 3.3 + "vcd_global_role": resourceVcdGlobalRole(), // 3.3 + "vcd_rights_bundle": resourceVcdRightsBundle(), // 3.3 + "vcd_nsxt_ip_set": resourceVcdNsxtIpSet(), // 3.3 + "vcd_nsxt_security_group": resourceVcdSecurityGroup(), // 3.3 + "vcd_nsxt_firewall": resourceVcdNsxtFirewall(), // 3.3 + "vcd_nsxt_app_port_profile": resourceVcdNsxtAppPortProfile(), // 3.3 + "vcd_nsxt_nat_rule": resourceVcdNsxtNatRule(), // 3.3 + "vcd_nsxt_ipsec_vpn_tunnel": resourceVcdNsxtIpSecVpnTunnel(), // 3.3 + "vcd_nsxt_alb_cloud": resourceVcdAlbCloud(), // 3.4 + "vcd_nsxt_alb_controller": resourceVcdAlbController(), // 3.4 + "vcd_nsxt_alb_service_engine_group": resourceVcdAlbServiceEngineGroup(), // 3.4 + "vcd_nsxt_alb_settings": resourceVcdAlbSettings(), // 3.5 + "vcd_nsxt_alb_edgegateway_service_engine_group": resourceVcdAlbEdgeGatewayServiceEngineGroup(), // 3.5 + "vcd_library_certificate": resourceLibraryCertificate(), // 3.5 } // Provider returns a terraform.ResourceProvider. diff --git a/vcd/resource_vcd_nsxt_alb_edgegateway_service_engine_group.go b/vcd/resource_vcd_nsxt_alb_edgegateway_service_engine_group.go new file mode 100644 index 000000000..b1a21a499 --- /dev/null +++ b/vcd/resource_vcd_nsxt_alb_edgegateway_service_engine_group.go @@ -0,0 +1,198 @@ +package vcd + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/vmware/go-vcloud-director/v2/types/v56" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceVcdAlbEdgeGatewayServiceEngineGroup() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceVcdAlbEdgeGatewayServiceEngineGroupCreate, + UpdateContext: resourceVcdAlbEdgeGatewayServiceEngineGroupUpdate, + ReadContext: resourceVcdAlbEdgeGatewayServiceEngineGroupRead, + DeleteContext: resourceVcdAlbEdgeGatewayServiceEngineGroupDelete, + Importer: &schema.ResourceImporter{ + StateContext: resourceVcdAlbEdgeGatewayServiceEngineGroupImport, + }, + + Schema: map[string]*schema.Schema{ + "org": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name of organization to use, optional if defined at provider " + + "level. Useful when connected as sysadmin working across different organizations", + }, + "vdc": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: "The name of VDC to use, optional if defined at provider level", + }, + "edge_gateway_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Edge Gateway ID in which ALB Service Engine Group should be located", + }, + "service_engine_group_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Edge Gateway ID in which ALB Service Engine Group should be located", + }, + "max_virtual_services": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "Maximum number of virtual services to be used in this Service Engine Group", + }, + "reserved_virtual_services": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: "Number of reserved virtual services for this Service Engine Group", + }, + "deployed_virtual_services": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "Number of deployed virtual services for this Service Engine Group", + }, + }, + } +} + +func resourceVcdAlbEdgeGatewayServiceEngineGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vcdClient := meta.(*VCDClient) + vcdClient.lockParentEdgeGtw(d) + defer vcdClient.unLockParentEdgeGtw(d) + + edgeAlbServiceEngineGroupAssignmentConfig := getAlbServiceEngineGroupAssignmentType(d) + edgeAlbServiceEngineGroupAssignment, err := vcdClient.CreateAlbServiceEngineGroupAssignment(edgeAlbServiceEngineGroupAssignmentConfig) + if err != nil { + return diag.Errorf("error creating ALB Service Engine Group assignment to Edge Gateway: %s", err) + } + + d.SetId(edgeAlbServiceEngineGroupAssignment.NsxtAlbServiceEngineGroupAssignment.ID) + return resourceVcdAlbEdgeGatewayServiceEngineGroupRead(ctx, d, meta) +} + +func resourceVcdAlbEdgeGatewayServiceEngineGroupUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vcdClient := meta.(*VCDClient) + vcdClient.lockParentEdgeGtw(d) + defer vcdClient.unLockParentEdgeGtw(d) + + edgeAlbServiceEngineGroupAssignment, err := vcdClient.GetAlbServiceEngineGroupAssignmentById(d.Id()) + if err != nil { + return diag.Errorf("error reading ALB Service Engine Group assignment to Edge Gateway: %s", err) + } + edgeAlbServiceEngineGroupAssignmentConfig := getAlbServiceEngineGroupAssignmentType(d) + // Add correct ID for update + edgeAlbServiceEngineGroupAssignmentConfig.ID = edgeAlbServiceEngineGroupAssignment.NsxtAlbServiceEngineGroupAssignment.ID + updatedEdgeAlbServiceEngineGroupAssignment, err := edgeAlbServiceEngineGroupAssignment.Update(edgeAlbServiceEngineGroupAssignmentConfig) + if err != nil { + return diag.Errorf("error updating ALB Service Engine Group assignment to Edge Gateway: %s", err) + } + + d.SetId(updatedEdgeAlbServiceEngineGroupAssignment.NsxtAlbServiceEngineGroupAssignment.ID) + return resourceVcdAlbEdgeGatewayServiceEngineGroupRead(ctx, d, meta) +} + +func resourceVcdAlbEdgeGatewayServiceEngineGroupRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vcdClient := meta.(*VCDClient) + + edgeAlbServiceEngineGroupAssignment, err := vcdClient.GetAlbServiceEngineGroupAssignmentById(d.Id()) + if err != nil { + return diag.Errorf("error reading ALB Service Engine Group assignment: %s", err) + } + setAlbServiceEngineGroupAssignmentData(d, edgeAlbServiceEngineGroupAssignment.NsxtAlbServiceEngineGroupAssignment) + d.SetId(edgeAlbServiceEngineGroupAssignment.NsxtAlbServiceEngineGroupAssignment.ID) + return nil +} + +func resourceVcdAlbEdgeGatewayServiceEngineGroupDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + vcdClient := meta.(*VCDClient) + vcdClient.lockParentEdgeGtw(d) + defer vcdClient.unLockParentEdgeGtw(d) + + edgeAlbServiceEngineGroupAssignment, err := vcdClient.GetAlbServiceEngineGroupAssignmentById(d.Id()) + if err != nil { + return diag.Errorf("error reading ALB Service Engine Group assignment to Edge Gateway: %s", err) + } + + err = edgeAlbServiceEngineGroupAssignment.Delete() + if err != nil { + return diag.Errorf("error deleting ALB Service Engine Group assignment to Edge Gateway: %s", err) + } + return nil +} + +func resourceVcdAlbEdgeGatewayServiceEngineGroupImport(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + log.Printf("[TRACE] NSX-T ALB Service Engine Group assignment import initiated") + + resourceURI := strings.Split(d.Id(), ImportSeparator) + if len(resourceURI) != 4 { + return nil, fmt.Errorf("resource name must be specified as org-name.vdc-name.nsxt-edge-gw-name.se-group-name") + } + orgName, vdcName, edgeName, seGroupName := resourceURI[0], resourceURI[1], resourceURI[2], resourceURI[3] + + vcdClient := meta.(*VCDClient) + + _, vdc, err := vcdClient.GetOrgAndVdc(orgName, vdcName) + if err != nil { + return nil, fmt.Errorf("unable to find Org %s: %s", vdcName, err) + } + + if vdc.IsNsxv() { + return nil, fmt.Errorf("this resource is only supported for NSX-T Edge Gateways") + } + + edge, err := vdc.GetNsxtEdgeGatewayByName(edgeName) + if err != nil { + return nil, fmt.Errorf("could not retrieve NSX-T Edge Gateway with ID '%s': %s", d.Id(), err) + } + + seGroupAssignment, err := vcdClient.GetAlbServiceEngineGroupAssignmentByName(seGroupName) + if err != nil { + return nil, fmt.Errorf("errorr retrieving Servce Engine Group assignment to Edge Gateway with Name '%s': %s", + seGroupName, err) + } + + dSet(d, "edge_gateway_id", edge.EdgeGateway.ID) + d.SetId(seGroupAssignment.NsxtAlbServiceEngineGroupAssignment.ID) + return []*schema.ResourceData{d}, nil +} + +func setAlbServiceEngineGroupAssignmentData(d *schema.ResourceData, t *types.NsxtAlbServiceEngineGroupAssignment) { + dSet(d, "edge_gateway_id", t.GatewayRef.ID) + dSet(d, "service_engine_group_id", t.ServiceEngineGroupRef.ID) + dSet(d, "max_virtual_services", t.MaxVirtualServices) + dSet(d, "reserved_virtual_services", t.MinVirtualServices) + dSet(d, "deployed_virtual_services", t.NumDeployedVirtualServices) +} + +func getAlbServiceEngineGroupAssignmentType(d *schema.ResourceData) *types.NsxtAlbServiceEngineGroupAssignment { + edgeAlbServiceEngineAssignmentConfig := &types.NsxtAlbServiceEngineGroupAssignment{ + GatewayRef: &types.OpenApiReference{ID: d.Get("edge_gateway_id").(string)}, + ServiceEngineGroupRef: &types.OpenApiReference{ID: d.Get("service_engine_group_id").(string)}, + } + + // Max Virtual Services and Reserved Virtual Services only work with SHARED Service Engine Group, but validation + // enforcement is left for VCD API. + if maxServicesInterface, isSet := d.GetOk("max_virtual_services"); isSet { + edgeAlbServiceEngineAssignmentConfig.MaxVirtualServices = takeIntPointer(maxServicesInterface.(int)) + } + + if reservedServicesInterface, isSet := d.GetOk("reserved_virtual_services"); isSet { + edgeAlbServiceEngineAssignmentConfig.MinVirtualServices = takeIntPointer(reservedServicesInterface.(int)) + } + + return edgeAlbServiceEngineAssignmentConfig +} diff --git a/vcd/resource_vcd_nsxt_alb_edgegateway_service_engine_group_test.go b/vcd/resource_vcd_nsxt_alb_edgegateway_service_engine_group_test.go new file mode 100644 index 000000000..ccd9ca9e6 --- /dev/null +++ b/vcd/resource_vcd_nsxt_alb_edgegateway_service_engine_group_test.go @@ -0,0 +1,224 @@ +//go:build nsxt || alb || ALL || functional +// +build nsxt alb ALL functional + +package vcd + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccVcdNsxtEdgeGatewayServiceEngineGroupDedicated(t *testing.T) { + preTestChecks(t) + if !usingSysAdmin() { + t.Skip(t.Name() + " requires system admin privileges") + return + } + + vcdClient := createTemporaryVCDConnection() + if vcdClient.Client.APIVCDMaxVersionIs("< 35.0") { + t.Skip(t.Name() + " requires at least API v35.0 (vCD 10.2+)") + } + skipNoNsxtAlbConfiguration(t) + + // String map to fill the template + var params = StringMap{ + "ControllerName": t.Name(), + "ControllerUrl": testConfig.Nsxt.NsxtAlbControllerUrl, + "ControllerUsername": testConfig.Nsxt.NsxtAlbControllerUser, + "ControllerPassword": testConfig.Nsxt.NsxtAlbControllerPassword, + "ReservationModel": "DEDICATED", + "ImportableCloud": testConfig.Nsxt.NsxtAlbImportableCloud, + "Org": testConfig.VCD.Org, + "NsxtVdc": testConfig.Nsxt.Vdc, + "EdgeGw": testConfig.Nsxt.EdgeGateway, + "Tags": "nsxt alb", + } + + params["FuncName"] = t.Name() + "step1" + params["IsActive"] = "true" + configText1 := templateFill(testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupDedicated, params) + debugPrintf("#[DEBUG] CONFIGURATION for step 1: %s", configText1) + + params["FuncName"] = t.Name() + "step2" + configText2 := templateFill(testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupDedicatedDS, params) + debugPrintf("#[DEBUG] CONFIGURATION for step 2: %s", configText2) + + if vcdShortTest { + t.Skip(acceptanceTestsSkipped) + return + } + + resource.Test(t, resource.TestCase{ + ProviderFactories: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: resource.ComposeAggregateTestCheckFunc( + testAccCheckVcdAlbControllerDestroy("vcd_nsxt_alb_controller.first"), + testAccCheckVcdAlbServiceEngineGroupDestroy("vcd_nsxt_alb_cloud.first"), + testAccCheckVcdAlbCloudDestroy("vcd_nsxt_alb_cloud.first"), + testAccCheckVcdNsxtEdgeGatewayAlbSettingsDestroy(params["EdgeGw"].(string)), + ), + + Steps: []resource.TestStep{ + resource.TestStep{ + Config: configText1, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "id", regexp.MustCompile(`\d*`)), + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "deployed_virtual_services", regexp.MustCompile(`\d*`)), + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "reserved_virtual_services", regexp.MustCompile(`\d*`)), + ), + }, + resource.TestStep{ + Config: configText2, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "id", regexp.MustCompile(`\d*`)), + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "deployed_virtual_services", regexp.MustCompile(`\d*`)), + resourceFieldsEqual("data.vcd_nsxt_alb_edgegateway_service_engine_group.test", "vcd_nsxt_alb_edgegateway_service_engine_group.test", nil), + ), + }, + resource.TestStep{ + ResourceName: "vcd_nsxt_alb_edgegateway_service_engine_group.test", + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: importStateIdNsxtEdgeGatewayObject(testConfig, params["EdgeGw"].(string), "first-se"), + }, + }, + }) + postTestChecks(t) +} + +const testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupDedicated = testAccVcdNsxtAlbGeneralSettings + ` +resource "vcd_nsxt_alb_edgegateway_service_engine_group" "test" { + edge_gateway_id = data.vcd_nsxt_edgegateway.existing.id + service_engine_group_id = vcd_nsxt_alb_service_engine_group.first.id +} +` + +const testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupDedicatedDS = testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupDedicated + ` +data "vcd_nsxt_alb_edgegateway_service_engine_group" "test" { + edge_gateway_id = data.vcd_nsxt_edgegateway.existing.id + service_engine_group_id = vcd_nsxt_alb_service_engine_group.first.id +} +` + +func TestAccVcdNsxtEdgeGatewayServiceEngineGroupShared(t *testing.T) { + preTestChecks(t) + if !usingSysAdmin() { + t.Skip(t.Name() + " requires system admin privileges") + return + } + + vcdClient := createTemporaryVCDConnection() + if vcdClient.Client.APIVCDMaxVersionIs("< 35.0") { + t.Skip(t.Name() + " requires at least API v35.0 (vCD 10.2+)") + } + skipNoNsxtAlbConfiguration(t) + + // String map to fill the template + var params = StringMap{ + "ControllerName": t.Name(), + "ControllerUrl": testConfig.Nsxt.NsxtAlbControllerUrl, + "ControllerUsername": testConfig.Nsxt.NsxtAlbControllerUser, + "ControllerPassword": testConfig.Nsxt.NsxtAlbControllerPassword, + "ReservationModel": "SHARED", + "ImportableCloud": testConfig.Nsxt.NsxtAlbImportableCloud, + "Org": testConfig.VCD.Org, + "NsxtVdc": testConfig.Nsxt.Vdc, + "EdgeGw": testConfig.Nsxt.EdgeGateway, + "Tags": "nsxt alb", + } + + params["FuncName"] = t.Name() + "step1" + params["IsActive"] = "true" + configText1 := templateFill(testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupShared, params) + debugPrintf("#[DEBUG] CONFIGURATION for step 1: %s", configText1) + + params["FuncName"] = t.Name() + "step2" + configText2 := templateFill(testAccVcdNsxtAlbEdgeServiceEngineGroupSharedDS, params) + debugPrintf("#[DEBUG] CONFIGURATION for step 2: %s", configText2) + + params["FuncName"] = t.Name() + "step3" + configText3 := templateFill(testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupSharedStep3, params) + debugPrintf("#[DEBUG] CONFIGURATION for step 3: %s", configText3) + + if vcdShortTest { + t.Skip(acceptanceTestsSkipped) + return + } + + resource.Test(t, resource.TestCase{ + ProviderFactories: testAccProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: resource.ComposeAggregateTestCheckFunc( + testAccCheckVcdAlbControllerDestroy("vcd_nsxt_alb_controller.first"), + testAccCheckVcdAlbServiceEngineGroupDestroy("vcd_nsxt_alb_cloud.first"), + testAccCheckVcdAlbCloudDestroy("vcd_nsxt_alb_cloud.first"), + testAccCheckVcdNsxtEdgeGatewayAlbSettingsDestroy(params["EdgeGw"].(string)), + ), + + Steps: []resource.TestStep{ + resource.TestStep{ + Config: configText1, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "id", regexp.MustCompile(`\d*`)), + resource.TestCheckResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "max_virtual_services", "100"), + resource.TestCheckResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "reserved_virtual_services", "30"), + resource.TestCheckResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "deployed_virtual_services", "0"), + ), + }, + resource.TestStep{ + Config: configText2, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "id", regexp.MustCompile(`\d*`)), + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "deployed_virtual_services", regexp.MustCompile(`\d*`)), + resourceFieldsEqual("data.vcd_nsxt_alb_edgegateway_service_engine_group.test", "vcd_nsxt_alb_edgegateway_service_engine_group.test", nil), + ), + }, + resource.TestStep{ + Config: configText3, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "id", regexp.MustCompile(`\d*`)), + resource.TestCheckResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "max_virtual_services", "70"), + resource.TestCheckResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "reserved_virtual_services", "35"), + resource.TestCheckResourceAttr("vcd_nsxt_alb_edgegateway_service_engine_group.test", "deployed_virtual_services", "0"), + ), + }, + resource.TestStep{ + ResourceName: "vcd_nsxt_alb_edgegateway_service_engine_group.test", + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: importStateIdNsxtEdgeGatewayObject(testConfig, params["EdgeGw"].(string), "first-se"), + }, + }, + }) + postTestChecks(t) +} + +const testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupShared = testAccVcdNsxtAlbGeneralSettings + ` +resource "vcd_nsxt_alb_edgegateway_service_engine_group" "test" { + edge_gateway_id = data.vcd_nsxt_edgegateway.existing.id + service_engine_group_id = vcd_nsxt_alb_service_engine_group.first.id + + max_virtual_services = 100 + reserved_virtual_services = 30 +} +` + +const testAccVcdNsxtAlbEdgeServiceEngineGroupSharedDS = testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupDedicated + ` +data "vcd_nsxt_alb_edgegateway_service_engine_group" "test" { + edge_gateway_id = data.vcd_nsxt_edgegateway.existing.id + service_engine_group_id = vcd_nsxt_alb_service_engine_group.first.id +} +` + +const testAccVcdNsxtAlbEdgeGatewayServiceEngineGroupSharedStep3 = testAccVcdNsxtAlbGeneralSettings + ` +resource "vcd_nsxt_alb_edgegateway_service_engine_group" "test" { + edge_gateway_id = data.vcd_nsxt_edgegateway.existing.id + service_engine_group_id = vcd_nsxt_alb_service_engine_group.first.id + + max_virtual_services = 70 + reserved_virtual_services = 35 +} +` diff --git a/vcd/resource_vcd_nsxt_alb_settings_test.go b/vcd/resource_vcd_nsxt_alb_settings_test.go index 42def816d..f968099b1 100644 --- a/vcd/resource_vcd_nsxt_alb_settings_test.go +++ b/vcd/resource_vcd_nsxt_alb_settings_test.go @@ -33,6 +33,7 @@ func TestAccVcdNsxtAlbSettings(t *testing.T) { "ControllerUsername": testConfig.Nsxt.NsxtAlbControllerUser, "ControllerPassword": testConfig.Nsxt.NsxtAlbControllerPassword, "ImportableCloud": testConfig.Nsxt.NsxtAlbImportableCloud, + "ReservationModel": "DEDICATED", "Org": testConfig.VCD.Org, "NsxtVdc": testConfig.Nsxt.Vdc, "EdgeGw": testConfig.Nsxt.EdgeGateway, @@ -149,7 +150,7 @@ resource "vcd_nsxt_alb_service_engine_group" "first" { name = "first-se" alb_cloud_id = vcd_nsxt_alb_cloud.first.id importable_service_engine_group_name = "Default-Group" - reservation_model = "DEDICATED" + reservation_model = "{{.ReservationModel}}" } ` diff --git a/website/docs/d/nsxt_alb_edgegateway_service_engine_group.html.markdown b/website/docs/d/nsxt_alb_edgegateway_service_engine_group.html.markdown new file mode 100644 index 000000000..da085a1dc --- /dev/null +++ b/website/docs/d/nsxt_alb_edgegateway_service_engine_group.html.markdown @@ -0,0 +1,51 @@ +--- +layout: "vcd" +page_title: "VMware Cloud Director: vcd_nsxt_alb_edgegateway_service_engine_group" +sidebar_current: "docs-vcd-datasource-nsxt-alb-edgegateway-service-engine-group" +description: |- + Provides a datasource to read NSX-T ALB Service Engine Group assignment to NSX-T Edge Gateway. +--- + +# vcd\_nsxt\_alb\_edgegateway\_service\_engine\_group + +Supported in provider *v3.5+* and VCD 10.2+ with NSX-T and ALB. + +Provides a datasource to read NSX-T ALB Service Engine Group assignment to NSX-T Edge Gateway. + +## Example Usage + +```hcl +data "vcd_nsxt_edgegateway" "existing" { + org = "my-org" + vdc = "nsxt-vdc" + + name = "nsxt-gw" +} + +data "vcd_nsxt_alb_service_engine_group" "first" { + name = "first-se" +} + +data "vcd_nsxt_alb_edgegateway_service_engine_group" "test" { + edge_gateway_id = data.vcd_nsxt_edgegateway.existing.id + service_engine_group_id = data.vcd_nsxt_alb_service_engine_group.first.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `org` - (Optional) The name of organization to which the edge gateway belongs. Optional if defined at provider level. +* `vdc` - (Optional) The name of VDC that owns the edge gateway. Optional if defined at provider level. +* `edge_gateway_id` - (Required) An ID of NSX-T Edge Gateway. Can be lookup up using + [vcd_nsxt_edgegateway](/providers/vmware/vcd/latest/docs/data-sources/nsxt_edgegateway) data source +* `service_engine_group_id` - (Required) An ID of NSX-T Service Engine Group. Can be looked up using + [vcd_nsxt_alb_service_engine_group](/providers/vmware/vcd/latest/docs/data-sources/nsxt_alb_service_engine_group) data + source + +## Attribute Reference + +All the arguments and attributes defined in +[`vcd_nsxt_alb_edgegateway_service_engine_group`](/providers/vmware/vcd/latest/docs/resources/nsxt_alb_edgegateway_service_engine_group) +resource are available. diff --git a/website/docs/r/nsxt_alb_edgegateway_service_engine_group.html.markdown b/website/docs/r/nsxt_alb_edgegateway_service_engine_group.html.markdown new file mode 100644 index 000000000..340b05694 --- /dev/null +++ b/website/docs/r/nsxt_alb_edgegateway_service_engine_group.html.markdown @@ -0,0 +1,78 @@ +--- +layout: "vcd" +page_title: "VMware Cloud Director: vcd_nsxt_alb_edgegateway_service_engine_group" +sidebar_current: "docs-vcd-resource-nsxt-alb-edge-service-engine-group" +description: |- + Provides a resource to manage NSX-T ALB Service Engine Group assignment to Edge Gateway. +--- + +# vcd\_nsxt\_alb\_edgegateway\_service\_engine\_group + +Supported in provider *v3.5+* and VCD 10.2+ with NSX-T and ALB. + +Provides a resource to manage NSX-T ALB Service Engine Group assignment to NSX-T Edge Gateway. + +~> Only `System Administrator` can create this resource. + +## Example Usage (Enabling NSX-T ALB on NSX-T Edge Gateway) + +```hcl +data "vcd_nsxt_edgegateway" "existing" { + org = "my-org" + vdc = "nsxt-vdc" + + name = "nsxt-gw" +} + +data "vcd_nsxt_alb_service_engine_group" "first" { + name = "first-se" +} + +resource "vcd_nsxt_alb_edgegateway_service_engine_group" "first" { + edge_gateway_id = data.vcd_nsxt_edgegateway.existing.id + service_engine_group_id = data.vcd_nsxt_alb_service_engine_group.first.id + + max_virtual_services = 100 + reserved_virtual_services = 30 +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `org` - (Optional) The name of organization to which the edge gateway belongs. Optional if defined at provider level. +* `vdc` - (Optional) The name of VDC that owns the edge gateway. Optional if defined at provider level. +* `edge_gateway_id` - (Required) An ID of NSX-T Edge Gateway. Can be looked up using + [vcd_nsxt_edgegateway](/providers/vmware/vcd/latest/docs/data-sources/nsxt_edgegateway) data source. +* `service_engine_group_id` - (Required) An ID of NSX-T Service Engine Group. Can be looked up using + [vcd_nsxt_alb_service_engine_group](/providers/vmware/vcd/latest/docs/data-sources/nsxt_alb_service_engine_group) data + source. +* `max_virtual_services` - (Optional) Maximum amount of Virtual Services to run on this Service Engine Group. **Only for + Shared Service Engine Groups**. +* `reserved_virtual_services` - (Optional) Number of reserved Virtual Services for this Edge Gateway. **Only for Shared + Service Engine Groups.** + +## Attribute reference + +* `deployed_virtual_services` - Number of deployed Virtual Services on this Service Engine Group. + +## Importing + +~> The current implementation of Terraform import can only import resources into the state. +It does not generate configuration. [More information.](https://www.terraform.io/docs/import/) + +An existing NSX-T Edge Gateway ALB Service Engine Group assignment configuration can be [imported][docs-import] into +this resource via supplying +path for it. An example is below: + +[docs-import]: https://www.terraform.io/docs/import/ + +``` +terraform import vcd_nsxt_alb_settings.imported my-org.my-vdc.my-nsxt-edge-gateway-name.service-engine-group-name +``` + +The above would import the NSX-T Edge Gateway ALB Service Engine Group assignment configuration for Service Engine Group +Name `service-engine-group-name` on Edge Gateway named `my-nsxt-edge-gateway-name` in Org `my-org` +and VDC `my-vdc`. \ No newline at end of file diff --git a/website/vcd.erb b/website/vcd.erb index 6ce960ec1..0247110bf 100644 --- a/website/vcd.erb +++ b/website/vcd.erb @@ -205,6 +205,9 @@ > vcd_nsxt_alb_settings + > + vcd_nsxt_alb_edgegateway_service_engine_group + > vcd_library_certificate @@ -384,6 +387,12 @@ > vcd_nsxt_alb_settings + > + vcd_nsxt_alb_edgegateway_service_engine_group + + > + vcd_library_certificate +