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 huaweicloud vpcep endpoint resource and docs #772

Merged
merged 1 commit into from
Dec 25, 2020
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
115 changes: 115 additions & 0 deletions docs/resources/vpcep_endpoint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
---
subcategory: "VPC Endpoint (VPCEP)"
---

# huaweicloud\_vpcep\_endpoint

Provides a resource to manage a VPC endpoint resource.

## Example Usage

### Access to the public service

```hcl
variable "vpc_id" {}
variable "network_id" {}

data "huaweicloud_vpcep_public_services" "cloud_service" {
service_name = "dis"
}

resource "huaweicloud_vpcep_endpoint" "myendpoint" {
service_id = data.huaweicloud_vpcep_public_services.cloud_service.services[0].id
vpc_id = var.vpc_id
network_id = var.network_id
enable_dns = true
enable_whitelist = true
whitelist = ["192.168.0.0/24"]
}
```

### Access to the private service

```hcl
variable "service_vpc_id" {}
variable "vm_port" {}
variable "vpc_id" {}
variable "network_id" {}

resource "huaweicloud_vpcep_service" "demo" {
name = "demo-service"
server_type = "VM"
vpc_id = var.service_vpc_id
port_id = var.vm_port

port_mapping {
service_port = 8080
terminal_port = 80
}
}

resource "huaweicloud_vpcep_endpoint" "demo" {
service_id = huaweicloud_vpcep_service.demo.id
vpc_id = var.vpc_id
network_id = var.network_id
enable_dns = true
}
```

## Argument Reference

The following arguments are supported:

* `region` - (Optional, String, ForceNew) The region in which to create the VPC endpoint.
If omitted, the provider-level region will be used. Changing this creates a new VPC endpoint.

* `service_id` (Required, String, ForceNew) - Specifies the ID of the VPC endpoint service.
Changing this creates a new VPC endpoint.

* `vpc_id` (Required, String, ForceNew) - Specifies the ID of the VPC where the VPC endpoint is to be created.
Changing this creates a new VPC endpoint.

* `network_id` (Required, String, ForceNew) - Specifies the network ID of the subnet in the VPC specified by `vpc_id`.
Changing this creates a new VPC endpoint.

* `ip_address` (Optional, String, ForceNew) - Specifies the IP address for accessing the associated VPC endpoint service.
Only IPv4 addresses are supported. Changing this creates a new VPC endpoint.

* `enable_dns` (Optional, Bool, ForceNew) - Specifies whether to create a private domain name. The default value is true.
Changing this creates a new VPC endpoint.

* `enable_whitelist` (Optional, Bool, ForceNew) - Specifies whether to enable access control. The default value is false.
Changing this creates a new VPC endpoint.

* `whitelist` (Optional, List, ForceNew) - Specifies the list of IP address or CIDR block which can be accessed to the VPC endpoint.
Changing this creates a new VPC endpoint.

* `tags` - (Optional, Map) The key/value pairs to associate with the VPC endpoint.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

* `id` - The unique ID of the VPC endpoint.

* `status` - The status of the VPC endpoint. The value can be **accepted**, **pendingAcceptance** or **rejected**.

* `service_name` - The name of the VPC endpoint service.

* `service_type` - The type of the VPC endpoint service.

* `domain_name` - The domain name for accessing the associated VPC endpoint service. This parameter is only
available when enable_dns is set to true.

## Timeouts
This resource provides the following timeouts configuration options:
- `create` - Default is 10 minute.
- `delete` - Default is 10 minute.

## Import

VPC endpoint can be imported using the `id`, e.g.

```
$ terraform import huaweicloud_vpcep_endpoint.test 828907cc-40c9-42fe-8206-ecc1bdd30060
```
1 change: 1 addition & 0 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ func Provider() terraform.ResourceProvider {
"huaweicloud_vpc_peering_connection_accepter": resourceVpcPeeringConnectionAccepterV2(),
"huaweicloud_vpc_route": ResourceVPCRouteV2(),
"huaweicloud_vpc_subnet": ResourceVpcSubnetV1(),
"huaweicloud_vpcep_endpoint": ResourceVPCEndpoint(),
"huaweicloud_vpcep_service": ResourceVPCEndpointService(),
"huaweicloud_vpnaas_endpoint_group": resourceVpnEndpointGroupV2(),
"huaweicloud_vpnaas_ike_policy": resourceVpnIKEPolicyV2(),
Expand Down
262 changes: 262 additions & 0 deletions huaweicloud/resource_huaweicloud_vpcep_endpoint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
package huaweicloud

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/huaweicloud/golangsdk"
"github.com/huaweicloud/golangsdk/openstack/vpcep/v1/endpoints"
)

func ResourceVPCEndpoint() *schema.Resource {
return &schema.Resource{
Create: resourceVPCEndpointCreate,
Read: resourceVPCEndpointRead,
Update: resourceVPCEndpointUpdate,
Delete: resourceVPCEndpointDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(10 * time.Minute),
Delete: schema.DefaultTimeout(10 * time.Minute),
},

Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"service_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vpc_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"network_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"ip_address": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"enable_dns": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: true,
},
"enable_whitelist": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},
"whitelist": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"service_name": {
Type: schema.TypeString,
Computed: true,
},
"service_type": {
Type: schema.TypeString,
Computed: true,
},
"domain_name": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchema(),
},
}
}

func resourceVPCEndpointCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
vpcepClient, err := config.VPCEPClient(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating Huaweicloud VPC endpoint client: %s", err)
}

enableDNS := d.Get("enable_dns").(bool)
enableACL := d.Get("enable_whitelist").(bool)
createOpts := endpoints.CreateOpts{
ServiceID: d.Get("service_id").(string),
VpcID: d.Get("vpc_id").(string),
SubnetID: d.Get("network_id").(string),
PortIP: d.Get("ip_address").(string),
EnableDNS: &enableDNS,
EnableWhitelist: &enableACL,
}

raw := d.Get("whitelist").(*schema.Set).List()
if enableACL && len(raw) > 0 {
whitelists := make([]string, len(raw))
for i, v := range raw {
whitelists[i] = v.(string)
}
createOpts.Whitelist = whitelists
}

//set tags
tagRaw := d.Get("tags").(map[string]interface{})
if len(tagRaw) > 0 {
taglist := expandResourceTags(tagRaw)
createOpts.Tags = taglist
}

log.Printf("[DEBUG] Create Options: %#v", createOpts)
ep, err := endpoints.Create(vpcepClient, createOpts).Extract()
if err != nil {
return fmt.Errorf("Error creating Huaweicloud VPC endpoint: %s", err)
}

d.SetId(ep.ID)
log.Printf("[INFO] Waiting for Huaweicloud VPC endpoint(%s) to become accepted", ep.ID)
stateConf := &resource.StateChangeConf{
Pending: []string{"creating"},
Target: []string{"accepted", "pendingAcceptance"},
Refresh: waitForVPCEndpointStatus(vpcepClient, ep.ID),
Timeout: d.Timeout(schema.TimeoutCreate),
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
}

_, stateErr := stateConf.WaitForState()
if stateErr != nil {
return fmt.Errorf(
"Error waiting for VPC endpoint(%s) to become accepted: %s",
ep.ID, stateErr)
}

return resourceVPCEndpointRead(d, meta)
}

func resourceVPCEndpointRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
vpcepClient, err := config.VPCEPClient(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating Huaweicloud VPC endpoint client: %s", err)
}

ep, err := endpoints.Get(vpcepClient, d.Id()).Extract()
if err != nil {
if _, ok := err.(golangsdk.ErrDefault404); ok {
d.SetId("")
return nil
}
return fmt.Errorf("Error retrieving Huaweicloud VPC endpoint: %s", err)
}

log.Printf("[DEBUG] retrieving Huaweicloud VPC endpoint: %#v", ep)
d.Set("region", GetRegion(d, config))
d.Set("status", ep.Status)
d.Set("service_id", ep.ServiceID)
d.Set("service_name", ep.ServiceName)
d.Set("service_type", ep.ServiceType)
d.Set("vpc_id", ep.VpcID)
d.Set("network_id", ep.SubnetID)
d.Set("ip_address", ep.IPAddr)
d.Set("enable_dns", ep.EnableDNS)
d.Set("enable_whitelist", ep.EnableWhitelist)
d.Set("whitelist", ep.Whitelist)

if len(ep.DNSNames) > 0 {
d.Set("domain_name", ep.DNSNames[0])
} else {
d.Set("domain_name", nil)
}

// fetch tags from endpoints.Endpoint
tagmap := make(map[string]string)
for _, val := range ep.Tags {
tagmap[val.Key] = val.Value
}
d.Set("tags", tagmap)

return nil
}

func resourceVPCEndpointUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
vpcepClient, err := config.VPCEPClient(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating Huaweicloud VPC endpoint client: %s", err)
}

//update tags
if d.HasChange("tags") {
tagErr := UpdateResourceTags(vpcepClient, d, tagVPCEP, d.Id())
if tagErr != nil {
return fmt.Errorf("Error updating tags of VPC endpoint service %s: %s", d.Id(), tagErr)
}
}
return resourceVPCEndpointRead(d, meta)
}

func resourceVPCEndpointDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
vpcepClient, err := config.VPCEPClient(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating Huaweicloud VPC endpoint client: %s", err)
}

err = endpoints.Delete(vpcepClient, d.Id()).ExtractErr()
if err != nil {
return fmt.Errorf("Error deleting Huaweicloud VPC endpoint %s: %s", d.Id(), err)
}

stateConf := &resource.StateChangeConf{
Pending: []string{"deleting"},
Target: []string{"deleted"},
Refresh: waitForVPCEndpointStatus(vpcepClient, d.Id()),
Timeout: d.Timeout(schema.TimeoutDelete),
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
}

_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error deleting Huaweicloud VPC endpoint %s: %s", d.Id(), err)
}

d.SetId("")
return nil
}

func waitForVPCEndpointStatus(vpcepClient *golangsdk.ServiceClient, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
ep, err := endpoints.Get(vpcepClient, id).Extract()
if err != nil {
if _, ok := err.(golangsdk.ErrDefault404); ok {
log.Printf("[INFO] Successfully deleted Huaweicloud VPC endpoint %s", id)
return ep, "deleted", nil
}
return ep, "error", err
}

return ep, ep.Status, nil
}
}
Loading