|
| 1 | +package ccn |
| 2 | + |
| 3 | +import ( |
| 4 | + "context" |
| 5 | + "fmt" |
| 6 | + "log" |
| 7 | + "strings" |
| 8 | + |
| 9 | + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" |
| 10 | + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" |
| 11 | + |
| 12 | + vpc "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/vpc/v20170312" |
| 13 | + |
| 14 | + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" |
| 15 | + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" |
| 16 | +) |
| 17 | + |
| 18 | +func ResourceTencentCloudCcnAttachmentV2() *schema.Resource { |
| 19 | + return &schema.Resource{ |
| 20 | + Create: resourceTencentCloudCcnAttachmentV2Create, |
| 21 | + Read: resourceTencentCloudCcnAttachmentV2Read, |
| 22 | + Update: resourceTencentCloudCcnAttachmentV2Update, |
| 23 | + Delete: resourceTencentCloudCcnAttachmentV2Delete, |
| 24 | + Importer: &schema.ResourceImporter{ |
| 25 | + State: schema.ImportStatePassthrough, |
| 26 | + }, |
| 27 | + Schema: map[string]*schema.Schema{ |
| 28 | + "ccn_id": { |
| 29 | + Type: schema.TypeString, |
| 30 | + Required: true, |
| 31 | + ForceNew: true, |
| 32 | + Description: "ID of the CCN.", |
| 33 | + }, |
| 34 | + "instance_id": { |
| 35 | + Type: schema.TypeString, |
| 36 | + Required: true, |
| 37 | + ForceNew: true, |
| 38 | + Description: "ID of instance is attached.", |
| 39 | + }, |
| 40 | + "instance_region": { |
| 41 | + Type: schema.TypeString, |
| 42 | + Required: true, |
| 43 | + ForceNew: true, |
| 44 | + Description: "The region that the instance locates at.", |
| 45 | + }, |
| 46 | + "instance_type": { |
| 47 | + Type: schema.TypeString, |
| 48 | + Required: true, |
| 49 | + ValidateFunc: tccommon.ValidateAllowedStringValue([]string{CNN_INSTANCE_TYPE_VPC, CNN_INSTANCE_TYPE_DIRECTCONNECT, CNN_INSTANCE_TYPE_BMVPC, CNN_INSTANCE_TYPE_VPNGW}), |
| 50 | + ForceNew: true, |
| 51 | + Description: "Type of attached instance network, and available values include `VPC`, `DIRECTCONNECT`, `BMVPC` and `VPNGW`. Note: `VPNGW` type is only for whitelist customer now.", |
| 52 | + }, |
| 53 | + "description": { |
| 54 | + Type: schema.TypeString, |
| 55 | + Optional: true, |
| 56 | + Description: "Remark of attachment.", |
| 57 | + }, |
| 58 | + "route_table_id": { |
| 59 | + Type: schema.TypeString, |
| 60 | + Optional: true, |
| 61 | + ForceNew: true, |
| 62 | + Computed: true, |
| 63 | + Description: "Ccn instance route table ID.", |
| 64 | + }, |
| 65 | + "ccn_uin": { |
| 66 | + Type: schema.TypeString, |
| 67 | + Optional: true, |
| 68 | + ForceNew: true, |
| 69 | + Computed: true, |
| 70 | + Description: "Uin of the ccn attached. If not set, which means the uin of this account. This parameter is used with case when attaching ccn of other account to the instance of this account. For now only support instance type `VPC`.", |
| 71 | + }, |
| 72 | + // Computed |
| 73 | + "state": { |
| 74 | + Type: schema.TypeString, |
| 75 | + Computed: true, |
| 76 | + Description: "States of instance is attached. Valid values: `PENDING`, `ACTIVE`, `EXPIRED`, `REJECTED`, `DELETED`, `FAILED`, `ATTACHING`, `DETACHING` and `DETACHFAILED`. `FAILED` means asynchronous forced disassociation after 2 hours. `DETACHFAILED` means asynchronous forced disassociation after 2 hours.", |
| 77 | + }, |
| 78 | + "attached_time": { |
| 79 | + Type: schema.TypeString, |
| 80 | + Computed: true, |
| 81 | + Description: "Time of attaching.", |
| 82 | + }, |
| 83 | + "cidr_block": { |
| 84 | + Type: schema.TypeList, |
| 85 | + Computed: true, |
| 86 | + Elem: &schema.Schema{Type: schema.TypeString}, |
| 87 | + Description: "A network address block of the instance that is attached.", |
| 88 | + }, |
| 89 | + "route_ids": { |
| 90 | + Type: schema.TypeList, |
| 91 | + Computed: true, |
| 92 | + Elem: &schema.Schema{Type: schema.TypeString}, |
| 93 | + Description: "Route id list.", |
| 94 | + }, |
| 95 | + }, |
| 96 | + } |
| 97 | +} |
| 98 | + |
| 99 | +func resourceTencentCloudCcnAttachmentV2Create(d *schema.ResourceData, meta interface{}) error { |
| 100 | + defer tccommon.LogElapsed("resource.tencentcloud_ccn_attachment_v2.create")() |
| 101 | + defer tccommon.InconsistentCheck(d, meta)() |
| 102 | + |
| 103 | + var ( |
| 104 | + logId = tccommon.GetLogId(tccommon.ContextNil) |
| 105 | + ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) |
| 106 | + request = vpc.NewAttachCcnInstancesRequest() |
| 107 | + ccnId string |
| 108 | + instanceId string |
| 109 | + instanceRegion string |
| 110 | + instanceType string |
| 111 | + ) |
| 112 | + |
| 113 | + if v, ok := d.GetOk("ccn_id"); ok { |
| 114 | + request.CcnId = helper.String(v.(string)) |
| 115 | + ccnId = v.(string) |
| 116 | + } |
| 117 | + |
| 118 | + ccnInstance := new(vpc.CcnInstance) |
| 119 | + if v, ok := d.GetOk("instance_id"); ok { |
| 120 | + ccnInstance.InstanceId = helper.String(v.(string)) |
| 121 | + instanceId = v.(string) |
| 122 | + } |
| 123 | + |
| 124 | + if v, ok := d.GetOk("instance_region"); ok { |
| 125 | + ccnInstance.InstanceRegion = helper.String(v.(string)) |
| 126 | + instanceRegion = v.(string) |
| 127 | + } |
| 128 | + |
| 129 | + if v, ok := d.GetOk("instance_type"); ok { |
| 130 | + ccnInstance.InstanceType = helper.String(v.(string)) |
| 131 | + instanceType = v.(string) |
| 132 | + } |
| 133 | + |
| 134 | + if v, ok := d.GetOk("description"); ok { |
| 135 | + ccnInstance.Description = helper.String(v.(string)) |
| 136 | + } |
| 137 | + |
| 138 | + if v, ok := d.GetOk("route_table_id"); ok { |
| 139 | + ccnInstance.RouteTableId = helper.String(v.(string)) |
| 140 | + } |
| 141 | + |
| 142 | + request.Instances = append(request.Instances, ccnInstance) |
| 143 | + |
| 144 | + if v, ok := d.GetOk("ccn_uin"); ok { |
| 145 | + request.CcnUin = helper.String(v.(string)) |
| 146 | + } |
| 147 | + |
| 148 | + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { |
| 149 | + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVpcClient().AttachCcnInstancesWithContext(ctx, request) |
| 150 | + if e != nil { |
| 151 | + return tccommon.RetryError(e) |
| 152 | + } else { |
| 153 | + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) |
| 154 | + } |
| 155 | + |
| 156 | + if result == nil || result.Response == nil { |
| 157 | + return resource.NonRetryableError(fmt.Errorf("Create attach ccn instance failed, Response is nil.")) |
| 158 | + } |
| 159 | + |
| 160 | + return nil |
| 161 | + }) |
| 162 | + |
| 163 | + if err != nil { |
| 164 | + log.Printf("[CRITAL]%s create attach ccn instance failed, reason:%+v", logId, err) |
| 165 | + return err |
| 166 | + } |
| 167 | + |
| 168 | + d.SetId(strings.Join([]string{ccnId, instanceType, instanceRegion, instanceId}, tccommon.FILED_SP)) |
| 169 | + return resourceTencentCloudCcnAttachmentV2Read(d, meta) |
| 170 | +} |
| 171 | + |
| 172 | +func resourceTencentCloudCcnAttachmentV2Read(d *schema.ResourceData, meta interface{}) error { |
| 173 | + defer tccommon.LogElapsed("resource.tencentcloud_ccn_attachment_v2.read")() |
| 174 | + defer tccommon.InconsistentCheck(d, meta)() |
| 175 | + |
| 176 | + var ( |
| 177 | + logId = tccommon.GetLogId(tccommon.ContextNil) |
| 178 | + ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) |
| 179 | + service = VpcService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} |
| 180 | + ) |
| 181 | + |
| 182 | + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) |
| 183 | + if len(idSplit) != 4 { |
| 184 | + return fmt.Errorf("id is broken,%s", d.Id()) |
| 185 | + } |
| 186 | + |
| 187 | + ccnId := idSplit[0] |
| 188 | + instanceType := idSplit[1] |
| 189 | + instanceRegion := idSplit[2] |
| 190 | + instanceId := idSplit[3] |
| 191 | + |
| 192 | + respData, err := service.DescribeCcnAttachedInstanceByFilter(ctx, ccnId, instanceType, instanceRegion, instanceId) |
| 193 | + if err != nil { |
| 194 | + return err |
| 195 | + } |
| 196 | + |
| 197 | + if respData == nil { |
| 198 | + log.Printf("[WARN]%s resource `tencentcloud_ccn_attachment_v2` [%s] not found, please check if it has been deleted.\n", logId, d.Id()) |
| 199 | + d.SetId("") |
| 200 | + return nil |
| 201 | + } |
| 202 | + |
| 203 | + _ = d.Set("ccn_id", ccnId) |
| 204 | + _ = d.Set("instance_id", instanceId) |
| 205 | + _ = d.Set("instance_region", instanceRegion) |
| 206 | + _ = d.Set("instance_type", instanceType) |
| 207 | + |
| 208 | + if respData.Description != nil { |
| 209 | + _ = d.Set("description", respData.Description) |
| 210 | + } |
| 211 | + |
| 212 | + if respData.RouteTableId != nil { |
| 213 | + _ = d.Set("route_table_id", respData.RouteTableId) |
| 214 | + } |
| 215 | + |
| 216 | + if respData.CcnUin != nil { |
| 217 | + _ = d.Set("ccn_uin", respData.CcnUin) |
| 218 | + } |
| 219 | + |
| 220 | + if respData.State != nil { |
| 221 | + _ = d.Set("state", respData.State) |
| 222 | + } |
| 223 | + |
| 224 | + if respData.AttachedTime != nil { |
| 225 | + _ = d.Set("attached_time", respData.AttachedTime) |
| 226 | + } |
| 227 | + |
| 228 | + if respData.CidrBlock != nil { |
| 229 | + _ = d.Set("cidr_block", respData.CidrBlock) |
| 230 | + } |
| 231 | + |
| 232 | + // get route ids |
| 233 | + routeIds := make([]string, 0) |
| 234 | + request := vpc.NewDescribeCcnRoutesRequest() |
| 235 | + request.CcnId = &ccnId |
| 236 | + err = resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { |
| 237 | + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVpcClient().DescribeCcnRoutes(request) |
| 238 | + if e != nil { |
| 239 | + return tccommon.RetryError(e) |
| 240 | + } else { |
| 241 | + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) |
| 242 | + } |
| 243 | + |
| 244 | + if result != nil && result.Response != nil && len(result.Response.RouteSet) > 0 { |
| 245 | + for _, route := range result.Response.RouteSet { |
| 246 | + routeIds = append(routeIds, *route.RouteId) |
| 247 | + } |
| 248 | + } |
| 249 | + |
| 250 | + _ = d.Set("route_ids", routeIds) |
| 251 | + return nil |
| 252 | + }) |
| 253 | + |
| 254 | + if err != nil { |
| 255 | + return err |
| 256 | + } |
| 257 | + |
| 258 | + return nil |
| 259 | +} |
| 260 | + |
| 261 | +func resourceTencentCloudCcnAttachmentV2Update(d *schema.ResourceData, meta interface{}) error { |
| 262 | + defer tccommon.LogElapsed("resource.tencentcloud_ccn_attachment_v2.update")() |
| 263 | + defer tccommon.InconsistentCheck(d, meta)() |
| 264 | + |
| 265 | + var ( |
| 266 | + logId = tccommon.GetLogId(tccommon.ContextNil) |
| 267 | + ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) |
| 268 | + request = vpc.NewModifyCcnAttachedInstancesAttributeRequest() |
| 269 | + ) |
| 270 | + |
| 271 | + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) |
| 272 | + if len(idSplit) != 4 { |
| 273 | + return fmt.Errorf("id is broken,%s", d.Id()) |
| 274 | + } |
| 275 | + |
| 276 | + ccnId := idSplit[0] |
| 277 | + instanceType := idSplit[1] |
| 278 | + instanceRegion := idSplit[2] |
| 279 | + instanceId := idSplit[3] |
| 280 | + |
| 281 | + if d.HasChange("description") { |
| 282 | + request.CcnId = &ccnId |
| 283 | + ccnInstance := new(vpc.CcnInstance) |
| 284 | + ccnInstance.InstanceType = &instanceType |
| 285 | + ccnInstance.InstanceRegion = &instanceRegion |
| 286 | + ccnInstance.InstanceId = &instanceId |
| 287 | + if v, ok := d.GetOk("description"); ok { |
| 288 | + ccnInstance.Description = helper.String(v.(string)) |
| 289 | + } |
| 290 | + |
| 291 | + if v, ok := d.GetOk("route_table_id"); ok { |
| 292 | + ccnInstance.RouteTableId = helper.String(v.(string)) |
| 293 | + } |
| 294 | + |
| 295 | + request.Instances = append(request.Instances, ccnInstance) |
| 296 | + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { |
| 297 | + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVpcClient().ModifyCcnAttachedInstancesAttributeWithContext(ctx, request) |
| 298 | + if e != nil { |
| 299 | + return tccommon.RetryError(e) |
| 300 | + } else { |
| 301 | + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) |
| 302 | + } |
| 303 | + |
| 304 | + return nil |
| 305 | + }) |
| 306 | + |
| 307 | + if err != nil { |
| 308 | + log.Printf("[CRITAL]%s modify ccn instance attribute failed, reason:%+v", logId, err) |
| 309 | + return err |
| 310 | + } |
| 311 | + } |
| 312 | + |
| 313 | + return resourceTencentCloudCcnAttachmentV2Read(d, meta) |
| 314 | +} |
| 315 | + |
| 316 | +func resourceTencentCloudCcnAttachmentV2Delete(d *schema.ResourceData, meta interface{}) error { |
| 317 | + defer tccommon.LogElapsed("resource.tencentcloud_ccn_attachment_v2.delete")() |
| 318 | + defer tccommon.InconsistentCheck(d, meta)() |
| 319 | + |
| 320 | + var ( |
| 321 | + logId = tccommon.GetLogId(tccommon.ContextNil) |
| 322 | + ctx = context.WithValue(context.TODO(), tccommon.LogIdKey, logId) |
| 323 | + request = vpc.NewDetachCcnInstancesRequest() |
| 324 | + ) |
| 325 | + |
| 326 | + idSplit := strings.Split(d.Id(), tccommon.FILED_SP) |
| 327 | + if len(idSplit) != 4 { |
| 328 | + return fmt.Errorf("id is broken,%s", d.Id()) |
| 329 | + } |
| 330 | + |
| 331 | + ccnId := idSplit[0] |
| 332 | + instanceType := idSplit[1] |
| 333 | + instanceRegion := idSplit[2] |
| 334 | + instanceId := idSplit[3] |
| 335 | + |
| 336 | + request.CcnId = &ccnId |
| 337 | + ccnInstance := new(vpc.CcnInstance) |
| 338 | + ccnInstance.InstanceType = &instanceType |
| 339 | + ccnInstance.InstanceRegion = &instanceRegion |
| 340 | + ccnInstance.InstanceId = &instanceId |
| 341 | + request.Instances = append(request.Instances, ccnInstance) |
| 342 | + err := resource.Retry(tccommon.WriteRetryTimeout, func() *resource.RetryError { |
| 343 | + result, e := meta.(tccommon.ProviderMeta).GetAPIV3Conn().UseVpcClient().DetachCcnInstancesWithContext(ctx, request) |
| 344 | + if e != nil { |
| 345 | + return tccommon.RetryError(e) |
| 346 | + } else { |
| 347 | + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) |
| 348 | + } |
| 349 | + |
| 350 | + return nil |
| 351 | + }) |
| 352 | + |
| 353 | + if err != nil { |
| 354 | + log.Printf("[CRITAL]%s detach ccn instance failed, reason:%+v", logId, err) |
| 355 | + return err |
| 356 | + } |
| 357 | + |
| 358 | + return nil |
| 359 | +} |
0 commit comments