alicloud/resource_alicloud_cdn_domain.go (915 lines of code) (raw):
package alicloud
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
"github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity"
"github.com/denverdino/aliyungo/cdn"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func resourceAlicloudCdnDomain() *schema.Resource {
return &schema.Resource{
Create: resourceAlicloudCdnDomainCreate,
Read: resourceAlicloudCdnDomainRead,
Update: resourceAlicloudCdnDomainUpdate,
Delete: resourceAlicloudCdnDomainDelete,
Schema: map[string]*schema.Schema{
"domain_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringLenBetween(5, 67),
},
"cdn_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{cdn.Web, cdn.Download, cdn.Video, cdn.LiveStream}, false),
},
"source_type": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{cdn.Ipaddr, cdn.Domain, cdn.OSS}, false),
Deprecated: "Use `alicloud_cdn_domain_new` configuration `sources` block `type` argument instead.",
},
"source_port": {
Type: schema.TypeInt,
Optional: true,
Default: 80,
// must be one 80 or 443.
ValidateFunc: validation.IntInSlice([]int{80, 443}),
Deprecated: "Use `alicloud_cdn_domain_new` configuration `sources` block `port` argument instead.",
},
"sources": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
MaxItems: 20,
Deprecated: "Use `alicloud_cdn_domain_new` configuration `sources` argument instead.",
},
"scope": {
Type: schema.TypeString,
Optional: true,
Computed: true,
// Domestic, Overseas, Global
ValidateFunc: validation.StringInSlice([]string{cdn.Domestic, cdn.Overseas, cdn.Global}, false),
},
// configs
"optimize_enable": {
Type: schema.TypeString,
Optional: true,
// must be 'on' or 'off'
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"page_compress_enable": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"range_enable": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"video_seek_enable": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"block_ips": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"parameter_filter_config": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"enable": {
Type: schema.TypeString,
Optional: true,
Default: "off",
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
},
"hash_key_args": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.StringDoesNotContainAny(",."),
},
MaxItems: 10,
},
},
},
MaxItems: 1,
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"page_404_config": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"page_type": {
Type: schema.TypeString,
Optional: true,
Default: "default",
ValidateFunc: validation.StringInSlice([]string{"default", "charity", "other"}, false),
},
"custom_page_url": {
Type: schema.TypeString,
Optional: true,
},
"error_code": {
Type: schema.TypeString,
Computed: true,
},
},
},
MaxItems: 1,
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"refer_config": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"refer_type": {
Type: schema.TypeString,
Optional: true,
Default: "block",
ValidateFunc: validation.StringInSlice([]string{"block", "allow"}, false),
},
"refer_list": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"allow_empty": {
Type: schema.TypeString,
Optional: true,
Default: "on",
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
},
},
},
MaxItems: 1,
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"certificate_config": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"server_certificate": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
},
"server_certificate_status": {
Type: schema.TypeString,
Default: "on",
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"on", "off"}, false),
},
"private_key": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
},
},
},
MaxItems: 1,
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"auth_config": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"auth_type": {
Type: schema.TypeString,
Optional: true,
Default: "no_auth",
// must be one of ['no_auth', 'type_a', 'type_b', 'type_c']"
ValidateFunc: validation.StringInSlice([]string{"no_auth", "type_a", "type_b", "type_c"}, false),
},
"master_key": {
Type: schema.TypeString,
Optional: true,
Computed: true,
// can only consists of alphanumeric characters and can not be longer than 32 or less than 6 characters.
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9]{6,32}$`), "can only consists of alphanumeric characters and can not be longer than 32 or less than 6 characters."),
},
"slave_key": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9]{6,32}$`), "can only consists of alphanumeric characters and can not be longer than 32 or less than 6 characters."),
},
"timeout": {
Type: schema.TypeInt,
Optional: true,
Default: 1800,
},
},
},
MaxItems: 1,
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"http_header_config": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"header_key": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{cdn.ContentType, cdn.CacheControl, cdn.ContentDisposition, cdn.ContentLanguage, cdn.Expires, cdn.AccessControlAllowMethods, cdn.AccessControlAllowOrigin, cdn.AccessControlMaxAge}, false),
},
"header_value": {
Type: schema.TypeString,
Required: true,
},
"header_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
MaxItems: 10,
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
"cache_config": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cache_content": {
Type: schema.TypeString,
Required: true,
},
"ttl": {
Type: schema.TypeInt,
Required: true,
},
"cache_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"suffix", "path"}, false),
},
"weight": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
ValidateFunc: validation.IntBetween(1, 99),
},
"cache_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
Deprecated: "Use `alicloud_cdn_domain_config` configuration `function_name` and `function_args` arguments instead.",
},
},
}
}
func resourceAlicloudCdnDomainCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
args := cdn.AddDomainRequest{
DomainName: d.Get("domain_name").(string),
CdnType: d.Get("cdn_type").(string),
SourcePort: d.Get("source_port").(int),
}
if v, ok := d.GetOk("scope"); ok {
args.Scope = v.(string)
}
if args.CdnType != cdn.LiveStream {
if v, ok := d.GetOk("sources"); ok && v.(*schema.Set).Len() > 0 {
sources := expandStringList(v.(*schema.Set).List())
args.Sources = strings.Join(sources, ",")
} else {
return fmt.Errorf("Sources is required when 'cdn_type' is not 'liveStream'.")
}
if v, ok := d.GetOk("source_type"); ok && v.(string) != "" {
args.SourceType = v.(string)
} else {
return fmt.Errorf("SourceType is required when 'cdn_type' is not 'liveStream'.")
}
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.AddCdnDomain(args)
})
if err != nil {
return fmt.Errorf("AddCdnDomain got an error: %#v", err)
}
d.SetId(args.DomainName)
err = WaitForDomainStatus(d.Id(), Configuring, 60, meta)
if err != nil {
return fmt.Errorf("Timeout when Cdn Domain Available. Error: %#v", err)
}
return resourceAlicloudCdnDomainUpdate(d, meta)
}
func resourceAlicloudCdnDomainUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
d.Partial(true)
args := cdn.ModifyDomainRequest{
DomainName: d.Id(),
SourceType: d.Get("source_type").(string),
}
if !d.IsNewResource() {
attributeUpdate := false
if d.HasChange("source_type") {
d.SetPartial("source_type")
attributeUpdate = true
}
if d.HasChange("sources") {
d.SetPartial("sources")
sources := expandStringList(d.Get("sources").(*schema.Set).List())
args.Sources = strings.Join(sources, ",")
attributeUpdate = true
}
if d.HasChange("source_port") {
d.SetPartial("source_port")
args.SourcePort = d.Get("source_port").(int)
attributeUpdate = true
}
if attributeUpdate {
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.ModifyCdnDomain(args)
})
if err != nil {
return fmt.Errorf("ModifyCdnDomain got an error: %#v", err)
}
}
}
// set optimize_enable 、range_enable、page_compress_enable and video_seek_enable
if err := enableConfigUpdate(client, d); err != nil {
return err
}
if d.HasChange("block_ips") {
d.SetPartial("block_ips")
blockIps := expandStringList(d.Get("block_ips").(*schema.Set).List())
args := cdn.IpBlackRequest{DomainName: d.Id(), BlockIps: strings.Join(blockIps, ",")}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetIpBlackListConfig(args)
})
if err != nil {
return err
}
}
if d.HasChange("parameter_filter_config") {
if err := queryStringConfigUpdate(client, d); err != nil {
return err
}
}
if d.HasChange("page_404_config") {
if err := page404ConfigUpdate(client, d); err != nil {
return err
}
}
if d.HasChange("refer_config") {
if err := referConfigUpdate(client, d); err != nil {
return err
}
}
if d.HasChange("auth_config") {
if err := authConfigUpdate(client, d); err != nil {
return err
}
}
if d.HasChange("http_header_config") {
if err := httpHeaderConfigUpdate(client, d); err != nil {
return err
}
}
if d.HasChange("cache_config") {
if err := cacheConfigUpdate(client, d); err != nil {
return err
}
}
if d.HasChange("certificate_config") {
if d.IsNewResource() {
err := WaitForDomainStatus(d.Id(), Online, 360, meta)
if err != nil {
return fmt.Errorf("Timeout when Cdn Domain Online. Error: %#v", err)
}
}
if err := certificateConfigUpdate(client, d); err != nil {
return err
}
}
d.Partial(false)
return resourceAlicloudCdnDomainRead(d, meta)
}
func resourceAlicloudCdnDomainRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
domain, err := DescribeDomainDetail(d.Id(), meta)
if err != nil {
return fmt.Errorf("DescribeDomainDetail got an error: %#v", err)
}
d.Set("domain_name", domain.DomainName)
d.Set("sources", domain.Sources.Source)
d.Set("cdn_type", domain.CdnType)
d.Set("source_type", domain.SourceType)
d.Set("scope", domain.Scope)
// get domain configs
describeConfigArgs := cdn.DomainConfigRequest{
DomainName: d.Id(),
}
raw, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.DescribeDomainConfigs(describeConfigArgs)
})
if err != nil {
return fmt.Errorf("DescribeDomainConfigs got an error: %#v", err)
}
resp, _ := raw.(cdn.DomainConfigResponse)
configs := resp.DomainConfigs
queryStringConfig := configs.IgnoreQueryStringConfig
if _, ok := d.GetOk("parameter_filter_config"); ok {
config := make([]map[string]interface{}, 1)
config[0] = map[string]interface{}{
"enable": queryStringConfig.Enable,
"hash_key_args": strings.Split(queryStringConfig.HashKeyArgs, ","),
}
d.Set("parameter_filter_config", config)
}
if _, ok := d.GetOk("certificate_config"); ok {
ov := d.Get("certificate_config")
oldConfig := ov.([]interface{})
config := make([]map[string]interface{}, 1)
serverCertificateStatus := domain.ServerCertificateStatus
if serverCertificateStatus == "" {
serverCertificateStatus = "off"
}
config[0] = map[string]interface{}{
"server_certificate": domain.ServerCertificate,
"server_certificate_status": serverCertificateStatus,
}
if oldConfig != nil && len(oldConfig) > 0 {
val := oldConfig[0].(map[string]interface{})
config[0]["private_key"] = val["private_key"]
}
d.Set("certificate_config", config)
}
errorPageConfig := configs.ErrorPageConfig
if _, ok := d.GetOk("page_404_config"); ok {
config := make([]map[string]interface{}, 1)
config[0] = map[string]interface{}{
"page_type": errorPageConfig.PageType,
"error_code": errorPageConfig.ErrorCode,
"custom_page_url": errorPageConfig.CustomPageUrl,
}
if errorPageConfig.PageType == "" {
config[0]["page_type"] = "default"
}
d.Set("page_404_config", config)
}
referConfig := configs.RefererConfig
if _, ok := d.GetOk("refer_config"); ok {
config := make([]map[string]interface{}, 1)
config[0] = map[string]interface{}{
"refer_type": referConfig.ReferType,
"refer_list": strings.Split(referConfig.ReferList, ","),
"allow_empty": referConfig.AllowEmpty,
}
d.Set("refer_config", config)
}
authConfig := configs.ReqAuthConfig
if _, ok := d.GetOk("auth_config"); ok {
config := make([]map[string]interface{}, 1)
timeout, _ := strconv.Atoi(authConfig.TimeOut)
config[0] = map[string]interface{}{
"auth_type": authConfig.AuthType,
"master_key": authConfig.Key1,
"slave_key": authConfig.Key2,
"timeout": timeout,
}
d.Set("auth_config", config)
}
headerConfigs := configs.HttpHeaderConfigs.HttpHeaderConfig
httpHeaderConfigs := make([]map[string]interface{}, 0, len(headerConfigs))
for _, v := range headerConfigs {
val := make(map[string]interface{})
val["header_key"] = v.HeaderKey
val["header_value"] = v.HeaderValue
val["header_id"] = v.ConfigId
httpHeaderConfigs = append(httpHeaderConfigs, val)
}
d.Set("http_header_config", httpHeaderConfigs)
cacheConfigs := configs.CacheExpiredConfigs.CacheExpiredConfig
cacheExpiredConfigs := make([]map[string]interface{}, 0, len(cacheConfigs))
for _, v := range cacheConfigs {
val := make(map[string]interface{})
ttl, _ := strconv.Atoi(v.TTL)
weight, _ := strconv.Atoi(v.Weight)
val["cache_type"] = v.CacheType
val["cache_content"] = v.CacheContent
val["cache_id"] = v.ConfigId
val["weight"] = weight
val["ttl"] = ttl
cacheExpiredConfigs = append(cacheExpiredConfigs, val)
}
d.Set("cache_config", cacheExpiredConfigs)
d.Set("optimize_enable", configs.OptimizeConfig.Enable)
d.Set("page_compress_enable", configs.PageCompressConfig.Enable)
d.Set("range_enable", configs.RangeConfig.Enable)
d.Set("video_seek_enable", configs.VideoSeekConfig.Enable)
blocks := make([]string, 0)
if len(configs.CcConfig.BlockIps) > 0 {
blocks = strings.Split(configs.CcConfig.BlockIps, ",")
}
d.Set("block_ips", blocks)
return nil
}
func resourceAlicloudCdnDomainDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*connectivity.AliyunClient)
args := cdn.DescribeDomainRequest{
DomainName: d.Id(),
}
return resource.Retry(5*time.Minute, func() *resource.RetryError {
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.DeleteCdnDomain(args)
})
if err != nil {
if IsExpectedErrors(err, []string{"ServiceBusy"}) {
return resource.RetryableError(fmt.Errorf("The specified Domain is configuring, please retry later."))
}
return resource.NonRetryableError(fmt.Errorf("Error deleting cdn domain %s: %#v.", d.Id(), err))
}
return nil
})
}
func enableConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
type configFunc func(req cdn.ConfigRequest) (cdn.CdnCommonResponse, error)
raw, _ := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return map[string]configFunc{
"optimize_enable": cdnClient.SetOptimizeConfig,
"range_enable": cdnClient.SetRangeConfig,
"page_compress_enable": cdnClient.SetPageCompressConfig,
"video_seek_enable": cdnClient.SetVideoSeekConfig,
}, nil
})
relation, _ := raw.(map[string]configFunc)
for key, fn := range relation {
if d.HasChange(key) {
d.SetPartial(key)
args := cdn.ConfigRequest{
DomainName: d.Id(),
Enable: d.Get(key).(string),
}
if _, err := fn(args); err != nil {
return err
}
}
}
return nil
}
func queryStringConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
valSet := d.Get("parameter_filter_config").(*schema.Set)
args := cdn.QueryStringConfigRequest{DomainName: d.Id()}
if valSet == nil || valSet.Len() == 0 {
args.Enable = "off"
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetIgnoreQueryStringConfig(args)
})
if err != nil {
return err
}
return nil
}
val := valSet.List()[0].(map[string]interface{})
d.SetPartial("parameter_filter_config")
args.Enable = val["enable"].(string)
if v, ok := val["hash_key_args"]; ok && len(v.([]interface{})) > 0 {
hashKeyArgs := expandStringList(v.([]interface{}))
args.HashKeyArgs = strings.Join(hashKeyArgs, ",")
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetIgnoreQueryStringConfig(args)
})
if err != nil {
return err
}
return nil
}
func page404ConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
valSet := d.Get("page_404_config").(*schema.Set)
args := cdn.ErrorPageConfigRequest{DomainName: d.Id()}
if valSet == nil || valSet.Len() == 0 {
args.PageType = "default"
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetErrorPageConfig(args)
})
if err != nil {
return err
}
return nil
}
val := valSet.List()[0].(map[string]interface{})
d.SetPartial("page_404_config")
args.PageType = val["page_type"].(string)
customPageUrl, ok := val["custom_page_url"]
if ok {
args.CustomPageUrl = customPageUrl.(string)
}
if args.PageType == "charity" && (ok && customPageUrl.(string) != CharityPageUrl || !ok) {
return fmt.Errorf("If 'page_type' value is 'charity', you must set 'custom_page_url' with '%s'.", CharityPageUrl)
}
if args.PageType == "default" && ok && customPageUrl.(string) != "" {
return fmt.Errorf("If 'page_type' value is 'default', you can not set 'custom_page_url'.")
}
if args.PageType == "other" && (!ok || customPageUrl.(string) == "") {
return fmt.Errorf("If 'page_type' value is 'other', you must set the value of 'custom_page_url'.")
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetErrorPageConfig(args)
})
if err != nil {
return err
}
return nil
}
func referConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
valSet := d.Get("refer_config").(*schema.Set)
args := cdn.ReferConfigRequest{DomainName: d.Id()}
if valSet == nil || valSet.Len() == 0 {
args.ReferType = "block"
args.AllowEmpty = "on"
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetRefererConfig(args)
})
if err != nil {
return err
}
return nil
}
val := valSet.List()[0].(map[string]interface{})
d.SetPartial("refer_config")
args.ReferType = val["refer_type"].(string)
args.AllowEmpty = val["allow_empty"].(string)
if v, ok := val["refer_list"]; ok && len(v.([]interface{})) > 0 {
referList := expandStringList(v.([]interface{}))
args.ReferList = strings.Join(referList, ",")
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetRefererConfig(args)
})
if err != nil {
return err
}
return nil
}
func authConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
ov, nv := d.GetChange("auth_config")
oldConfig, newConfig := ov.(*schema.Set), nv.(*schema.Set)
args := cdn.ReqAuthConfigRequest{DomainName: d.Id()}
if newConfig == nil || newConfig.Len() == 0 {
args.AuthType = "no_auth"
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetReqAuthConfig(args)
})
if err != nil {
return err
}
return nil
}
val := newConfig.List()[0].(map[string]interface{})
d.SetPartial("auth_config")
args.AuthType = val["auth_type"].(string)
args.Timeout = strconv.Itoa(val["timeout"].(int))
masterKey, okMasterKey := val["master_key"]
slaveKey, okSlaveKey := val["slave_key"]
if okMasterKey {
args.Key1 = masterKey.(string)
}
if okSlaveKey {
args.Key2 = slaveKey.(string)
}
if args.AuthType == "no_auth" {
if oldConfig == nil || oldConfig.Len() == 0 {
if okMasterKey || okSlaveKey {
return fmt.Errorf("If 'auth_type' value is 'no_auth', you can not set the value of 'master_key' and 'slave_key'.")
}
} else {
oldVal := oldConfig.List()[0].(map[string]interface{})
if oldVal["master_key"] != val["master_key"] || oldVal["slave_key"] != val["slave_key"] {
return fmt.Errorf("If 'auth_type' value is 'no_auth', you can not change the value of 'master_key' and 'slave_key'.")
}
}
} else {
if !okMasterKey || !okSlaveKey {
return fmt.Errorf("If 'auth_type' value is one of ['type_a', 'type_b', 'type_c'], you must set 'master_key' and 'slave_key' at one time.")
}
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetReqAuthConfig(args)
})
if err != nil {
return err
}
return nil
}
func certificateConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
ov, nv := d.GetChange("certificate_config")
oldConfig, newConfig := ov.([]interface{}), nv.([]interface{})
args := cdn.CertificateRequest{
DomainName: d.Id(),
}
if newConfig == nil || len(newConfig) == 0 {
args.ServerCertificateStatus = "off"
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetDomainServerCertificate(args)
})
if err != nil {
return err
}
d.SetPartial("certificate_config")
return nil
}
val := newConfig[0].(map[string]interface{})
args.ServerCertificateStatus = val["server_certificate_status"].(string)
serverCertificate, okServerCertificate := val["server_certificate"]
privateKey, okPrivateKey := val["private_key"]
if okServerCertificate {
args.ServerCertificate = serverCertificate.(string)
}
if okPrivateKey {
args.PrivateKey = privateKey.(string)
}
if args.ServerCertificateStatus == "off" {
if oldConfig == nil || len(oldConfig) == 0 {
if okServerCertificate || okPrivateKey {
return fmt.Errorf("If 'server_certificate_status' value is 'off', you can not set the value of 'server_certificate' and 'private_key'.")
}
}
} else {
if !okServerCertificate || !okPrivateKey {
return fmt.Errorf("If 'server_certificate_status' value is 'on', you must set 'server_certificate', and 'private_key'")
}
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetDomainServerCertificate(args)
})
if err != nil {
return err
}
d.SetPartial("certificate_config")
if okServerCertificate && args.ServerCertificateStatus != "off" {
err := WaitForServerCertificate(client, d.Id(), args.ServerCertificate, 360)
if err != nil {
return fmt.Errorf("Timeout waiting for Cdn server certificate. Error: %#v", err)
}
}
return nil
}
func httpHeaderConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
ov, nv := d.GetChange("http_header_config")
oldConfigs := ov.(*schema.Set).List()
newConfigs := nv.(*schema.Set).List()
for _, v := range oldConfigs {
configId := v.(map[string]interface{})["header_id"].(string)
args := cdn.DeleteHttpHeaderConfigRequest{
DomainName: d.Id(),
ConfigID: configId,
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.DeleteHttpHeaderConfig(args)
})
if err != nil {
return err
}
}
if len(newConfigs) == 0 {
return nil
}
for _, v := range newConfigs {
args := cdn.HttpHeaderConfigRequest{
DomainName: d.Id(),
HeaderKey: v.(map[string]interface{})["header_key"].(string),
HeaderValue: v.(map[string]interface{})["header_value"].(string),
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetHttpHeaderConfig(args)
})
if err != nil {
return fmt.Errorf("SetHttpHeaderConfig got an error: %#v", err)
}
}
return nil
}
func cacheConfigUpdate(client *connectivity.AliyunClient, d *schema.ResourceData) error {
ov, nv := d.GetChange("cache_config")
oldConfigs := ov.(*schema.Set).List()
newConfigs := nv.(*schema.Set).List()
for _, v := range oldConfigs {
val := v.(map[string]interface{})
configId := val["cache_id"].(string)
args := cdn.DeleteCacheConfigRequest{
DomainName: d.Id(),
ConfigID: configId,
CacheType: val["cache_type"].(string),
}
_, err := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.DeleteCacheExpiredConfig(args)
})
if err != nil {
return fmt.Errorf("DeleteCacheExpiredConfig got an error: %#v", err)
}
}
if len(newConfigs) == 0 {
return nil
}
for _, v := range newConfigs {
val := v.(map[string]interface{})
args := cdn.CacheConfigRequest{
DomainName: d.Id(),
CacheContent: val["cache_content"].(string),
TTL: strconv.Itoa(val["ttl"].(int)),
Weight: strconv.Itoa(val["weight"].(int)),
}
if err := setCacheExpiredConfig(args, val["cache_type"].(string), client); err != nil {
return err
}
}
return nil
}
func setCacheExpiredConfig(req cdn.CacheConfigRequest, cacheType string, client *connectivity.AliyunClient) (err error) {
if cacheType == "suffix" {
_, err = client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetFileCacheExpiredConfig(req)
})
} else {
_, err = client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.SetPathCacheExpiredConfig(req)
})
}
return
}
func describeDomainDetailClient(Id string, client *connectivity.AliyunClient) (domain cdn.DomainDetail, err error) {
args := cdn.DescribeDomainRequest{
DomainName: Id,
}
raw, e := client.WithCdnClient(func(cdnClient *cdn.CdnClient) (interface{}, error) {
return cdnClient.DescribeCdnDomainDetail(args)
})
if e != nil {
err = fmt.Errorf("DescribeCdnDomainDetail got an error: %#v", e)
return
}
response, _ := raw.(cdn.DomainResponse)
domain = response.GetDomainDetailModel
return
}
func DescribeDomainDetail(Id string, meta interface{}) (domain cdn.DomainDetail, err error) {
client := meta.(*connectivity.AliyunClient)
return describeDomainDetailClient(Id, client)
}
func WaitForDomainStatus(Id string, status Status, timeout int, meta interface{}) error {
if timeout <= 0 {
timeout = DefaultTimeout
}
for {
domain, err := DescribeDomainDetail(Id, meta)
if err != nil {
return err
}
if domain.DomainStatus == string(status) {
break
}
timeout = timeout - DefaultIntervalShort
if timeout <= 0 {
return GetTimeErrorFromString(GetTimeoutMessage("Domain", string(status)))
}
time.Sleep(DefaultIntervalShort * time.Second)
}
return nil
}
func WaitForServerCertificate(client *connectivity.AliyunClient, Id string, serverCertificate string, timeout int) error {
if timeout <= 0 {
timeout = DefaultTimeout
}
for {
domain, err := describeDomainDetailClient(Id, client)
if err != nil {
return err
}
if strings.TrimSpace(domain.ServerCertificate) == strings.TrimSpace(serverCertificate) {
break
}
timeout = timeout - DefaultIntervalShort
if timeout <= 0 {
return GetTimeErrorFromString(GetTimeoutMessage("ServerCertificate", string(serverCertificate)))
}
time.Sleep(DefaultIntervalShort * time.Second)
}
return nil
}