github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/alicloud/resource_alicloud_nat_gateway.go (about) 1 package alicloud 2 3 import ( 4 "fmt" 5 6 "github.com/denverdino/aliyungo/common" 7 "github.com/denverdino/aliyungo/ecs" 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 "log" 11 "strconv" 12 "strings" 13 "time" 14 ) 15 16 func resourceAliyunNatGateway() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceAliyunNatGatewayCreate, 19 Read: resourceAliyunNatGatewayRead, 20 Update: resourceAliyunNatGatewayUpdate, 21 Delete: resourceAliyunNatGatewayDelete, 22 23 Schema: map[string]*schema.Schema{ 24 "vpc_id": &schema.Schema{ 25 Type: schema.TypeString, 26 Required: true, 27 ForceNew: true, 28 }, 29 "spec": &schema.Schema{ 30 Type: schema.TypeString, 31 Required: true, 32 }, 33 "name": &schema.Schema{ 34 Type: schema.TypeString, 35 Optional: true, 36 Computed: true, 37 }, 38 "description": &schema.Schema{ 39 Type: schema.TypeString, 40 Optional: true, 41 }, 42 43 "bandwidth_package_ids": &schema.Schema{ 44 Type: schema.TypeString, 45 Computed: true, 46 }, 47 48 "snat_table_ids": &schema.Schema{ 49 Type: schema.TypeString, 50 Computed: true, 51 }, 52 53 "forward_table_ids": &schema.Schema{ 54 Type: schema.TypeString, 55 Computed: true, 56 }, 57 58 "bandwidth_packages": &schema.Schema{ 59 Type: schema.TypeList, 60 Elem: &schema.Resource{ 61 Schema: map[string]*schema.Schema{ 62 "ip_count": &schema.Schema{ 63 Type: schema.TypeInt, 64 Required: true, 65 }, 66 "bandwidth": &schema.Schema{ 67 Type: schema.TypeInt, 68 Required: true, 69 }, 70 "zone": &schema.Schema{ 71 Type: schema.TypeString, 72 Optional: true, 73 }, 74 "public_ip_addresses": &schema.Schema{ 75 Type: schema.TypeString, 76 Computed: true, 77 }, 78 }, 79 }, 80 Required: true, 81 MaxItems: 4, 82 }, 83 }, 84 } 85 } 86 87 func resourceAliyunNatGatewayCreate(d *schema.ResourceData, meta interface{}) error { 88 conn := meta.(*AliyunClient).vpcconn 89 90 args := &ecs.CreateNatGatewayArgs{ 91 RegionId: getRegion(d, meta), 92 VpcId: d.Get("vpc_id").(string), 93 Spec: d.Get("spec").(string), 94 } 95 96 bandwidthPackages := d.Get("bandwidth_packages").([]interface{}) 97 98 bandwidthPackageTypes := []ecs.BandwidthPackageType{} 99 100 for _, e := range bandwidthPackages { 101 pack := e.(map[string]interface{}) 102 bandwidthPackage := ecs.BandwidthPackageType{ 103 IpCount: pack["ip_count"].(int), 104 Bandwidth: pack["bandwidth"].(int), 105 } 106 if pack["zone"].(string) != "" { 107 bandwidthPackage.Zone = pack["zone"].(string) 108 } 109 110 bandwidthPackageTypes = append(bandwidthPackageTypes, bandwidthPackage) 111 } 112 113 args.BandwidthPackage = bandwidthPackageTypes 114 115 var name string 116 if v, ok := d.GetOk("name"); ok { 117 name = v.(string) 118 } 119 120 args.Name = name 121 122 if v, ok := d.GetOk("description"); ok { 123 args.Description = v.(string) 124 } 125 resp, err := conn.CreateNatGateway(args) 126 if err != nil { 127 return fmt.Errorf("CreateNatGateway got error: %#v", err) 128 } 129 130 d.SetId(resp.NatGatewayId) 131 132 return resourceAliyunNatGatewayRead(d, meta) 133 } 134 135 func resourceAliyunNatGatewayRead(d *schema.ResourceData, meta interface{}) error { 136 137 client := meta.(*AliyunClient) 138 139 natGateway, err := client.DescribeNatGateway(d.Id()) 140 if err != nil { 141 if notFoundError(err) { 142 d.SetId("") 143 return nil 144 } 145 return err 146 } 147 148 d.Set("name", natGateway.Name) 149 d.Set("spec", natGateway.Spec) 150 d.Set("bandwidth_package_ids", strings.Join(natGateway.BandwidthPackageIds.BandwidthPackageId, ",")) 151 d.Set("snat_table_ids", strings.Join(natGateway.SnatTableIds.SnatTableId, ",")) 152 d.Set("forward_table_ids", strings.Join(natGateway.ForwardTableIds.ForwardTableId, ",")) 153 d.Set("description", natGateway.Description) 154 d.Set("vpc_id", natGateway.VpcId) 155 bindWidthPackages, err := flattenBandWidthPackages(natGateway.BandwidthPackageIds.BandwidthPackageId, meta, d) 156 if err != nil { 157 log.Printf("[ERROR] bindWidthPackages flattenBandWidthPackages failed. natgateway id is %#v", d.Id()) 158 } else { 159 d.Set("bandwidth_packages", bindWidthPackages) 160 } 161 162 return nil 163 } 164 165 func resourceAliyunNatGatewayUpdate(d *schema.ResourceData, meta interface{}) error { 166 167 client := meta.(*AliyunClient) 168 conn := client.vpcconn 169 170 natGateway, err := client.DescribeNatGateway(d.Id()) 171 if err != nil { 172 return err 173 } 174 175 d.Partial(true) 176 attributeUpdate := false 177 args := &ecs.ModifyNatGatewayAttributeArgs{ 178 RegionId: natGateway.RegionId, 179 NatGatewayId: natGateway.NatGatewayId, 180 } 181 182 if d.HasChange("name") { 183 d.SetPartial("name") 184 var name string 185 if v, ok := d.GetOk("name"); ok { 186 name = v.(string) 187 } else { 188 return fmt.Errorf("cann't change name to empty string") 189 } 190 args.Name = name 191 192 attributeUpdate = true 193 } 194 195 if d.HasChange("description") { 196 d.SetPartial("description") 197 var description string 198 if v, ok := d.GetOk("description"); ok { 199 description = v.(string) 200 } else { 201 return fmt.Errorf("can to change description to empty string") 202 } 203 204 args.Description = description 205 206 attributeUpdate = true 207 } 208 209 if attributeUpdate { 210 if err := conn.ModifyNatGatewayAttribute(args); err != nil { 211 return err 212 } 213 } 214 215 if d.HasChange("spec") { 216 d.SetPartial("spec") 217 var spec ecs.NatGatewaySpec 218 if v, ok := d.GetOk("spec"); ok { 219 spec = ecs.NatGatewaySpec(v.(string)) 220 } else { 221 // set default to small spec 222 spec = ecs.NatGatewaySmallSpec 223 } 224 225 args := &ecs.ModifyNatGatewaySpecArgs{ 226 RegionId: natGateway.RegionId, 227 NatGatewayId: natGateway.NatGatewayId, 228 Spec: spec, 229 } 230 231 err := conn.ModifyNatGatewaySpec(args) 232 if err != nil { 233 return fmt.Errorf("%#v %#v", err, *args) 234 } 235 236 } 237 d.Partial(false) 238 239 return resourceAliyunNatGatewayRead(d, meta) 240 } 241 242 func resourceAliyunNatGatewayDelete(d *schema.ResourceData, meta interface{}) error { 243 244 client := meta.(*AliyunClient) 245 conn := client.vpcconn 246 247 return resource.Retry(5*time.Minute, func() *resource.RetryError { 248 249 packages, err := conn.DescribeBandwidthPackages(&ecs.DescribeBandwidthPackagesArgs{ 250 RegionId: getRegion(d, meta), 251 NatGatewayId: d.Id(), 252 }) 253 if err != nil { 254 log.Printf("[ERROR] Describe bandwidth package is failed, natGateway Id: %s", d.Id()) 255 return resource.NonRetryableError(err) 256 } 257 258 retry := false 259 for _, pack := range packages { 260 err = conn.DeleteBandwidthPackage(&ecs.DeleteBandwidthPackageArgs{ 261 RegionId: getRegion(d, meta), 262 BandwidthPackageId: pack.BandwidthPackageId, 263 }) 264 265 if err != nil { 266 er, _ := err.(*common.Error) 267 if er.ErrorResponse.Code == NatGatewayInvalidRegionId { 268 log.Printf("[ERROR] Delete bandwidth package is failed, bandwidthPackageId: %#v", pack.BandwidthPackageId) 269 return resource.NonRetryableError(err) 270 } 271 retry = true 272 } 273 } 274 275 if retry { 276 return resource.RetryableError(fmt.Errorf("Bandwidth package in use - trying again while it is deleted.")) 277 } 278 279 args := &ecs.DeleteNatGatewayArgs{ 280 RegionId: getRegion(d, meta), 281 NatGatewayId: d.Id(), 282 } 283 284 err = conn.DeleteNatGateway(args) 285 if err != nil { 286 er, _ := err.(*common.Error) 287 if er.ErrorResponse.Code == DependencyViolationBandwidthPackages { 288 return resource.RetryableError(fmt.Errorf("NatGateway in use - trying again while it is deleted.")) 289 } 290 } 291 292 describeArgs := &ecs.DescribeNatGatewaysArgs{ 293 RegionId: getRegion(d, meta), 294 NatGatewayId: d.Id(), 295 } 296 gw, _, gwErr := conn.DescribeNatGateways(describeArgs) 297 298 if gwErr != nil { 299 log.Printf("[ERROR] Describe NatGateways failed.") 300 return resource.NonRetryableError(gwErr) 301 } else if gw == nil || len(gw) < 1 { 302 return nil 303 } 304 305 return resource.RetryableError(fmt.Errorf("NatGateway in use - trying again while it is deleted.")) 306 }) 307 } 308 309 func flattenBandWidthPackages(bandWidthPackageIds []string, meta interface{}, d *schema.ResourceData) ([]map[string]interface{}, error) { 310 311 packageLen := len(bandWidthPackageIds) 312 result := make([]map[string]interface{}, 0, packageLen) 313 314 for i := packageLen - 1; i >= 0; i-- { 315 packageId := bandWidthPackageIds[i] 316 packages, err := getPackages(packageId, meta, d) 317 if err != nil { 318 log.Printf("[ERROR] NatGateways getPackages failed. packageId is %#v", packageId) 319 return result, err 320 } 321 ipAddress := flattenPackPublicIp(packages.PublicIpAddresses.PublicIpAddresse) 322 ipCont, ipContErr := strconv.Atoi(packages.IpCount) 323 bandWidth, bandWidthErr := strconv.Atoi(packages.Bandwidth) 324 if ipContErr != nil { 325 log.Printf("[ERROR] NatGateways getPackages failed: ipCont convert error. packageId is %#v", packageId) 326 return result, ipContErr 327 } 328 if bandWidthErr != nil { 329 log.Printf("[ERROR] NatGateways getPackages failed: bandWidthErr convert error. packageId is %#v", packageId) 330 return result, bandWidthErr 331 } 332 l := map[string]interface{}{ 333 "ip_count": ipCont, 334 "bandwidth": bandWidth, 335 "zone": packages.ZoneId, 336 "public_ip_addresses": ipAddress, 337 } 338 result = append(result, l) 339 } 340 return result, nil 341 } 342 343 func getPackages(packageId string, meta interface{}, d *schema.ResourceData) (*ecs.DescribeBandwidthPackageType, error) { 344 client := meta.(*AliyunClient) 345 conn := client.vpcconn 346 packages, err := conn.DescribeBandwidthPackages(&ecs.DescribeBandwidthPackagesArgs{ 347 RegionId: getRegion(d, meta), 348 BandwidthPackageId: packageId, 349 }) 350 351 if err != nil { 352 log.Printf("[ERROR] Describe bandwidth package is failed, BandwidthPackageId Id: %s", packageId) 353 return nil, err 354 } 355 356 if len(packages) == 0 { 357 return nil, common.GetClientErrorFromString(InstanceNotfound) 358 } 359 360 return &packages[0], nil 361 362 } 363 364 func flattenPackPublicIp(publicIpAddressList []ecs.PublicIpAddresseType) string { 365 var result []string 366 367 for _, publicIpAddresses := range publicIpAddressList { 368 ipAddress := publicIpAddresses.IpAddress 369 result = append(result, ipAddress) 370 } 371 372 return strings.Join(result, ",") 373 }