github.com/pmcatominey/terraform@v0.7.0-rc2.0.20160708105029-1401a52a5cc5/builtin/providers/cloudstack/resource_cloudstack_vpc.go (about) 1 package cloudstack 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "github.com/hashicorp/terraform/helper/schema" 9 "github.com/xanzy/go-cloudstack/cloudstack" 10 ) 11 12 func resourceCloudStackVPC() *schema.Resource { 13 return &schema.Resource{ 14 Create: resourceCloudStackVPCCreate, 15 Read: resourceCloudStackVPCRead, 16 Update: resourceCloudStackVPCUpdate, 17 Delete: resourceCloudStackVPCDelete, 18 19 Schema: map[string]*schema.Schema{ 20 "name": &schema.Schema{ 21 Type: schema.TypeString, 22 Required: true, 23 }, 24 25 "display_text": &schema.Schema{ 26 Type: schema.TypeString, 27 Optional: true, 28 Computed: true, 29 }, 30 31 "cidr": &schema.Schema{ 32 Type: schema.TypeString, 33 Required: true, 34 ForceNew: true, 35 }, 36 37 "vpc_offering": &schema.Schema{ 38 Type: schema.TypeString, 39 Required: true, 40 ForceNew: true, 41 }, 42 43 "network_domain": &schema.Schema{ 44 Type: schema.TypeString, 45 Optional: true, 46 Computed: true, 47 ForceNew: true, 48 }, 49 50 "project": &schema.Schema{ 51 Type: schema.TypeString, 52 Optional: true, 53 ForceNew: true, 54 }, 55 56 "source_nat_ip": &schema.Schema{ 57 Type: schema.TypeString, 58 Computed: true, 59 }, 60 61 "zone": &schema.Schema{ 62 Type: schema.TypeString, 63 Required: true, 64 ForceNew: true, 65 }, 66 }, 67 } 68 } 69 70 func resourceCloudStackVPCCreate(d *schema.ResourceData, meta interface{}) error { 71 cs := meta.(*cloudstack.CloudStackClient) 72 73 name := d.Get("name").(string) 74 75 // Retrieve the vpc_offering ID 76 vpcofferingid, e := retrieveID(cs, "vpc_offering", d.Get("vpc_offering").(string)) 77 if e != nil { 78 return e.Error() 79 } 80 81 // Retrieve the zone ID 82 zoneid, e := retrieveID(cs, "zone", d.Get("zone").(string)) 83 if e != nil { 84 return e.Error() 85 } 86 87 // Set the display text 88 displaytext, ok := d.GetOk("display_text") 89 if !ok { 90 displaytext = name 91 } 92 93 // Create a new parameter struct 94 p := cs.VPC.NewCreateVPCParams( 95 d.Get("cidr").(string), 96 displaytext.(string), 97 name, 98 vpcofferingid, 99 zoneid, 100 ) 101 102 // If there is a network domain supplied, make sure to add it to the request 103 if networkDomain, ok := d.GetOk("network_domain"); ok { 104 // Set the network domain 105 p.SetNetworkdomain(networkDomain.(string)) 106 } 107 108 // If there is a project supplied, we retrieve and set the project id 109 if err := setProjectid(p, cs, d); err != nil { 110 return err 111 } 112 113 // Create the new VPC 114 r, err := cs.VPC.CreateVPC(p) 115 if err != nil { 116 return fmt.Errorf("Error creating VPC %s: %s", name, err) 117 } 118 119 d.SetId(r.Id) 120 121 return resourceCloudStackVPCRead(d, meta) 122 } 123 124 func resourceCloudStackVPCRead(d *schema.ResourceData, meta interface{}) error { 125 cs := meta.(*cloudstack.CloudStackClient) 126 127 // Get the VPC details 128 v, count, err := cs.VPC.GetVPCByID( 129 d.Id(), 130 cloudstack.WithProject(d.Get("project").(string)), 131 ) 132 if err != nil { 133 if count == 0 { 134 log.Printf( 135 "[DEBUG] VPC %s does no longer exist", d.Get("name").(string)) 136 d.SetId("") 137 return nil 138 } 139 140 return err 141 } 142 143 d.Set("name", v.Name) 144 d.Set("display_text", v.Displaytext) 145 d.Set("cidr", v.Cidr) 146 d.Set("network_domain", v.Networkdomain) 147 148 // Get the VPC offering details 149 o, _, err := cs.VPC.GetVPCOfferingByID(v.Vpcofferingid) 150 if err != nil { 151 return err 152 } 153 154 setValueOrID(d, "vpc_offering", o.Name, v.Vpcofferingid) 155 setValueOrID(d, "project", v.Project, v.Projectid) 156 setValueOrID(d, "zone", v.Zonename, v.Zoneid) 157 158 // Create a new parameter struct 159 p := cs.Address.NewListPublicIpAddressesParams() 160 p.SetVpcid(d.Id()) 161 p.SetIssourcenat(true) 162 163 // If there is a project supplied, we retrieve and set the project id 164 if err := setProjectid(p, cs, d); err != nil { 165 return err 166 } 167 168 // Get the source NAT IP assigned to the VPC 169 l, err := cs.Address.ListPublicIpAddresses(p) 170 if err != nil { 171 return err 172 } 173 174 if l.Count != 1 { 175 return fmt.Errorf("Unexpected number (%d) of source NAT IPs returned", l.Count) 176 } 177 178 d.Set("source_nat_ip", l.PublicIpAddresses[0].Ipaddress) 179 180 return nil 181 } 182 183 func resourceCloudStackVPCUpdate(d *schema.ResourceData, meta interface{}) error { 184 cs := meta.(*cloudstack.CloudStackClient) 185 186 // Check if the name or display text is changed 187 if d.HasChange("name") || d.HasChange("display_text") { 188 // Create a new parameter struct 189 p := cs.VPC.NewUpdateVPCParams(d.Id()) 190 191 // Set the display text 192 displaytext, ok := d.GetOk("display_text") 193 if !ok { 194 displaytext = d.Get("name") 195 } 196 // Set the (new) display text 197 p.SetDisplaytext(displaytext.(string)) 198 199 // Update the VPC 200 _, err := cs.VPC.UpdateVPC(p) 201 if err != nil { 202 return fmt.Errorf( 203 "Error updating VPC %s: %s", d.Get("name").(string), err) 204 } 205 } 206 207 return resourceCloudStackVPCRead(d, meta) 208 } 209 210 func resourceCloudStackVPCDelete(d *schema.ResourceData, meta interface{}) error { 211 cs := meta.(*cloudstack.CloudStackClient) 212 213 // Create a new parameter struct 214 p := cs.VPC.NewDeleteVPCParams(d.Id()) 215 216 // Delete the VPC 217 _, err := cs.VPC.DeleteVPC(p) 218 if err != nil { 219 // This is a very poor way to be told the ID does no longer exist :( 220 if strings.Contains(err.Error(), fmt.Sprintf( 221 "Invalid parameter id value=%s due to incorrect long value format, "+ 222 "or entity does not exist", d.Id())) { 223 return nil 224 } 225 226 return fmt.Errorf("Error deleting VPC %s: %s", d.Get("name").(string), err) 227 } 228 229 return nil 230 }