provider/openstack: Enable Security Group Updates (#14815)

* vendor: Updating Gophercloud for OpenStack Provider

* provider/openstack: Enable Security Group Updates

This commit enables security group names and descriptions to
be updated without causing a recreate.
This commit is contained in:
Joe Topjian 2017-05-25 00:53:26 -06:00 committed by Paul Stack
parent e6b776fedd
commit db47721e15
7 changed files with 120 additions and 13 deletions

View File

@ -204,6 +204,17 @@ func TestAccNetworkingV2Port_updateSecurityGroups(t *testing.T) {
},
resource.TestStep{
Config: testAccNetworkingV2Port_updateSecurityGroups_3,
Check: resource.ComposeTestCheckFunc(
testAccCheckNetworkingV2SubnetExists("openstack_networking_subnet_v2.subnet_1", &subnet),
testAccCheckNetworkingV2NetworkExists("openstack_networking_network_v2.network_1", &network),
testAccCheckNetworkingV2PortExists("openstack_networking_port_v2.port_1", &port),
testAccCheckNetworkingV2SecGroupExists(
"openstack_networking_secgroup_v2.secgroup_1", &security_group),
testAccCheckNetworkingV2PortCountSecurityGroups(&port, 1),
),
},
resource.TestStep{
Config: testAccNetworkingV2Port_updateSecurityGroups_4,
Check: resource.ComposeTestCheckFunc(
testAccCheckNetworkingV2SubnetExists("openstack_networking_subnet_v2.subnet_1", &subnet),
testAccCheckNetworkingV2NetworkExists("openstack_networking_network_v2.network_1", &network),
@ -606,6 +617,37 @@ resource "openstack_networking_subnet_v2" "subnet_1" {
network_id = "${openstack_networking_network_v2.network_1.id}"
}
resource "openstack_networking_secgroup_v2" "secgroup_1" {
name = "security_group_1"
description = "terraform security group acceptance test"
}
resource "openstack_networking_port_v2" "port_1" {
name = "port_1"
admin_state_up = "true"
network_id = "${openstack_networking_network_v2.network_1.id}"
security_group_ids = ["${openstack_networking_secgroup_v2.secgroup_1.id}"]
fixed_ip {
subnet_id = "${openstack_networking_subnet_v2.subnet_1.id}"
ip_address = "192.168.199.23"
}
}
`
const testAccNetworkingV2Port_updateSecurityGroups_4 = `
resource "openstack_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
}
resource "openstack_networking_subnet_v2" "subnet_1" {
name = "subnet_1"
cidr = "192.168.199.0/24"
ip_version = 4
network_id = "${openstack_networking_network_v2.network_1.id}"
}
resource "openstack_networking_secgroup_v2" "secgroup_1" {
name = "security_group"
description = "terraform security group acceptance test"

View File

@ -17,6 +17,7 @@ func resourceNetworkingSecGroupV2() *schema.Resource {
return &schema.Resource{
Create: resourceNetworkingSecGroupV2Create,
Read: resourceNetworkingSecGroupV2Read,
Update: resourceNetworkingSecGroupV2Update,
Delete: resourceNetworkingSecGroupV2Delete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
@ -36,12 +37,10 @@ func resourceNetworkingSecGroupV2() *schema.Resource {
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"tenant_id": &schema.Schema{
@ -121,6 +120,37 @@ func resourceNetworkingSecGroupV2Read(d *schema.ResourceData, meta interface{})
return nil
}
func resourceNetworkingSecGroupV2Update(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
networkingClient, err := config.networkingV2Client(GetRegion(d))
if err != nil {
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
}
var update bool
var updateOpts groups.UpdateOpts
if d.HasChange("name") {
update = true
updateOpts.Name = d.Get("name").(string)
}
if d.HasChange("description") {
update = true
updateOpts.Name = d.Get("description").(string)
}
if update {
log.Printf("[DEBUG] Updating SecGroup %s with options: %#v", d.Id(), updateOpts)
_, err = groups.Update(networkingClient, d.Id(), updateOpts).Extract()
if err != nil {
return fmt.Errorf("Error updating OpenStack SecGroup: %s", err)
}
}
return resourceNetworkingSecGroupV2Read(d, meta)
}
func resourceNetworkingSecGroupV2Delete(d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] Destroy security group: %s", d.Id())

View File

@ -29,6 +29,8 @@ func TestAccNetworkingV2SecGroup_basic(t *testing.T) {
resource.TestStep{
Config: testAccNetworkingV2SecGroup_update,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPtr(
"openstack_networking_secgroup_v2.secgroup_1", "id", &security_group.ID),
resource.TestCheckResourceAttr(
"openstack_networking_secgroup_v2.secgroup_1", "name", "security_group_2"),
),

View File

@ -40,9 +40,9 @@ type CreateOptsBuilder interface {
// CreateOpts contains all the values needed to create a new security group.
type CreateOpts struct {
// Required. Human-readable name for the VIP. Does not have to be unique.
// Required. Human-readable name for the Security Group. Does not have to be unique.
Name string `json:"name" required:"true"`
// Required for admins. Indicates the owner of the VIP.
// Required for admins. Indicates the owner of the Security Group.
TenantID string `json:"tenant_id,omitempty"`
// Optional. Describes the security group.
Description string `json:"description,omitempty"`
@ -64,6 +64,36 @@ func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResul
return
}
type UpdateOptsBuilder interface {
ToSecGroupUpdateMap() (map[string]interface{}, error)
}
// UpdateOpts contains all the values needed to update an existing security group.
type UpdateOpts struct {
// Human-readable name for the Security Group. Does not have to be unique.
Name string `json:"name,omitempty"`
// Optional. Describes the security group.
Description string `json:"description,omitempty"`
}
func (opts UpdateOpts) ToSecGroupUpdateMap() (map[string]interface{}, error) {
return gophercloud.BuildRequestBody(opts, "security_group")
}
// Update is an operation which updates an existing security group.
func Update(c *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
b, err := opts.ToSecGroupUpdateMap()
if err != nil {
r.Err = err
return
}
_, r.Err = c.Put(resourceURL(c, id), b, &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return
}
// Get retrieves a particular security group based on its unique ID.
func Get(c *gophercloud.ServiceClient, id string) (r GetResult) {
_, r.Err = c.Get(resourceURL(c, id), &r.Body, nil)

View File

@ -83,6 +83,11 @@ type CreateResult struct {
commonResult
}
// UpdateResult represents the result of an update operation.
type UpdateResult struct {
commonResult
}
// GetResult represents the result of a get operation.
type GetResult struct {
commonResult

10
vendor/vendor.json vendored
View File

@ -1835,16 +1835,16 @@
"revisionTime": "2017-03-10T01:59:53Z"
},
{
"checksumSHA1": "FKwSMrpQf7b3TcCOQfh+ovoBShA=",
"checksumSHA1": "qabBGU1tfT99h1YXyxO9nGxMghE=",
"path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups",
"revision": "0f64da0e36de86a0ca1a8f2fc1b0570a0d3f7504",
"revisionTime": "2017-03-10T01:59:53Z"
"revision": "3027adb1ce72bc52b87b2decccc7852574b90031",
"revisionTime": "2017-05-24T13:09:59Z"
},
{
"checksumSHA1": "E/5q7DTCoOD15K1KGFXSwFCGDE4=",
"path": "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules",
"revision": "ce1e02c3ccfdb7fab257340dc4d603ec3035fa11",
"revisionTime": "2017-05-08T02:10:49Z"
"revision": "3027adb1ce72bc52b87b2decccc7852574b90031",
"revisionTime": "2017-05-24T13:09:59Z"
},
{
"checksumSHA1": "zKOhFTL5BDZPMC58ZzZkryjskno=",

View File

@ -30,11 +30,9 @@ The following arguments are supported:
`OS_REGION_NAME` environment variable is used. Changing this creates a new
security group.
* `name` - (Required) A unique name for the security group. Changing this
creates a new security group.
* `name` - (Required) A unique name for the security group.
* `description` - (Optional) A unique name for the security group. Changing this
creates a new security group.
* `description` - (Optional) A unique name for the security group.
* `tenant_id` - (Optional) The owner of the security group. Required if admin
wants to create a port for another tenant. Changing this creates a new