diff --git a/alicloud/data_source_alicloud_cen_traffic_marking_policies.go b/alicloud/data_source_alicloud_cen_traffic_marking_policies.go new file mode 100644 index 00000000000..af40730ac6f --- /dev/null +++ b/alicloud/data_source_alicloud_cen_traffic_marking_policies.go @@ -0,0 +1,218 @@ +package alicloud + +import ( + "fmt" + "regexp" + "time" + + "github.com/PaesslerAG/jsonpath" + util "github.com/alibabacloud-go/tea-utils/service" + "github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func dataSourceAlicloudCenTrafficMarkingPolicies() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAlicloudCenTrafficMarkingPoliciesRead, + Schema: map[string]*schema.Schema{ + "status": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"Active", "Creating", "Deleting", "Updating"}, false), + }, + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "ids": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + "name_regex": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.ValidateRegexp, + ForceNew: true, + }, + "names": { + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + }, + "transit_router_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "output_file": { + Type: schema.TypeString, + Optional: true, + }, + "policies": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "description": { + Type: schema.TypeString, + Computed: true, + }, + "marking_dscp": { + Type: schema.TypeInt, + Computed: true, + }, + "priority": { + Type: schema.TypeInt, + Computed: true, + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "id": { + Type: schema.TypeString, + Computed: true, + }, + "traffic_marking_policy_id": { + Type: schema.TypeString, + Computed: true, + }, + "transit_router_id": { + Type: schema.TypeString, + Computed: true, + }, + "traffic_marking_policy_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceAlicloudCenTrafficMarkingPoliciesRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + + action := "ListTrafficMarkingPolicies" + request := make(map[string]interface{}) + if v, ok := d.GetOk("description"); ok { + request["TrafficMarkingPolicyDescription"] = v + } + request["TransitRouterId"] = d.Get("transit_router_id") + request["MaxResults"] = PageSizeLarge + var objects []map[string]interface{} + var trafficMarkingPolicyNameRegex *regexp.Regexp + if v, ok := d.GetOk("name_regex"); ok { + r, err := regexp.Compile(v.(string)) + if err != nil { + return WrapError(err) + } + trafficMarkingPolicyNameRegex = r + } + + idsMap := make(map[string]string) + if v, ok := d.GetOk("ids"); ok { + for _, vv := range v.([]interface{}) { + if vv == nil { + continue + } + idsMap[vv.(string)] = vv.(string) + } + } + status, statusOk := d.GetOk("status") + var response map[string]interface{} + conn, err := client.NewCbnClient() + if err != nil { + return WrapError(err) + } + for { + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 3*time.Second) + err = resource.Retry(5*time.Minute, func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-09-12"), StringPointer("AK"), nil, request, &runtime) + if err != nil { + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + return nil + }) + addDebug(action, response, request) + if err != nil { + return WrapErrorf(err, DataDefaultErrorMsg, "alicloud_cen_traffic_marking_policies", action, AlibabaCloudSdkGoERROR) + } + resp, err := jsonpath.Get("$.TrafficMarkingPolicies", response) + if err != nil { + return WrapErrorf(err, FailedGetAttributeMsg, action, "$.TrafficMarkingPolicies", response) + } + result, _ := resp.([]interface{}) + for _, v := range result { + item := v.(map[string]interface{}) + if trafficMarkingPolicyNameRegex != nil && !trafficMarkingPolicyNameRegex.MatchString(fmt.Sprint(item["TrafficMarkingPolicyName"])) { + continue + } + if len(idsMap) > 0 { + if _, ok := idsMap[fmt.Sprint(request["TransitRouterId"], ":", item["TrafficMarkingPolicyId"])]; !ok { + continue + } + } + if statusOk && status.(string) != "" && status.(string) != item["TrafficMarkingPolicyStatus"].(string) { + continue + } + objects = append(objects, item) + } + if nextToken, ok := response["NextToken"].(string); ok && nextToken != "" { + request["NextToken"] = nextToken + } else { + break + } + } + ids := make([]string, 0) + names := make([]interface{}, 0) + s := make([]map[string]interface{}, 0) + for _, object := range objects { + mapping := map[string]interface{}{ + "description": object["TrafficMarkingPolicyDescription"], + "marking_dscp": formatInt(object["MarkingDscp"]), + "priority": formatInt(object["Priority"]), + "status": object["TrafficMarkingPolicyStatus"], + "transit_router_id": request["TransitRouterId"], + "id": fmt.Sprint(request["TransitRouterId"], ":", object["TrafficMarkingPolicyId"]), + "traffic_marking_policy_id": fmt.Sprint(object["TrafficMarkingPolicyId"]), + "traffic_marking_policy_name": object["TrafficMarkingPolicyName"], + } + ids = append(ids, fmt.Sprint(mapping["id"])) + names = append(names, object["TrafficMarkingPolicyName"]) + s = append(s, mapping) + } + + d.SetId(dataResourceIdHash(ids)) + if err := d.Set("ids", ids); err != nil { + return WrapError(err) + } + + if err := d.Set("names", names); err != nil { + return WrapError(err) + } + + if err := d.Set("policies", s); err != nil { + return WrapError(err) + } + if output, ok := d.GetOk("output_file"); ok && output.(string) != "" { + writeToFile(output.(string), s) + } + + return nil +} diff --git a/alicloud/data_source_alicloud_cen_traffic_marking_policies_test.go b/alicloud/data_source_alicloud_cen_traffic_marking_policies_test.go new file mode 100644 index 00000000000..c06c31a860e --- /dev/null +++ b/alicloud/data_source_alicloud_cen_traffic_marking_policies_test.go @@ -0,0 +1,136 @@ +package alicloud + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" +) + +func TestAccAlicloudCenTrafficMarkingPoliciesDataSource(t *testing.T) { + rand := acctest.RandIntRange(1000000, 9999999) + nameRegexConf := dataSourceTestAccConfig{ + existConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "name_regex": `"${alicloud_cen_traffic_marking_policy.default.traffic_marking_policy_name}"`, + }), + fakeConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "name_regex": `"${alicloud_cen_traffic_marking_policy.default.traffic_marking_policy_name}_fake"`, + }), + } + + idsConf := dataSourceTestAccConfig{ + existConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}"]`, + }), + fakeConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}_fake"]`, + }), + } + + descriptionConf := dataSourceTestAccConfig{ + existConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}"]`, + "description": `"${alicloud_cen_traffic_marking_policy.default.description}"`, + }), + fakeConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}"]`, + "description": `"${alicloud_cen_traffic_marking_policy.default.description}_fake"`, + }), + } + + statusConf := dataSourceTestAccConfig{ + existConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}"]`, + "status": `"Active"`, + }), + fakeConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}"]`, + "status": `"Creating"`, + }), + } + + allConf := dataSourceTestAccConfig{ + existConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}"]`, + "name_regex": `"${alicloud_cen_traffic_marking_policy.default.traffic_marking_policy_name}"`, + "description": `"${alicloud_cen_traffic_marking_policy.default.description}"`, + "status": `"Active"`, + }), + fakeConfig: testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand, map[string]string{ + "ids": `["${alicloud_cen_traffic_marking_policy.default.id}_fake"]`, + "name_regex": `"${alicloud_cen_traffic_marking_policy.default.traffic_marking_policy_name}_fake"`, + "description": `"${alicloud_cen_traffic_marking_policy.default.description}_fake"`, + "status": `"Creating"`, + }), + } + + var existCenTrafficMarkingPoliciesMapFunc = func(rand int) map[string]string { + return map[string]string{ + "ids.#": "1", + "policies.#": "1", + "policies.0.priority": "1", + "policies.0.description": fmt.Sprintf("tf-testAccCenTrafficMarkingPolicies%d", rand), + "policies.0.traffic_marking_policy_name": fmt.Sprintf("tf-testAccCenTrafficMarkingPolicies%d", rand), + "policies.0.traffic_marking_policy_id": CHECKSET, + "policies.0.marking_dscp": "1", + "policies.0.transit_router_id": CHECKSET, + "policies.0.status": "Active", + "policies.0.id": CHECKSET, + } + } + + var fakeCenTrafficMarkingPoliciesMapFunc = func(rand int) map[string]string { + return map[string]string{ + "ids.#": "0", + "policies.#": "0", + } + } + + var cenTrafficMarkingPoliciesCheckInfo = dataSourceAttr{ + resourceId: "data.alicloud_cen_traffic_marking_policies.default", + existMapFunc: existCenTrafficMarkingPoliciesMapFunc, + fakeMapFunc: fakeCenTrafficMarkingPoliciesMapFunc, + } + preCheck := func() { + testAccPreCheck(t) + } + + cenTrafficMarkingPoliciesCheckInfo.dataSourceTestCheckWithPreCheck(t, rand, preCheck, nameRegexConf, idsConf, statusConf, descriptionConf, allConf) + +} + +func testAccCheckAlicloudCenTrafficMarkingPoliciesSourceConfig(rand int, attrMap map[string]string) string { + var pairs []string + for k, v := range attrMap { + pairs = append(pairs, k+" = "+v) + } + config := fmt.Sprintf(` +variable "name" { + default = "tf-testAccCenTrafficMarkingPolicies%d" +} + +resource "alicloud_cen_instance" "default" { + cen_instance_name = var.name +} + +resource "alicloud_cen_transit_router" "default" { + cen_id = alicloud_cen_instance.default.id + transit_router_name = var.name +} + +resource "alicloud_cen_traffic_marking_policy" "default" { + marking_dscp = 1 + priority = 1 + traffic_marking_policy_name = var.name + description = var.name + transit_router_id = alicloud_cen_transit_router.default.transit_router_id +} + +data "alicloud_cen_traffic_marking_policies" "default" { + transit_router_id = alicloud_cen_transit_router.default.transit_router_id +%s +} +`, rand, strings.Join(pairs, "\n ")) + return config +} diff --git a/alicloud/provider.go b/alicloud/provider.go index 8a65dd0e378..78447706ba5 100644 --- a/alicloud/provider.go +++ b/alicloud/provider.go @@ -703,6 +703,7 @@ func Provider() terraform.ResourceProvider { "alicloud_cdn_blocked_regions": dataSourceAlicloudCdnBlockedRegions(), "alicloud_schedulerx_namespaces": dataSourceAlicloudSchedulerxNamespaces(), "alicloud_ehpc_clusters": dataSourceAlicloudEhpcClusters(), + "alicloud_cen_traffic_marking_policies": dataSourceAlicloudCenTrafficMarkingPolicies(), }, ResourcesMap: map[string]*schema.Resource{ "alicloud_instance": resourceAliyunInstance(), @@ -1302,6 +1303,7 @@ func Provider() terraform.ResourceProvider { "alicloud_edas_namespace": resourceAlicloudEdasNamespace(), "alicloud_schedulerx_namespace": resourceAlicloudSchedulerxNamespace(), "alicloud_ehpc_cluster": resourceAlicloudEhpcCluster(), + "alicloud_cen_traffic_marking_policy": resourceAlicloudCenTrafficMarkingPolicy(), }, ConfigureFunc: providerConfigure, diff --git a/alicloud/resource_alicloud_cen_traffic_marking_policy.go b/alicloud/resource_alicloud_cen_traffic_marking_policy.go new file mode 100644 index 00000000000..826964319f8 --- /dev/null +++ b/alicloud/resource_alicloud_cen_traffic_marking_policy.go @@ -0,0 +1,248 @@ +package alicloud + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "log" + "regexp" + "time" + + util "github.com/alibabacloud-go/tea-utils/service" + "github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func resourceAlicloudCenTrafficMarkingPolicy() *schema.Resource { + return &schema.Resource{ + Create: resourceAlicloudCenTrafficMarkingPolicyCreate, + Read: resourceAlicloudCenTrafficMarkingPolicyRead, + Update: resourceAlicloudCenTrafficMarkingPolicyUpdate, + Delete: resourceAlicloudCenTrafficMarkingPolicyDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(6 * time.Minute), + Delete: schema.DefaultTimeout(6 * time.Minute), + Update: schema.DefaultTimeout(6 * time.Minute), + }, + Schema: map[string]*schema.Schema{ + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]{1,127}$`), "The description must be 2 to 128 characters in length, and must start with a letter. It can contain digits, underscores (_), and hyphens (-)."), + }, + "dry_run": { + Type: schema.TypeBool, + Optional: true, + }, + "marking_dscp": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: intBetween(0, 63), + }, + "priority": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + ValidateFunc: intBetween(1, 100), + }, + "status": { + Type: schema.TypeString, + Computed: true, + }, + "traffic_marking_policy_name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]{1,127}$`), "The name must be 2 to 128 characters in length, and must start with a letter. It can contain digits, underscores (_), and hyphens (-)."), + }, + "transit_router_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "traffic_marking_policy_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceAlicloudCenTrafficMarkingPolicyCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + var response map[string]interface{} + action := "CreateTrafficMarkingPolicy" + request := make(map[string]interface{}) + conn, err := client.NewCbnClient() + if err != nil { + return WrapError(err) + } + if v, ok := d.GetOk("description"); ok { + request["TrafficMarkingPolicyDescription"] = v + } + if v, ok := d.GetOkExists("dry_run"); ok { + request["DryRun"] = v + } + request["MarkingDscp"] = d.Get("marking_dscp") + request["Priority"] = d.Get("priority") + if v, ok := d.GetOk("traffic_marking_policy_name"); ok { + request["TrafficMarkingPolicyName"] = v + } + request["TransitRouterId"] = d.Get("transit_router_id") + request["ClientToken"] = buildClientToken("CreateTrafficMarkingPolicy") + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 5*time.Second) + err = resource.Retry(d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-09-12"), StringPointer("AK"), nil, request, &runtime) + if err != nil { + if IsExpectedErrors(err, []string{"Operation.Blocking", "Throttling.User"}) || NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + return nil + }) + addDebug(action, response, request) + if err != nil { + return WrapErrorf(err, DefaultErrorMsg, "alicloud_cen_traffic_marking_policy", action, AlibabaCloudSdkGoERROR) + } + + d.SetId(fmt.Sprint(request["TransitRouterId"], ":", response["TrafficMarkingPolicyId"])) + cbnService := CbnService{client} + stateConf := BuildStateConf([]string{}, []string{"Active"}, d.Timeout(schema.TimeoutCreate), 5*time.Second, cbnService.CenTrafficMarkingPolicyStateRefreshFunc(d.Id(), []string{})) + if _, err := stateConf.WaitForState(); err != nil { + return WrapErrorf(err, IdMsg, d.Id()) + } + + return resourceAlicloudCenTrafficMarkingPolicyRead(d, meta) +} +func resourceAlicloudCenTrafficMarkingPolicyRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + cbnService := CbnService{client} + object, err := cbnService.DescribeCenTrafficMarkingPolicy(d.Id()) + if err != nil { + if NotFoundError(err) { + log.Printf("[DEBUG] Resource alicloud_cen_traffic_marking_policy cbnService.DescribeCenTrafficMarkingPolicy Failed!!! %s", err) + d.SetId("") + return nil + } + return WrapError(err) + } + parts, err := ParseResourceId(d.Id(), 2) + if err != nil { + return WrapError(err) + } + + d.Set("transit_router_id", parts[0]) + d.Set("traffic_marking_policy_id", parts[1]) + d.Set("description", object["TrafficMarkingPolicyDescription"]) + d.Set("marking_dscp", object["MarkingDscp"]) + d.Set("priority", object["Priority"]) + d.Set("status", object["TrafficMarkingPolicyStatus"]) + d.Set("traffic_marking_policy_name", object["TrafficMarkingPolicyName"]) + return nil +} +func resourceAlicloudCenTrafficMarkingPolicyUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + conn, err := client.NewCbnClient() + if err != nil { + return WrapError(err) + } + cbnService := CbnService{client} + var response map[string]interface{} + update := false + parts, err := ParseResourceId(d.Id(), 2) + if err != nil { + return WrapError(err) + } + request := map[string]interface{}{ + "TrafficMarkingPolicyId": parts[1], + } + if d.HasChange("description") { + update = true + if v, ok := d.GetOk("description"); ok { + request["TrafficMarkingPolicyDescription"] = v + } + } + if d.HasChange("traffic_marking_policy_name") { + update = true + if v, ok := d.GetOk("traffic_marking_policy_name"); ok { + request["TrafficMarkingPolicyName"] = v + } + } + if update { + if v, ok := d.GetOkExists("dry_run"); ok { + request["DryRun"] = v + } + action := "UpdateTrafficMarkingPolicyAttribute" + request["ClientToken"] = buildClientToken("UpdateTrafficMarkingPolicyAttribute") + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 5*time.Second) + err = resource.Retry(d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-09-12"), StringPointer("AK"), nil, request, &runtime) + if err != nil { + if IsExpectedErrors(err, []string{"Operation.Blocking", "Throttling.User"}) || NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + return nil + }) + addDebug(action, response, request) + if err != nil { + return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR) + } + stateConf := BuildStateConf([]string{}, []string{"Active"}, d.Timeout(schema.TimeoutUpdate), 5*time.Second, cbnService.CenTrafficMarkingPolicyStateRefreshFunc(d.Id(), []string{})) + if _, err := stateConf.WaitForState(); err != nil { + return WrapErrorf(err, IdMsg, d.Id()) + } + } + return resourceAlicloudCenTrafficMarkingPolicyRead(d, meta) +} +func resourceAlicloudCenTrafficMarkingPolicyDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*connectivity.AliyunClient) + action := "DeleteTrafficMarkingPolicy" + var response map[string]interface{} + conn, err := client.NewCbnClient() + if err != nil { + return WrapError(err) + } + parts, err := ParseResourceId(d.Id(), 2) + if err != nil { + return WrapError(err) + } + request := map[string]interface{}{ + "TrafficMarkingPolicyId": parts[1], + } + + if v, ok := d.GetOkExists("dry_run"); ok { + request["DryRun"] = v + } + request["ClientToken"] = buildClientToken("DeleteTrafficMarkingPolicy") + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 5*time.Second) + err = resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-09-12"), StringPointer("AK"), nil, request, &runtime) + if err != nil { + if IsExpectedErrors(err, []string{"Operation.Blocking", "Throttling.User"}) || NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + return nil + }) + addDebug(action, response, request) + if err != nil { + return WrapErrorf(err, DefaultErrorMsg, d.Id(), action, AlibabaCloudSdkGoERROR) + } + return nil +} diff --git a/alicloud/resource_alicloud_cen_traffic_marking_policy_test.go b/alicloud/resource_alicloud_cen_traffic_marking_policy_test.go new file mode 100644 index 00000000000..5d5af158f70 --- /dev/null +++ b/alicloud/resource_alicloud_cen_traffic_marking_policy_test.go @@ -0,0 +1,374 @@ +package alicloud + +import ( + "fmt" + "log" + "os" + "reflect" + "testing" + + "github.com/agiledragon/gomonkey/v2" + "github.com/alibabacloud-go/tea-rpc/client" + util "github.com/alibabacloud-go/tea-utils/service" + "github.com/alibabacloud-go/tea/tea" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/stretchr/testify/assert" + + "github.com/aliyun/terraform-provider-alicloud/alicloud/connectivity" + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccAlicloudCENTrafficMarkingPolicy_basic0(t *testing.T) { + var v map[string]interface{} + resourceId := "alicloud_cen_traffic_marking_policy.default" + checkoutSupportedRegions(t, true, connectivity.CenTRSupportRegions) + ra := resourceAttrInit(resourceId, AlicloudCENTrafficMarkingPolicyMap0) + rc := resourceCheckInitWithDescribeMethod(resourceId, &v, func() interface{} { + return &CbnService{testAccProvider.Meta().(*connectivity.AliyunClient)} + }, "DescribeCenTrafficMarkingPolicy") + rac := resourceAttrCheckInit(rc, ra) + testAccCheck := rac.resourceAttrMapUpdateSet() + rand := acctest.RandIntRange(10000, 99999) + name := fmt.Sprintf("tf-testacc%scentrafficmarkingpolicy%d", defaultRegionToTest, rand) + testAccConfig := resourceTestAccConfigFunc(resourceId, name, AlicloudCENTrafficMarkingPolicyBasicDependence0) + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + IDRefreshName: resourceId, + Providers: testAccProviders, + CheckDestroy: rac.checkResourceDestroy(), + Steps: []resource.TestStep{ + { + Config: testAccConfig(map[string]interface{}{ + "priority": "5", + "description": "${var.name}", + "traffic_marking_policy_name": "${var.name}", + "marking_dscp": "5", + "transit_router_id": "${alicloud_cen_transit_router.default.transit_router_id}", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "priority": "5", + "description": name, + "traffic_marking_policy_name": name, + "marking_dscp": "5", + "transit_router_id": CHECKSET, + }), + ), + }, + { + Config: testAccConfig(map[string]interface{}{ + "description": "${var.name}_update", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "description": name + "_update", + }), + ), + }, + { + Config: testAccConfig(map[string]interface{}{ + "traffic_marking_policy_name": "${var.name}_update", + }), + Check: resource.ComposeTestCheckFunc( + testAccCheck(map[string]string{ + "traffic_marking_policy_name": name + "_update", + }), + ), + }, + { + ResourceName: resourceId, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"dry_run"}, + }, + }, + }) +} + +var AlicloudCENTrafficMarkingPolicyMap0 = map[string]string{ + "dry_run": NOSET, + "status": CHECKSET, +} + +func AlicloudCENTrafficMarkingPolicyBasicDependence0(name string) string { + return fmt.Sprintf(` +variable "name" { + default = "%s" +} +resource "alicloud_cen_instance" "default" { + cen_instance_name = var.name +} + +resource "alicloud_cen_transit_router" "default" { + cen_id = alicloud_cen_instance.default.id + transit_router_name = var.name +} +`, name) +} + +func TestUnitAccAlicloudCENTrafficMarkingPolicy(t *testing.T) { + p := Provider().(*schema.Provider).ResourcesMap + dInit, _ := schema.InternalMap(p["alicloud_cen_traffic_marking_policy"].Schema).Data(nil, nil) + dExisted, _ := schema.InternalMap(p["alicloud_cen_traffic_marking_policy"].Schema).Data(nil, nil) + dInit.MarkNewResource() + attributes := map[string]interface{}{ + "priority": 5, + "dry_run": true, + "description": "CreateCenTrafficMarkingPolicyValue", + "traffic_marking_policy_name": "CreateCenTrafficMarkingPolicyValue", + "marking_dscp": 5, + "transit_router_id": "CreateCenTrafficMarkingPolicyValue", + } + for key, value := range attributes { + err := dInit.Set(key, value) + assert.Nil(t, err) + err = dExisted.Set(key, value) + assert.Nil(t, err) + if err != nil { + log.Printf("[ERROR] the field %s setting error", key) + } + } + region := os.Getenv("ALICLOUD_REGION") + rawClient, err := sharedClientForRegion(region) + if err != nil { + t.Skipf("Skipping the test case with err: %s", err) + t.Skipped() + } + + rawClient = rawClient.(*connectivity.AliyunClient) + ReadMockResponse := map[string]interface{}{ + "TrafficMarkingPolicies": []interface{}{ + map[string]interface{}{ + "TrafficMarkingPolicyStatus": "Active", + "TrafficMarkingPolicyId": "CreateCenTrafficMarkingPolicyValue", + "MarkingDscp": 5, + "TrafficMarkingPolicyName": "CreateCenTrafficMarkingPolicyValue", + "Priority": 5, + "TrafficMarkingPolicyDescription": "CreateCenTrafficMarkingPolicyValue", + }, + }, + } + CreateMockResponse := map[string]interface{}{ + "TrafficMarkingPolicyId": "CreateCenTrafficMarkingPolicyValue", + } + failedResponseMock := func(errorCode string) (map[string]interface{}, error) { + return nil, &tea.SDKError{ + Code: String(errorCode), + Data: String(errorCode), + Message: String(errorCode), + StatusCode: tea.Int(400), + } + } + notFoundResponseMock := func(errorCode string) (map[string]interface{}, error) { + return nil, GetNotFoundErrorFromString(GetNotFoundMessage("alicloud_cen_traffic_marking_policy", errorCode)) + } + successResponseMock := func(operationMockResponse map[string]interface{}) (map[string]interface{}, error) { + if len(operationMockResponse) > 0 { + mapMerge(ReadMockResponse, operationMockResponse) + } + return ReadMockResponse, nil + } + // Create + patches := gomonkey.ApplyMethod(reflect.TypeOf(&connectivity.AliyunClient{}), "NewCbnClient", func(_ *connectivity.AliyunClient) (*client.Client, error) { + return nil, &tea.SDKError{ + Code: String("loadEndpoint error"), + Data: String("loadEndpoint error"), + Message: String("loadEndpoint error"), + StatusCode: tea.Int(400), + } + }) + err = resourceAlicloudCenTrafficMarkingPolicyCreate(dInit, rawClient) + patches.Reset() + assert.NotNil(t, err) + ReadMockResponseDiff := map[string]interface{}{} + errorCodes := []string{"NonRetryableError", "Throttling", "nil"} + for index, errorCode := range errorCodes { + retryIndex := index - 1 // a counter used to cover retry scenario; the same below + patches = gomonkey.ApplyMethod(reflect.TypeOf(&client.Client{}), "DoRequest", func(_ *client.Client, action *string, _ *string, _ *string, _ *string, _ *string, _ map[string]interface{}, _ map[string]interface{}, _ *util.RuntimeOptions) (map[string]interface{}, error) { + if *action == "CreateTrafficMarkingPolicy" { + switch errorCode { + case "NonRetryableError": + return failedResponseMock(errorCode) + default: + retryIndex++ + if retryIndex >= len(errorCodes)-1 { + successResponseMock(ReadMockResponseDiff) + return CreateMockResponse, nil + } + return failedResponseMock(errorCodes[retryIndex]) + } + } + return ReadMockResponse, nil + }) + err := resourceAlicloudCenTrafficMarkingPolicyCreate(dInit, rawClient) + patches.Reset() + switch errorCode { + case "NonRetryableError": + assert.NotNil(t, err) + default: + assert.Nil(t, err) + dCompare, _ := schema.InternalMap(p["alicloud_cen_traffic_marking_policy"].Schema).Data(dInit.State(), nil) + for key, value := range attributes { + _ = dCompare.Set(key, value) + } + assert.Equal(t, dCompare.State().Attributes, dInit.State().Attributes) + } + if retryIndex >= len(errorCodes)-1 { + break + } + } + + // Update + patches = gomonkey.ApplyMethod(reflect.TypeOf(&connectivity.AliyunClient{}), "NewCbnClient", func(_ *connectivity.AliyunClient) (*client.Client, error) { + return nil, &tea.SDKError{ + Code: String("loadEndpoint error"), + Data: String("loadEndpoint error"), + Message: String("loadEndpoint error"), + StatusCode: tea.Int(400), + } + }) + err = resourceAlicloudCenTrafficMarkingPolicyUpdate(dExisted, rawClient) + patches.Reset() + assert.NotNil(t, err) + attributesDiff := map[string]interface{}{ + "description": "UpdateCenTrafficMarkingPolicyValue", + "traffic_marking_policy_name": "UpdateCenTrafficMarkingPolicyValue", + } + diff, err := newInstanceDiff("alicloud_cen_traffic_marking_policy", attributes, attributesDiff, dInit.State()) + if err != nil { + t.Error(err) + } + dExisted, _ = schema.InternalMap(p["alicloud_cen_traffic_marking_policy"].Schema).Data(dInit.State(), diff) + ReadMockResponseDiff = map[string]interface{}{ + "TrafficMarkingPolicies": []interface{}{ + map[string]interface{}{ + "TrafficMarkingPolicyName": "UpdateCenTrafficMarkingPolicyValue", + "TrafficMarkingPolicyDescription": "UpdateCenTrafficMarkingPolicyValue", + }, + }, + } + errorCodes = []string{"NonRetryableError", "Throttling", "nil"} + for index, errorCode := range errorCodes { + retryIndex := index - 1 + patches = gomonkey.ApplyMethod(reflect.TypeOf(&client.Client{}), "DoRequest", func(_ *client.Client, action *string, _ *string, _ *string, _ *string, _ *string, _ map[string]interface{}, _ map[string]interface{}, _ *util.RuntimeOptions) (map[string]interface{}, error) { + if *action == "UpdateTrafficMarkingPolicyAttribute" { + switch errorCode { + case "NonRetryableError": + return failedResponseMock(errorCode) + default: + retryIndex++ + if retryIndex >= len(errorCodes)-1 { + return successResponseMock(ReadMockResponseDiff) + } + return failedResponseMock(errorCodes[retryIndex]) + } + } + return ReadMockResponse, nil + }) + err := resourceAlicloudCenTrafficMarkingPolicyUpdate(dExisted, rawClient) + patches.Reset() + switch errorCode { + case "NonRetryableError": + assert.NotNil(t, err) + default: + assert.Nil(t, err) + dCompare, _ := schema.InternalMap(p["alicloud_cen_traffic_marking_policy"].Schema).Data(dExisted.State(), nil) + for key, value := range attributes { + _ = dCompare.Set(key, value) + } + assert.Equal(t, dCompare.State().Attributes, dExisted.State().Attributes) + } + if retryIndex >= len(errorCodes)-1 { + break + } + } + + // Read + diff, err = newInstanceDiff("alicloud_cen_traffic_marking_policy", attributes, attributesDiff, dInit.State()) + if err != nil { + t.Error(err) + } + dExisted, _ = schema.InternalMap(p["alicloud_cen_traffic_marking_policy"].Schema).Data(dInit.State(), diff) + errorCodes = []string{"NonRetryableError", "Throttling", "nil", "{}"} + for index, errorCode := range errorCodes { + retryIndex := index - 1 + patches = gomonkey.ApplyMethod(reflect.TypeOf(&client.Client{}), "DoRequest", func(_ *client.Client, action *string, _ *string, _ *string, _ *string, _ *string, _ map[string]interface{}, _ map[string]interface{}, _ *util.RuntimeOptions) (map[string]interface{}, error) { + if *action == "ListTrafficMarkingPolicies" { + switch errorCode { + case "{}": + return notFoundResponseMock(errorCode) + case "NonRetryableError": + return failedResponseMock(errorCode) + default: + retryIndex++ + if errorCodes[retryIndex] == "nil" { + return ReadMockResponse, nil + } + return failedResponseMock(errorCodes[retryIndex]) + } + } + return ReadMockResponse, nil + }) + err := resourceAlicloudCenTrafficMarkingPolicyRead(dExisted, rawClient) + patches.Reset() + switch errorCode { + case "NonRetryableError": + assert.NotNil(t, err) + case "{}": + assert.Nil(t, err) + } + } + + // Delete + patches = gomonkey.ApplyMethod(reflect.TypeOf(&connectivity.AliyunClient{}), "NewCbnClient", func(_ *connectivity.AliyunClient) (*client.Client, error) { + return nil, &tea.SDKError{ + Code: String("loadEndpoint error"), + Data: String("loadEndpoint error"), + Message: String("loadEndpoint error"), + StatusCode: tea.Int(400), + } + }) + err = resourceAlicloudCenTrafficMarkingPolicyDelete(dExisted, rawClient) + patches.Reset() + assert.NotNil(t, err) + attributesDiff = map[string]interface{}{} + diff, err = newInstanceDiff("alicloud_cen_traffic_marking_policy", attributes, attributesDiff, dInit.State()) + if err != nil { + t.Error(err) + } + dExisted, _ = schema.InternalMap(p["alicloud_cen_traffic_marking_policy"].Schema).Data(dInit.State(), diff) + errorCodes = []string{"NonRetryableError", "Throttling", "nil"} + for index, errorCode := range errorCodes { + retryIndex := index - 1 + patches := gomonkey.ApplyMethod(reflect.TypeOf(&client.Client{}), "DoRequest", func(_ *client.Client, action *string, _ *string, _ *string, _ *string, _ *string, _ map[string]interface{}, _ map[string]interface{}, _ *util.RuntimeOptions) (map[string]interface{}, error) { + if *action == "DeleteTrafficMarkingPolicy" { + switch errorCode { + case "NonRetryableError": + return failedResponseMock(errorCode) + default: + retryIndex++ + if errorCodes[retryIndex] == "nil" { + ReadMockResponse = map[string]interface{}{} + return ReadMockResponse, nil + } + return failedResponseMock(errorCodes[retryIndex]) + } + } + if *action == "ListTrafficMarkingPolicies" { + return notFoundResponseMock("{}") + } + return ReadMockResponse, nil + }) + err := resourceAlicloudCenTrafficMarkingPolicyDelete(dExisted, rawClient) + patches.Reset() + switch errorCode { + case "NonRetryableError": + assert.NotNil(t, err) + case "nil": + assert.Nil(t, err) + } + } +} diff --git a/alicloud/service_alicloud_cbn.go b/alicloud/service_alicloud_cbn.go index 80cc5670cd5..1a956de56b8 100644 --- a/alicloud/service_alicloud_cbn.go +++ b/alicloud/service_alicloud_cbn.go @@ -1186,3 +1186,72 @@ func (s *CbnService) CenTransitRouterRouteTablePropagationStateRefreshFunc(id st return object, fmt.Sprint(object["Status"]), nil } } + +func (s *CbnService) DescribeCenTrafficMarkingPolicy(id string) (object map[string]interface{}, err error) { + var response map[string]interface{} + conn, err := s.client.NewCbnClient() + if err != nil { + return nil, WrapError(err) + } + parts, err := ParseResourceId(id, 2) + if err != nil { + err = WrapError(err) + return + } + action := "ListTrafficMarkingPolicies" + request := map[string]interface{}{ + "TransitRouterId": parts[0], + "TrafficMarkingPolicyId": parts[1], + } + runtime := util.RuntimeOptions{} + runtime.SetAutoretry(true) + wait := incrementalWait(3*time.Second, 3*time.Second) + err = resource.Retry(5*time.Minute, func() *resource.RetryError { + response, err = conn.DoRequest(StringPointer(action), nil, StringPointer("POST"), StringPointer("2017-09-12"), StringPointer("AK"), nil, request, &runtime) + if err != nil { + if NeedRetry(err) { + wait() + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + return nil + }) + addDebug(action, response, request) + if err != nil { + return object, WrapErrorf(err, DefaultErrorMsg, id, action, AlibabaCloudSdkGoERROR) + } + v, err := jsonpath.Get("$.TrafficMarkingPolicies", response) + if err != nil { + return object, WrapErrorf(err, FailedGetAttributeMsg, id, "$.TrafficMarkingPolicies", response) + } + if len(v.([]interface{})) < 1 { + return object, WrapErrorf(Error(GetNotFoundMessage("CEN", id)), NotFoundWithResponse, response) + } else { + if v.([]interface{})[0].(map[string]interface{})["TrafficMarkingPolicyId"].(string) != parts[1] { + return object, WrapErrorf(Error(GetNotFoundMessage("CEN", id)), NotFoundWithResponse, response) + } + } + object = v.([]interface{})[0].(map[string]interface{}) + return object, nil +} + +func (s *CbnService) CenTrafficMarkingPolicyStateRefreshFunc(id string, failStates []string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + object, err := s.DescribeCenTrafficMarkingPolicy(id) + if err != nil { + if NotFoundError(err) { + // Set this to nil as if we didn't find anything. + return nil, "", nil + } + return nil, "", WrapError(err) + } + + for _, failState := range failStates { + if fmt.Sprint(object["TrafficMarkingPolicyStatus"]) == failState { + return object, fmt.Sprint(object["TrafficMarkingPolicyStatus"]), WrapError(Error(FailedToReachTargetStatus, fmt.Sprint(object["TrafficMarkingPolicyStatus"]))) + } + } + return object, fmt.Sprint(object["TrafficMarkingPolicyStatus"]), nil + } +} diff --git a/website/alicloud.erb b/website/alicloud.erb index cc516140783..0ac62f28f61 100644 --- a/website/alicloud.erb +++ b/website/alicloud.erb @@ -784,6 +784,9 @@
  • alicloud_cen_route_maps
  • +
  • + alicloud_cen_traffic_marking_policies +
  • alicloud_cen_transit_router_available_resources
  • @@ -855,6 +858,9 @@
  • alicloud_cen_route_map
  • +
  • + alicloud_cen_traffic_marking_policy +
  • alicloud_cen_transit_router
  • diff --git a/website/docs/d/cen_traffic_marking_policies.html.markdown b/website/docs/d/cen_traffic_marking_policies.html.markdown new file mode 100644 index 00000000000..49768b0220b --- /dev/null +++ b/website/docs/d/cen_traffic_marking_policies.html.markdown @@ -0,0 +1,62 @@ +--- +subcategory: "Cloud Enterprise Network (CEN)" +layout: "alicloud" +page_title: "Alicloud: alicloud_cen_traffic_marking_policies" +sidebar_current: "docs-alicloud-datasource-cen-traffic-marking-policies" +description: |- + Provides a list of Cen Traffic Marking Policies to the user. +--- + +# alicloud\_cen\_traffic\_marking\_policies + +This data source provides the Cen Traffic Marking Policies of the current Alibaba Cloud user. + +-> **NOTE:** Available in v1.173.0+. + +## Example Usage + +Basic Usage + +```terraform +data "alicloud_cen_traffic_marking_policies" "ids" { + transit_router_id = "example_value" + ids = ["example_value-1", "example_value-2"] +} +output "cen_traffic_marking_policy_id_1" { + value = data.alicloud_cen_traffic_marking_policies.ids.policies.0.id +} + +data "alicloud_cen_traffic_marking_policies" "nameRegex" { + transit_router_id = "example_value" + name_regex = "^my-TrafficMarkingPolicy" +} +output "cen_traffic_marking_policy_id_2" { + value = data.alicloud_cen_traffic_marking_policies.nameRegex.policies.0.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `ids` - (Optional, ForceNew, Computed) A list of Traffic Marking Policy IDs. +* `name_regex` - (Optional, ForceNew) A regex string to filter results by Traffic Marking Policy name. +* `output_file` - (Optional) File name where to save data source results (after running `terraform plan`). +* `status` - (Optional, ForceNew) The status of the resource. Valid values: `Active`, `Creating`, `Deleting`, `Updating`. +* `traffic_marking_policy_description` - (Optional, ForceNew) The traffic marking policy description. +* `transit_router_id` - (Required, ForceNew) The ID of the transit router. + +## Argument Reference + +The following attributes are exported in addition to the arguments listed above: + +* `names` - A list of Traffic Marking Policy names. +* `policies` - A list of Cen Traffic Marking Policies. Each element contains the following attributes: + * `description` - The description of the Traffic Marking Policy. + * `id` - The ID of the resource. The value is formatted `:`. + * `marking_dscp` - The DSCP(Differentiated Services Code Point) of the Traffic Marking Policy. + * `priority` - The Priority of the Traffic Marking Policy. + * `transit_router_id` - The ID of the transit router. + * `status` - The status of the resource. + * `traffic_marking_policy_id` - The ID of the Traffic Marking Policy. + * `traffic_marking_policy_name` - The name of the Traffic Marking Policy. \ No newline at end of file diff --git a/website/docs/r/cen_traffic_marking_policy.html.markdown b/website/docs/r/cen_traffic_marking_policy.html.markdown new file mode 100644 index 00000000000..d33c3fac847 --- /dev/null +++ b/website/docs/r/cen_traffic_marking_policy.html.markdown @@ -0,0 +1,73 @@ +--- +subcategory: "Cloud Enterprise Network (CEN)" +layout: "alicloud" +page_title: "Alicloud: alicloud_cen_traffic_marking_policy" +sidebar_current: "docs-alicloud-resource-cen-traffic-marking-policy" +description: |- + Provides a Alicloud Cloud Enterprise Network (CEN) Traffic Marking Policy resource. +--- + +# alicloud\_cen\_traffic\_marking\_policy + +Provides a Cloud Enterprise Network (CEN) Traffic Marking Policy resource. + +For information about Cloud Enterprise Network (CEN) Traffic Marking Policy and how to use it, see [What is Traffic Marking Policy](https://help.aliyun.com/document_detail/419025.html). + +-> **NOTE:** Available in v1.173.0+. + +## Example Usage + +Basic Usage + +```terraform +resource "alicloud_cen_instance" "example" { + cen_instance_name = "example_value" +} + +resource "alicloud_cen_transit_router" "example" { + cen_id = alicloud_cen_instance.example.id + transit_router_name = "example_value" +} + +resource "alicloud_cen_traffic_marking_policy" "example" { + marking_dscp = 1 + priority = 1 + traffic_marking_policy_name = "example_value" + transit_router_id = alicloud_cen_transit_router.example.transit_router_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `description` - (Optional) The description of the Traffic Marking Policy. The description must be 2 to 128 characters in length, and must start with a letter. It can contain digits, underscores (_), and hyphens (-). +* `dry_run` - (Optional) The dry run. +* `marking_dscp` - (Required, ForceNew) The DSCP(Differentiated Services Code Point) of the Traffic Marking Policy. Value range: 0~63. +* `priority` - (Required, ForceNew) The Priority of the Traffic Marking Policy. Value range: 1~100. +* `traffic_marking_policy_name` - (Optional) The name of the Traffic Marking Policy. The name must be 2 to 128 characters in length, and must start with a letter. It can contain digits, underscores (_), and hyphens (-). +* `transit_router_id` - (Required, ForceNew) The ID of the transit router. + +## Attributes Reference + +The following attributes are exported: + +* `id` - ID of the resource, It is formatted to `:`. +* `status` - The status of the resource. +* `traffic_marking_policy_id` - The ID of the Traffic Marking Policy. + +### Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration-0-11/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 6 mins) Used when create the Traffic Marking Policy. +* `delete` - (Defaults to 6 mins) Used when delete the Traffic Marking Policy. +* `update` - (Defaults to 6 mins) Used when update the Traffic Marking Policy. + +## Import + +Cloud Enterprise Network (CEN) Traffic Marking Policy can be imported using the id, e.g. + +``` +$ terraform import alicloud_cen_traffic_marking_policy.example : +``` \ No newline at end of file