Skip to content

Commit

Permalink
Add huaweicloud_cdn_domain_v1 resource and docs (#223)
Browse files Browse the repository at this point in the history
* Add huaweicloud_cdn_domain_v1 resource

Signed-off-by: ShiChangkuo <[email protected]>

* Add testAcc for huaweicloud_cdn_domain_v1 resource

Signed-off-by: ShiChangkuo <[email protected]>

* Add website/docs for huaweicloud_cdn_domain_v1 resource

Signed-off-by: ShiChangkuo <[email protected]>
  • Loading branch information
ShiChangkuo authored and niuzhenguo committed Nov 4, 2019
1 parent ab4222c commit f40f1e4
Show file tree
Hide file tree
Showing 13 changed files with 779 additions and 5 deletions.
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/errwrap v1.0.0
github.com/hashicorp/go-cleanhttp v0.5.1
github.com/hashicorp/terraform-plugin-sdk v1.0.0
github.com/huaweicloud/golangsdk v0.0.0-20191015074635-101cf928fd59
github.com/huaweicloud/golangsdk v0.0.0-20191101095004-04427fad1e00
github.com/jen20/awspolicyequivalence v0.0.0-20170831201602-3d48364a137a
github.com/mitchellh/go-homedir v1.1.0
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKe
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huaweicloud/golangsdk v0.0.0-20191015074635-101cf928fd59 h1:niLc18KsKDSiCIEEJRtCwmjtGcgcjelHVysjyVSA7Fo=
github.com/huaweicloud/golangsdk v0.0.0-20191015074635-101cf928fd59/go.mod h1:WQBcHRNX9shz3928lWEvstQJtAtYI7ks6XlgtRT9Tcw=
github.com/huaweicloud/golangsdk v0.0.0-20191101095004-04427fad1e00 h1:Gw2+Mx0dVIgiCwZw1iSSIS9Za46VQBhD875dDtD62xg=
github.com/huaweicloud/golangsdk v0.0.0-20191101095004-04427fad1e00/go.mod h1:WQBcHRNX9shz3928lWEvstQJtAtYI7ks6XlgtRT9Tcw=
github.com/jen20/awspolicyequivalence v0.0.0-20170831201602-3d48364a137a h1:FyS/ubzBR5xJlnJGRTwe7GUHpJOR4ukYK3y+LFNffuA=
github.com/jen20/awspolicyequivalence v0.0.0-20170831201602-3d48364a137a/go.mod h1:uoIMjNxUfXi48Ci40IXkPRbghZ1vbti6v9LCbNqRgHY=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
Expand Down
7 changes: 7 additions & 0 deletions huaweicloud/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,13 @@ func (c *Config) RdsV1Client(region string) (*golangsdk.ServiceClient, error) {
})
}

func (c *Config) CdnV1Client(region string) (*golangsdk.ServiceClient, error) {
return huaweisdk.NewCDNV1(c.HwClient, golangsdk.EndpointOpts{
Region: c.determineRegion(region),
Availability: c.getHwEndpointType(),
})
}

func (c *Config) sdkClient(region, serviceType string, level string) (*golangsdk.ServiceClient, error) {
client := c.HwClient
if level == serviceDomainLevel {
Expand Down
1 change: 1 addition & 0 deletions huaweicloud/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ func Provider() terraform.ResourceProvider {
"huaweicloud_cs_route_v1": resourceCsRouteV1(),
"huaweicloud_networking_vip_v2": resourceNetworkingVIPV2(),
"huaweicloud_networking_vip_associate_v2": resourceNetworkingVIPAssociateV2(),
"huaweicloud_cdn_domain_v1": resourceCdnDomainV1(),
},
}

Expand Down
9 changes: 9 additions & 0 deletions huaweicloud/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var (
OS_DMS_ENVIRONMENT = os.Getenv("OS_DMS_ENVIRONMENT")
OS_NAT_ENVIRONMENT = os.Getenv("OS_NAT_ENVIRONMENT")
OS_KMS_ENVIRONMENT = os.Getenv("OS_KMS_ENVIRONMENT")
OS_CDN_DOMAIN_NAME = os.Getenv("OS_CDN_DOMAIN_NAME")
)

var testAccProviders map[string]terraform.ResourceProvider
Expand Down Expand Up @@ -198,6 +199,14 @@ func testAccPreCheckKms(t *testing.T) {
}
}

func testAccPreCheckCDN(t *testing.T) {
testAccPreCheckRequiredEnvVars(t)

if OS_CDN_DOMAIN_NAME == "" {
t.Skip("This environment does not support CDN tests")
}
}

func TestProvider(t *testing.T) {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
Expand Down
274 changes: 274 additions & 0 deletions huaweicloud/resource_huaweicloud_cdn_domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
package huaweicloud

import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/huaweicloud/golangsdk"
"github.com/huaweicloud/golangsdk/openstack/cdn/v1/domains"
)

func resourceCdnDomainV1() *schema.Resource {
return &schema.Resource{
Create: resourceCdnDomainV1Create,
Read: resourceCdnDomainV1Read,
Delete: resourceCdnDomainV1Delete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(20 * time.Minute),
Delete: schema.DefaultTimeout(20 * time.Minute),
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
"web", "download", "video",
}, true),
},
"sources": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"domain": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"domain_type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{
"ipaddr", "domain", "obs_bucket",
}, true),
},
"active": {
Type: schema.TypeInt,
Computed: true,
ForceNew: false,
},
},
},
},
"enterprise_project_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"cname": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"domain_status": {
Type: schema.TypeString,
Optional: true,
ForceNew: false,
Computed: true,
},
"service_area": {
Type: schema.TypeString,
Optional: true,
ForceNew: false,
Computed: true,
},
},
}
}

type WaitDomainStatus struct {
ID string
Penging []string
Target []string
Opts *domains.ExtensionOpts
}

func getDomainSources(d *schema.ResourceData) []domains.SourcesOpts {
var sourceRequests []domains.SourcesOpts

sources := d.Get("sources").([]interface{})
for i := range sources {
source := sources[i].(map[string]interface{})
sourceRequest := domains.SourcesOpts{
IporDomain: source["domain"].(string),
OriginType: source["domain_type"].(string),
ActiveStandby: 1,
}
sourceRequests = append(sourceRequests, sourceRequest)
}
return sourceRequests
}

func resourceCdnDomainV1Create(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
cdnClient, err := config.CdnV1Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CDN v1 client: %s", err)
}

createOpts := &domains.CreateOpts{
DomainName: d.Get("name").(string),
BusinessType: d.Get("type").(string),
Sources: getDomainSources(d),
EnterpriseProjectId: d.Get("enterprise_project_id").(string),
}

log.Printf("[DEBUG] Create Options: %#v", createOpts)
v, err := domains.Create(cdnClient, createOpts).Extract()
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CDN Domain: %s", err)
}

// Wait for CDN domain to become active again before continuing
log.Printf("[INFO] Waiting for CDN domain %s to become online.", v.ID)
wait := &WaitDomainStatus{
ID: v.ID,
Penging: []string{"configuring"},
Target: []string{"online"},
Opts: getResourceExtensionOpts(d),
}
timeout := d.Timeout(schema.TimeoutCreate)
err = waitforCDNV1DomainStatus(cdnClient, wait, timeout)
if err != nil {
return fmt.Errorf("Error waiting for CDN domain %s to become online: %s", v.ID, err)
}

// Store the ID now
d.SetId(v.ID)

return resourceCdnDomainV1Read(d, meta)
}

func waitforCDNV1DomainStatus(c *golangsdk.ServiceClient, waitstatus *WaitDomainStatus, timeout time.Duration) error {
stateConf := &resource.StateChangeConf{
Pending: waitstatus.Penging,
Target: waitstatus.Target,
Refresh: resourceCDNV1DomainRefreshFunc(c, waitstatus.ID, waitstatus.Opts),
Timeout: timeout,
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
}

_, err := stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for CDN domain %s to become %s: %s",
waitstatus.ID, waitstatus.Target, err)
}
return nil
}

func resourceCDNV1DomainRefreshFunc(c *golangsdk.ServiceClient, id string, opts *domains.ExtensionOpts) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
domain, err := domains.Get(c, id, opts).Extract()
if err != nil {
return nil, "", err
}

// return DomainStatus attribute of CDN domain resource
return domain, domain.DomainStatus, nil
}
}

func resourceCdnDomainV1Read(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
cdnClient, err := config.CdnV1Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CDN v1 client: %s", err)
}

opts := getResourceExtensionOpts(d)
v, err := domains.Get(cdnClient, d.Id(), opts).Extract()
if err != nil {
return fmt.Errorf("Error reading CDN Domain: %s", err)
}

log.Printf("[DEBUG] Retrieved CDN domain %s: %+v", d.Id(), v)

d.Set("name", v.DomainName)
d.Set("type", v.BusinessType)
d.Set("cname", v.CName)
d.Set("domain_status", v.DomainStatus)
d.Set("service_area", v.ServiceArea)

// set sources
sources := make([]map[string]interface{}, len(v.Sources))
for i, source := range v.Sources {
sources[i] = make(map[string]interface{})
sources[i]["domain"] = source.IporDomain
sources[i]["domain_type"] = source.OriginType
sources[i]["active"] = source.ActiveStandby
}
d.Set("sources", sources)

return nil
}

func resourceCdnDomainV1Delete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
cdnClient, err := config.CdnV1Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating HuaweiCloud CDN v1 client: %s", err)
}

id := d.Id()
opts := getResourceExtensionOpts(d)
timeout := d.Timeout(schema.TimeoutCreate)

if d.Get("domain_status").(string) == "online" {
// make sure the status has changed to offline
log.Printf("[INFO] Disable CDN domain %s.", id)
if err = domains.Disable(cdnClient, id, opts).Err; err != nil {
return fmt.Errorf("Error disable HuaweiCloud CDN Domain %s: %s", id, err)
}

log.Printf("[INFO] Waiting for disabling CDN domain %s.", id)
wait := &WaitDomainStatus{
ID: id,
Penging: []string{"configuring", "online"},
Target: []string{"offline"},
Opts: opts,
}

err = waitforCDNV1DomainStatus(cdnClient, wait, timeout)
if err != nil {
return fmt.Errorf("Error waiting for CDN domain %s to become offline: %s", id, err)
}
}

log.Printf("[INFO] Waiting for deleting CDN domain %s.", id)
_, err = domains.Delete(cdnClient, id, opts).Extract()
if err != nil {
return fmt.Errorf("Error deleting CDN Domain %s: %s", id, err)
}

d.SetId("")
return nil
}

func getResourceExtensionOpts(d *schema.ResourceData) *domains.ExtensionOpts {
if hasFilledOpt(d, "enterprise_project_id") {
return &domains.ExtensionOpts{
EnterpriseProjectId: d.Get("enterprise_project_id").(string),
}
}

return nil
}
Loading

0 comments on commit f40f1e4

Please sign in to comment.