From 233908d7d2adbaa9eaa214649de49990d81f73a3 Mon Sep 17 00:00:00 2001 From: Anton Sidelnikov <53078276+anton-sidelnikov@users.noreply.github.com> Date: Mon, 7 Oct 2024 15:32:41 +0200 Subject: [PATCH] [EVPN] New `resource/opentelekomcloud_enterprise_vpn_customer_gateway_v5` (#2673) [EVPN] New `resource/opentelekomcloud_enterprise_vpn_customer_gateway_v5` Summary of the Pull Request PR Checklist Refers to: #2640 Tests added/passed. Documentation updated. Schema updated. Release notes added. Acceptance Steps Performed === RUN TestAccCustomerGateway_basic === PAUSE TestAccCustomerGateway_basic === CONT TestAccCustomerGateway_basic --- PASS: TestAccCustomerGateway_basic (48.87s) PASS Process finished with the exit code 0 Reviewed-by: Artem Lifshits Reviewed-by: Anton Sidelnikov --- docs/resources/vpn_customer_gateway_v5.md | 79 ++++++++ docs/resources/vpn_gateway_v5.md | 6 +- ...enterprise_vpn_customer_gateway_v5_test.go | 95 +++++++++ opentelekomcloud/provider.go | 1 + ...loud_enterprise_vpn_customer_gateway_v5.go | 187 ++++++++++++++++++ ...vpn-customer-gateway-5b64a180413e1aef.yaml | 4 + 6 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 docs/resources/vpn_customer_gateway_v5.md create mode 100644 opentelekomcloud/acceptance/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5_test.go create mode 100644 opentelekomcloud/services/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5.go create mode 100644 releasenotes/notes/evpn-customer-gateway-5b64a180413e1aef.yaml diff --git a/docs/resources/vpn_customer_gateway_v5.md b/docs/resources/vpn_customer_gateway_v5.md new file mode 100644 index 000000000..b599d9cb7 --- /dev/null +++ b/docs/resources/vpn_customer_gateway_v5.md @@ -0,0 +1,79 @@ +--- +subcategory: "Virtual Private Network (VPN)" +layout: "opentelekomcloud" +page_title: "OpenTelekomCloud: opentelekomcloud_enterprise_vpn_customer_gateway_v5" +sidebar_current: "docs-opentelekomcloud-resource-enterprise-vpn-customer-gateway-v5" +description: |- +Manages a Enterprise VPN Customer Gateway Service resource within OpenTelekomCloud. +--- + +Up-to-date reference of API arguments for EVPN you can get at +[documentation portal](https://docs.otc.t-systems.com/virtual-private-network/api-ref/api_reference_enterprise_edition_vpn/apis_of_enterprise_edition_vpn/customer_gateway/index.html) + +# opentelekomcloud_enterprise_vpn_customer_gateway_v5 + +Manages a VPN customer gateway resource within OpenTelekomCloud. + +## Example Usage + +### Manages a common VPN customer gateway + +```hcl +variable "name" {} +variable "id_value" {} + +resource "opentelekomcloud_enterprise_vpn_customer_gateway_v5" "test" { + name = var.name + id_value = var.id_value +} +``` + + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required, String) The customer gateway name. + The valid length is limited from `1` to `64`, only letters, digits, hyphens (-) and underscores (_) are allowed. + +* `id_value` - (Required, String, ForceNew) Specifies the identifier of a customer gateway. + When `id_type` is set to `ip`, the value is an IPv4 address in dotted decimal notation, for example, 192.168.45.7. + When `id_type` is set to `fqdn`, the value is a string of characters that can contain uppercase letters, lowercase letters, + digits, and special characters. Spaces and the following special characters are not supported: & < > [ ] \ ?. + + Changing this parameter will create a new resource. + +* `id_type` - (Optional, String, ForceNew) Specifies the identifier type of customer gateway. + The value can be `ip` or `fqdn`. The default value is `ip`. + +* `asn` - (Optional, Int, ForceNew) The BGP ASN number of the customer gateway. + The value ranges from `1` to `4,294,967,295`, the default value is `65,000`. + Set this parameter to `0` when `id_type` is set to `fqdn`. + + Changing this parameter will create a new resource. + +* `tags` - (Optional, Map) Specifies the tags of the customer gateway. + +## Attribute Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The resource ID. + +* `created_at` - The create time. + +* `updated_at` - The update time. + +* `route_mode` - Specifies the routing mode. + +* `ip` - Specifies the IP address of the customer gateway. + +* `region` - Specifies the region in which resource is created. + +## Import + +The gateway can be imported using the `id`, e.g. + +```bash +$ terraform import opentelekomcloud_enterprise_vpn_customer_gateway_v5.cgw +``` diff --git a/docs/resources/vpn_gateway_v5.md b/docs/resources/vpn_gateway_v5.md index 8de7b7680..1d50f666c 100644 --- a/docs/resources/vpn_gateway_v5.md +++ b/docs/resources/vpn_gateway_v5.md @@ -7,6 +7,10 @@ description: |- Manages a Enterprise VPN Gateway Service resource within OpenTelekomCloud. --- +Up-to-date reference of API arguments for EVPN you can get at +[documentation portal](https://docs.otc.t-systems.com/virtual-private-network/api-ref/api_reference_enterprise_edition_vpn/apis_of_enterprise_edition_vpn/vpn_gateway/index.html) + + # opentelekomcloud_enterprise_vpn_gateway_v5 Manages a VPN gateway resource within OpenTelekomCloud. @@ -218,7 +222,7 @@ In addition to all arguments above, the following attributes are exported: * `er_attachment_id` - The ER attachment ID. -* `region` - Specifies the region in which to create the resource. +* `region` - Specifies the region in which resource is created. * `eip1` - The master 1 IP in active-active VPN gateway or the master IP in active-standby VPN gateway. The [object](#GatewayGetResponseEip) structure is documented below. diff --git a/opentelekomcloud/acceptance/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5_test.go b/opentelekomcloud/acceptance/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5_test.go new file mode 100644 index 000000000..58a6b558a --- /dev/null +++ b/opentelekomcloud/acceptance/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5_test.go @@ -0,0 +1,95 @@ +package acceptance + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + cgw "github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/customer-gateway" + "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/common" + "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/acceptance/env" + "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/cfg" +) + +const resourceEvpnCustomerGatewayName = "opentelekomcloud_enterprise_vpn_customer_gateway_v5.cgw_1" + +func getCustomerGatewayResourceFunc(conf *cfg.Config, state *terraform.ResourceState) (interface{}, error) { + client, err := conf.EvpnV5Client(env.OS_REGION_NAME) + if err != nil { + return nil, fmt.Errorf("error creating OpenTelekomCloud EVPN v5 client: %s", err) + } + return cgw.Get(client, state.Primary.ID) +} + +func TestAccCustomerGateway_basic(t *testing.T) { + var gw cgw.CustomerGateway + name := fmt.Sprintf("evpn_acc_cgw_%s", acctest.RandString(5)) + updateName := fmt.Sprintf("evpn_acc_cgw_up_%s", acctest.RandString(5)) + + rc := common.InitResourceCheck( + resourceEvpnCustomerGatewayName, + &gw, + getCustomerGatewayResourceFunc, + ) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { common.TestAccPreCheck(t) }, + ProviderFactories: common.TestAccProviderFactories, + CheckDestroy: rc.CheckResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testCustomerGateway_basic(name), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "name", name), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "id_value", "10.1.2.10"), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "tags.key", "val"), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "tags.foo", "bar"), + ), + }, + { + Config: testCustomerGateway_update(updateName), + Check: resource.ComposeTestCheckFunc( + rc.CheckResourceExists(), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "name", updateName), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "id_value", "10.1.2.10"), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "tags.key", "val"), + resource.TestCheckResourceAttr(resourceEvpnCustomerGatewayName, "tags.foo", "bar-update"), + ), + }, + { + ResourceName: resourceEvpnCustomerGatewayName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCustomerGateway_basic(name string) string { + return fmt.Sprintf(` +resource "opentelekomcloud_enterprise_vpn_customer_gateway_v5" "cgw_1" { + name = "%s" + id_value = "10.1.2.10" + + tags = { + key = "val" + foo = "bar" + } +}`, name) +} + +func testCustomerGateway_update(name string) string { + return fmt.Sprintf(` +resource "opentelekomcloud_enterprise_vpn_customer_gateway_v5" "cgw_1" { + name = "%s" + id_value = "10.1.2.10" + + tags = { + key = "val" + foo = "bar-update" + } +}`, name) +} diff --git a/opentelekomcloud/provider.go b/opentelekomcloud/provider.go index 2f3b77276..256b3d379 100644 --- a/opentelekomcloud/provider.go +++ b/opentelekomcloud/provider.go @@ -562,6 +562,7 @@ func Provider() *schema.Provider { "opentelekomcloud_vpnaas_endpoint_group_v2": vpn.ResourceVpnEndpointGroupV2(), "opentelekomcloud_vpnaas_site_connection_v2": vpn.ResourceVpnSiteConnectionV2(), "opentelekomcloud_enterprise_vpn_gateway_v5": vpn.ResourceEnterpriseVpnGateway(), + "opentelekomcloud_enterprise_vpn_customer_gateway_v5": vpn.ResourceEnterpriseCustomerGateway(), "opentelekomcloud_waf_alarm_notification_v1": waf.ResourceWafAlarmNotificationV1(), "opentelekomcloud_waf_certificate_v1": waf.ResourceWafCertificateV1(), "opentelekomcloud_waf_domain_v1": waf.ResourceWafDomainV1(), diff --git a/opentelekomcloud/services/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5.go b/opentelekomcloud/services/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5.go new file mode 100644 index 000000000..f594fc93c --- /dev/null +++ b/opentelekomcloud/services/vpn/resource_opentelekomcloud_enterprise_vpn_customer_gateway_v5.go @@ -0,0 +1,187 @@ +package vpn + +import ( + "context" + + "github.com/hashicorp/go-multierror" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/pointerto" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/tags" + cgw "github.com/opentelekomcloud/gophertelekomcloud/openstack/evpn/v5/customer-gateway" + "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common" + "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/cfg" + "github.com/opentelekomcloud/terraform-provider-opentelekomcloud/opentelekomcloud/common/fmterr" +) + +func ResourceEnterpriseCustomerGateway() *schema.Resource { + return &schema.Resource{ + CreateContext: resourceEvpnCustomerGatewayCreate, + UpdateContext: resourceEvpnCustomerGatewayUpdate, + ReadContext: resourceEvpnCustomerGatewayRead, + DeleteContext: resourceEvpnCustomerGatewayDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + "asn": { + Type: schema.TypeInt, + Optional: true, + Default: 65000, + ForceNew: true, + }, + "id_value": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "id_type": { + Type: schema.TypeString, + Optional: true, + Default: "ip", + ForceNew: true, + }, + "tags": common.TagsSchema(), + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "updated_at": { + Type: schema.TypeString, + Computed: true, + }, + "region": { + Type: schema.TypeString, + Computed: true, + }, + "ip": { + Type: schema.TypeString, + Computed: true, + }, + "route_mode": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceEvpnCustomerGatewayCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + config := meta.(*cfg.Config) + client, err := common.ClientFromCtx(ctx, keyClientV5, func() (*golangsdk.ServiceClient, error) { + return config.EvpnV5Client(config.GetRegion(d)) + }) + if err != nil { + return fmterr.Errorf(errCreationV5Client, err) + } + + gatewayTags := d.Get("tags").(map[string]interface{}) + var tagSlice []tags.ResourceTag + for k, v := range gatewayTags { + tagSlice = append(tagSlice, tags.ResourceTag{Key: k, Value: v.(string)}) + } + createOpts := cgw.CreateOpts{ + Name: d.Get("name").(string), + BgpAsn: pointerto.Int(d.Get("asn").(int)), + Tags: tagSlice, + IdType: d.Get("id_type").(string), + IdValue: d.Get("id_value").(string), + } + + n, err := cgw.Create(client, createOpts) + if err != nil { + return fmterr.Errorf("error creating OpenTelekomCloud EVPN customer gateway: %w", err) + } + d.SetId(n.ID) + + clientCtx := common.CtxWithClient(ctx, client, keyClientV5) + return resourceEvpnCustomerGatewayRead(clientCtx, d, meta) +} + +func resourceEvpnCustomerGatewayRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + config := meta.(*cfg.Config) + client, err := common.ClientFromCtx(ctx, keyClientV5, func() (*golangsdk.ServiceClient, error) { + return config.EvpnV5Client(config.GetRegion(d)) + }) + if err != nil { + return fmterr.Errorf(errCreationV5Client, err) + } + + gw, err := cgw.Get(client, d.Id()) + if err != nil { + return diag.Errorf("error retrieving OpenTelekomCloud EVPN customer gateway (%s): %s", d.Id(), err) + } + + tagsMap := make(map[string]string) + for _, tag := range gw.Tags { + tagsMap[tag.Key] = tag.Value + } + + mErr := multierror.Append( + nil, + d.Set("region", config.GetRegion(d)), + d.Set("name", gw.Name), + d.Set("id_value", gw.IdValue), + d.Set("asn", gw.BgpAsn), + d.Set("id_type", gw.IdType), + d.Set("created_at", gw.CreatedAt), + d.Set("updated_at", gw.UpdatedAt), + d.Set("tags", tagsMap), + d.Set("ip", gw.Ip), + d.Set("route_mode", gw.RouteMode), + ) + + return diag.FromErr(mErr.ErrorOrNil()) +} + +func resourceEvpnCustomerGatewayUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + config := meta.(*cfg.Config) + client, err := common.ClientFromCtx(ctx, keyClientV5, func() (*golangsdk.ServiceClient, error) { + return config.EvpnV5Client(config.GetRegion(d)) + }) + if err != nil { + return fmterr.Errorf(errCreationV5Client, err) + } + + if d.HasChange("name") { + _, err := cgw.Update(client, cgw.UpdateOpts{ + GatewayID: d.Id(), + Name: d.Get("name").(string), + }) + if err != nil { + return diag.Errorf("error updating OpenTelekomCloud EVPN customer gateway: %s", err) + } + } + + if d.HasChange("tags") { + if err = updateTags(client, d, "customer-gateway", d.Id()); err != nil { + return diag.Errorf("error updating tags of OpenTelekomCloud EVPN customer gateway (%s): %s", d.Id(), err) + } + } + clientCtx := common.CtxWithClient(ctx, client, keyClientV5) + return resourceEvpnCustomerGatewayRead(clientCtx, d, meta) +} + +func resourceEvpnCustomerGatewayDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + config := meta.(*cfg.Config) + client, err := common.ClientFromCtx(ctx, keyClientV5, func() (*golangsdk.ServiceClient, error) { + return config.EvpnV5Client(config.GetRegion(d)) + }) + if err != nil { + return fmterr.Errorf(errCreationV5Client, err) + } + + err = cgw.Delete(client, d.Id()) + if err != nil { + return common.CheckDeletedDiag(d, err, "error deleting OpenTelekomCloud EVPN customer gateway") + } + + return nil +} diff --git a/releasenotes/notes/evpn-customer-gateway-5b64a180413e1aef.yaml b/releasenotes/notes/evpn-customer-gateway-5b64a180413e1aef.yaml new file mode 100644 index 000000000..bf64fef1c --- /dev/null +++ b/releasenotes/notes/evpn-customer-gateway-5b64a180413e1aef.yaml @@ -0,0 +1,4 @@ +--- +features: + | + **[EVPN]** Add new resource ``resource/opentelekomcloud_enterprise_vpn_customer_gateway_v5`` (`#2673 `_)