@@ -10,7 +10,9 @@ import (
1010 "github.com/hashicorp/terraform/helper/schema"
1111 "github.com/rackspace/gophercloud"
1212 "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
13+ "github.com/rackspace/gophercloud/openstack/compute/v2/extensions/secgroups"
1314 "github.com/rackspace/gophercloud/openstack/compute/v2/servers"
15+ "github.com/rackspace/gophercloud/pagination"
1416)
1517
1618func resourceComputeInstance () * schema.Resource {
@@ -121,10 +123,10 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err
121123 var createOpts servers.CreateOptsBuilder
122124
123125 serverCreateOpts := & servers.CreateOpts {
124- Name : d .Get ("name" ).(string ),
125- ImageRef : d .Get ("image_ref" ).(string ),
126- FlavorRef : d .Get ("flavor_ref" ).(string ),
127- // SecurityGroups []string
126+ Name : d .Get ("name" ).(string ),
127+ ImageRef : d .Get ("image_ref" ).(string ),
128+ FlavorRef : d .Get ("flavor_ref" ).(string ),
129+ SecurityGroups : resourceInstanceSecGroups ( d ),
128130 AvailabilityZone : d .Get ("availability_zone" ).(string ),
129131 Networks : resourceInstanceNetworks (d ),
130132 Metadata : resourceInstanceMetadata (d ),
@@ -214,6 +216,22 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
214216 })
215217
216218 d .Set ("metadata" , server .Metadata )
219+
220+ var currentSG []string
221+ err = secgroups .ListByServer (osClient , d .Id ()).EachPage (func (page pagination.Page ) (bool , error ) {
222+ secGrpList , err := secgroups .ExtractSecurityGroups (page )
223+ if err != nil {
224+ return false , fmt .Errorf ("Error setting security groups for OpenStack server: %s" , err )
225+ }
226+
227+ for _ , sg := range secGrpList {
228+ currentSG = append (currentSG , sg .Name )
229+ }
230+
231+ return true , nil
232+ })
233+ d .Set ("security_groups" , currentSG )
234+
217235 newFlavor , ok := server .Flavor ["id" ].(string )
218236 if ! ok {
219237 return fmt .Errorf ("Error setting OpenStack server's flavor: %v" , newFlavor )
@@ -263,6 +281,33 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err
263281 }
264282 }
265283
284+ if d .HasChange ("security_groups" ) {
285+ oldSGRaw , newSGRaw := d .GetChange ("security_groups" )
286+ oldSGSet , newSGSet := oldSGRaw .(* schema.Set ), newSGRaw .(* schema.Set )
287+ secgroupsToAdd := newSGSet .Difference (oldSGSet )
288+ secgroupsToRemove := oldSGSet .Difference (newSGSet )
289+
290+ log .Printf ("[DEBUG] Security groups to add: %v" , secgroupsToAdd )
291+
292+ log .Printf ("[DEBUG] Security groups to remove: %v" , secgroupsToRemove )
293+
294+ for _ , g := range secgroupsToAdd .List () {
295+ err := secgroups .AddServerToGroup (osClient , d .Id (), g .(string )).ExtractErr ()
296+ if err != nil {
297+ return fmt .Errorf ("Error adding security group to OpenStack server (%s): %s" , d .Id (), err )
298+ }
299+ log .Printf ("[DEBUG] Added security group (%s) to instance (%s)" , g .(string ), d .Id ())
300+ }
301+
302+ for _ , g := range secgroupsToRemove .List () {
303+ err := secgroups .RemoveServerFromGroup (osClient , d .Id (), g .(string )).ExtractErr ()
304+ if err != nil {
305+ return fmt .Errorf ("Error removing security group from OpenStack server (%s): %s" , d .Id (), err )
306+ }
307+ log .Printf ("[DEBUG] Removed security group (%s) from instance (%s)" , g .(string ), d .Id ())
308+ }
309+ }
310+
266311 if d .HasChange ("flavor_ref" ) {
267312 resizeOpts := & servers.ResizeOpts {
268313 FlavorRef : d .Get ("flavor_ref" ).(string ),
@@ -358,6 +403,15 @@ func ServerStateRefreshFunc(client *gophercloud.ServiceClient, instanceID string
358403 }
359404}
360405
406+ func resourceInstanceSecGroups (d * schema.ResourceData ) []string {
407+ rawSecGroups := d .Get ("security_groups" ).(* schema.Set )
408+ secgroups := make ([]string , rawSecGroups .Len ())
409+ for i , raw := range rawSecGroups .List () {
410+ secgroups [i ] = raw .(string )
411+ }
412+ return secgroups
413+ }
414+
361415func resourceInstanceNetworks (d * schema.ResourceData ) []servers.Network {
362416 rawNetworks := d .Get ("networks" ).([]interface {})
363417 networks := make ([]servers.Network , len (rawNetworks ))
0 commit comments