|
| 1 | +/* |
| 2 | +Provides a resource to create a antiddos ip. Only support for bgp-multip. |
| 3 | +
|
| 4 | +Example Usage |
| 5 | +
|
| 6 | +```hcl |
| 7 | +resource "tencentcloud_dayu_ddos_ip_attachment_v2" "boundip" { |
| 8 | + id = "bgp-xxxxxx" |
| 9 | + bound_ip_list { |
| 10 | + ip = "1.1.1.1" |
| 11 | + biz_type = "public" |
| 12 | + instance_id = "ins-xxx" |
| 13 | + device_type = "cvm" |
| 14 | + } |
| 15 | +} |
| 16 | +``` |
| 17 | +*/ |
| 18 | +package tencentcloud |
| 19 | + |
| 20 | +import ( |
| 21 | + "context" |
| 22 | + "errors" |
| 23 | + "fmt" |
| 24 | + "log" |
| 25 | + "strings" |
| 26 | + |
| 27 | + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" |
| 28 | + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" |
| 29 | + antiddos "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/antiddos/v20200309" |
| 30 | + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" |
| 31 | +) |
| 32 | + |
| 33 | +func resourceTencentCloudDayuDDosIpAttachmentV2() *schema.Resource { |
| 34 | + return &schema.Resource{ |
| 35 | + Create: resourceTencentCloudDayuDDosIpAttachmentCreateV2, |
| 36 | + Read: resourceTencentCloudDayuDDosIpAttachmentReadV2, |
| 37 | + Delete: resourceTencentCloudDayuDDosIpAttachmentDeleteV2, |
| 38 | + Schema: map[string]*schema.Schema{ |
| 39 | + "bgp_instance_id": { |
| 40 | + Required: true, |
| 41 | + ForceNew: true, |
| 42 | + Type: schema.TypeString, |
| 43 | + Description: "Anti-DDoS instance ID.", |
| 44 | + }, |
| 45 | + |
| 46 | + "bound_ip_list": { |
| 47 | + Optional: true, |
| 48 | + ForceNew: true, |
| 49 | + Type: schema.TypeList, |
| 50 | + Description: "Array of IPs to bind to the Anti-DDoS instance. For Anti-DDoS Pro Single IP instance, the array contains only one IP. If there are no IPs to bind, it is empty; however, either BoundDevList or UnBoundDevList must not be empty.", |
| 51 | + Elem: &schema.Resource{ |
| 52 | + Schema: map[string]*schema.Schema{ |
| 53 | + "ip": { |
| 54 | + Type: schema.TypeString, |
| 55 | + Required: true, |
| 56 | + Description: "IP address.", |
| 57 | + }, |
| 58 | + "biz_type": { |
| 59 | + Type: schema.TypeString, |
| 60 | + Optional: true, |
| 61 | + Description: "Category of product that can be bound. Valid values: public (CVM and CLB), bm (BM), eni (ENI), vpngw (VPN gateway), natgw (NAT gateway), waf (WAF), fpc (financial products), gaap (GAAP), and other (hosted IP). This field is required when you perform binding.", |
| 62 | + }, |
| 63 | + "instance_id": { |
| 64 | + Type: schema.TypeString, |
| 65 | + Optional: true, |
| 66 | + Description: "Anti-DDoS instance ID of the IP. This field is required only when the instance is bound to an IP. For example, this field InstanceId will be eni-* if the instance ID is bound to an ENI IP; none if there is no instance to bind to a managed IP.", |
| 67 | + }, |
| 68 | + "device_type": { |
| 69 | + Type: schema.TypeString, |
| 70 | + Optional: true, |
| 71 | + Description: "Sub-product category. Valid values: cvm (CVM), lb (Load balancer), eni (ENI), vpngw (VPN gateway), natgw (NAT gateway), waf (WAF), fpc (financial products), gaap (GAAP), eip (BM EIP) and other (managed IP). This field is required when you perform binding.", |
| 72 | + }, |
| 73 | + }, |
| 74 | + }, |
| 75 | + }, |
| 76 | + }, |
| 77 | + } |
| 78 | +} |
| 79 | + |
| 80 | +func resourceTencentCloudDayuDDosIpAttachmentCreateV2(d *schema.ResourceData, meta interface{}) error { |
| 81 | + defer logElapsed("resource.tencentcloud_dayu_ddos_ip_attachment_v2.create")() |
| 82 | + defer inconsistentCheck(d, meta)() |
| 83 | + |
| 84 | + logId := getLogId(contextNil) |
| 85 | + ctx := context.WithValue(context.TODO(), logIdKey, logId) |
| 86 | + |
| 87 | + service := AntiddosService{client: meta.(*TencentCloudClient).apiV3Conn} |
| 88 | + |
| 89 | + var bgpInstanceId string |
| 90 | + boundIps := make([]string, 0) |
| 91 | + request := antiddos.NewCreateBoundIPRequest() |
| 92 | + |
| 93 | + request.Business = helper.String(BUSINESS_BGP_MULTIP) |
| 94 | + if v, ok := d.GetOk("bgp_instance_id"); ok { |
| 95 | + bgpInstanceId = v.(string) |
| 96 | + request.Id = helper.String(bgpInstanceId) |
| 97 | + } |
| 98 | + |
| 99 | + if v, ok := d.GetOk("bound_ip_list"); ok { |
| 100 | + for _, item := range v.([]interface{}) { |
| 101 | + dMap := item.(map[string]interface{}) |
| 102 | + boundIpInfo := antiddos.BoundIpInfo{} |
| 103 | + if v, ok := dMap["ip"]; ok { |
| 104 | + boundIps = append(boundIps, v.(string)) |
| 105 | + boundIpInfo.Ip = helper.String(v.(string)) |
| 106 | + } |
| 107 | + if v, ok := dMap["biz_type"]; ok { |
| 108 | + boundIpInfo.BizType = helper.String(v.(string)) |
| 109 | + } |
| 110 | + if v, ok := dMap["instance_id"]; ok { |
| 111 | + boundIpInfo.InstanceId = helper.String(v.(string)) |
| 112 | + } |
| 113 | + if v, ok := dMap["device_type"]; ok { |
| 114 | + boundIpInfo.DeviceType = helper.String(v.(string)) |
| 115 | + } |
| 116 | + boundIpInfo.IspCode = helper.IntUint64(ISP_CODE_BGP) |
| 117 | + request.BoundDevList = append(request.BoundDevList, &boundIpInfo) |
| 118 | + } |
| 119 | + } |
| 120 | + |
| 121 | + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { |
| 122 | + result, e := meta.(*TencentCloudClient).apiV3Conn.UseAntiddosClient().CreateBoundIP(request) |
| 123 | + if e != nil { |
| 124 | + return retryError(e) |
| 125 | + } else { |
| 126 | + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) |
| 127 | + } |
| 128 | + if *result.Response.Success.Code != RESPONSE_SUCCESS_CODE { |
| 129 | + return resource.RetryableError(errors.New("request failed")) |
| 130 | + } |
| 131 | + return nil |
| 132 | + }) |
| 133 | + if err != nil { |
| 134 | + log.Printf("[CRITAL]%s create antiddos boundip failed, reason:%+v", logId, err) |
| 135 | + return err |
| 136 | + } |
| 137 | + err = resource.Retry(writeRetryTimeout, func() *resource.RetryError { |
| 138 | + boundip, e := service.DescribeAntiddosBoundipById(ctx, bgpInstanceId) |
| 139 | + if e != nil { |
| 140 | + return retryError(e) |
| 141 | + } |
| 142 | + if *boundip.BoundStatus == DAYU_BOUNDSTATUS_IDLE { |
| 143 | + return nil |
| 144 | + } |
| 145 | + return resource.RetryableError(errors.New("still building.")) |
| 146 | + |
| 147 | + }) |
| 148 | + if err != nil { |
| 149 | + return err |
| 150 | + } |
| 151 | + |
| 152 | + d.SetId(bgpInstanceId + FILED_SP + strings.Join(boundIps, COMMA_SP)) |
| 153 | + |
| 154 | + return resourceTencentCloudDayuDDosIpAttachmentReadV2(d, meta) |
| 155 | +} |
| 156 | + |
| 157 | +func resourceTencentCloudDayuDDosIpAttachmentReadV2(d *schema.ResourceData, meta interface{}) error { |
| 158 | + defer logElapsed("resource.tencentcloud_dayu_ddos_ip_attachment_v2.read")() |
| 159 | + defer inconsistentCheck(d, meta)() |
| 160 | + |
| 161 | + logId := getLogId(contextNil) |
| 162 | + |
| 163 | + ctx := context.WithValue(context.TODO(), logIdKey, logId) |
| 164 | + |
| 165 | + service := AntiddosService{client: meta.(*TencentCloudClient).apiV3Conn} |
| 166 | + |
| 167 | + idSplit := strings.Split(d.Id(), FILED_SP) |
| 168 | + if len(idSplit) != 2 { |
| 169 | + return fmt.Errorf("id is broken,%s", d.Id()) |
| 170 | + } |
| 171 | + bgpInstanceId := idSplit[0] |
| 172 | + boundIps := idSplit[1] |
| 173 | + boundIpMap := make(map[string]bool) |
| 174 | + for _, boundIp := range strings.Split(boundIps, COMMA_SP) { |
| 175 | + boundIpMap[boundIp] = true |
| 176 | + } |
| 177 | + |
| 178 | + boundip, err := service.DescribeAntiddosBoundipById(ctx, bgpInstanceId) |
| 179 | + if err != nil { |
| 180 | + return err |
| 181 | + } |
| 182 | + |
| 183 | + if boundip == nil { |
| 184 | + d.SetId("") |
| 185 | + log.Printf("resource `AntiddosIp` %s does not exist", d.Id()) |
| 186 | + return nil |
| 187 | + } |
| 188 | + _ = d.Set("bgp_instance_id", bgpInstanceId) |
| 189 | + boundIpList := make([]map[string]interface{}, 0) |
| 190 | + if boundip.EipProductInfos != nil { |
| 191 | + boundIpListItem := make(map[string]interface{}) |
| 192 | + for _, item := range boundip.EipProductInfos { |
| 193 | + if _, ok := boundIpMap[*item.Ip]; !ok { |
| 194 | + continue |
| 195 | + } |
| 196 | + boundIpListItem["ip"] = *item.Ip |
| 197 | + boundIpListItem["biz_type"] = *item.BizType |
| 198 | + boundIpListItem["instance_id"] = *item.InstanceId |
| 199 | + boundIpListItem["device_type"] = *item.DeviceType |
| 200 | + boundIpList = append(boundIpList, boundIpListItem) |
| 201 | + } |
| 202 | + } |
| 203 | + _ = d.Set("bound_ip_list", boundIpList) |
| 204 | + |
| 205 | + return nil |
| 206 | +} |
| 207 | + |
| 208 | +func resourceTencentCloudDayuDDosIpAttachmentDeleteV2(d *schema.ResourceData, meta interface{}) error { |
| 209 | + defer logElapsed("resource.tencentcloud_dayu_ddos_ip_attachment_v2.delete")() |
| 210 | + defer inconsistentCheck(d, meta)() |
| 211 | + |
| 212 | + logId := getLogId(contextNil) |
| 213 | + ctx := context.WithValue(context.TODO(), logIdKey, logId) |
| 214 | + |
| 215 | + service := AntiddosService{client: meta.(*TencentCloudClient).apiV3Conn} |
| 216 | + |
| 217 | + idSplit := strings.Split(d.Id(), FILED_SP) |
| 218 | + if len(idSplit) != 2 { |
| 219 | + return fmt.Errorf("id is broken,%s", d.Id()) |
| 220 | + } |
| 221 | + bgpInstanceId := idSplit[0] |
| 222 | + boundIps := idSplit[1] |
| 223 | + |
| 224 | + request := antiddos.NewCreateBoundIPRequest() |
| 225 | + request.Business = helper.String(BUSINESS_BGP_MULTIP) |
| 226 | + request.Id = helper.String(bgpInstanceId) |
| 227 | + ubBoundDevList := make([]*antiddos.BoundIpInfo, 0) |
| 228 | + for _, boundIp := range strings.Split(boundIps, COMMA_SP) { |
| 229 | + ubBoundDevList = append( |
| 230 | + ubBoundDevList, |
| 231 | + &antiddos.BoundIpInfo{ |
| 232 | + Ip: &boundIp, |
| 233 | + }, |
| 234 | + ) |
| 235 | + } |
| 236 | + request.UnBoundDevList = ubBoundDevList |
| 237 | + |
| 238 | + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { |
| 239 | + result, e := meta.(*TencentCloudClient).apiV3Conn.UseAntiddosClient().CreateBoundIP(request) |
| 240 | + if e != nil { |
| 241 | + return retryError(e) |
| 242 | + } else { |
| 243 | + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) |
| 244 | + } |
| 245 | + if *result.Response.Success.Code != RESPONSE_SUCCESS_CODE { |
| 246 | + return resource.RetryableError(errors.New("request failed")) |
| 247 | + } |
| 248 | + return nil |
| 249 | + }) |
| 250 | + if err != nil { |
| 251 | + log.Printf("[CRITAL]%s create antiddos boundip failed, reason:%+v", logId, err) |
| 252 | + return err |
| 253 | + } |
| 254 | + |
| 255 | + err = resource.Retry(writeRetryTimeout, func() *resource.RetryError { |
| 256 | + boundip, e := service.DescribeAntiddosBoundipById(ctx, bgpInstanceId) |
| 257 | + if e != nil { |
| 258 | + return retryError(e) |
| 259 | + } |
| 260 | + if *boundip.BoundStatus == DAYU_BOUNDSTATUS_IDLE { |
| 261 | + return nil |
| 262 | + } |
| 263 | + return resource.RetryableError(errors.New("still building.")) |
| 264 | + |
| 265 | + }) |
| 266 | + if err != nil { |
| 267 | + return err |
| 268 | + } |
| 269 | + |
| 270 | + return nil |
| 271 | +} |
0 commit comments