diff --git a/builtin/providers/openstack/provider.go b/builtin/providers/openstack/provider.go index 7454a55c36..8b72ba22a6 100644 --- a/builtin/providers/openstack/provider.go +++ b/builtin/providers/openstack/provider.go @@ -101,6 +101,8 @@ func Provider() terraform.ResourceProvider { "openstack_networking_router_v2": resourceNetworkingRouterV2(), "openstack_networking_router_interface_v2": resourceNetworkingRouterInterfaceV2(), "openstack_networking_router_route_v2": resourceNetworkingRouterRouteV2(), + "openstack_networking_secgroup_v2": resourceNetworkingSecGroupV2(), + "openstack_networking_secgroup_rule_v2": resourceNetworkingSecGroupRuleV2(), "openstack_objectstorage_container_v1": resourceObjectStorageContainerV1(), }, diff --git a/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2.go b/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2.go new file mode 100644 index 0000000000..598813a389 --- /dev/null +++ b/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2.go @@ -0,0 +1,209 @@ +package openstack + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules" +) + +func resourceNetworkingSecGroupRuleV2() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkingSecGroupRuleV2Create, + Read: resourceNetworkingSecGroupRuleV2Read, + Delete: resourceNetworkingSecGroupRuleV2Delete, + + Schema: map[string]*schema.Schema{ + "region": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), + }, + "direction": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "ethertype": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "port_range_min": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Computed: true, + }, + "port_range_max": &schema.Schema{ + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Computed: true, + }, + "protocol": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "remote_group_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "remote_ip_prefix": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "security_group_id": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "tenant_id": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + }, + } +} + +func resourceNetworkingSecGroupRuleV2Create(d *schema.ResourceData, meta interface{}) error { + + config := meta.(*Config) + networkingClient, err := config.networkingV2Client(d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error creating OpenStack networking client: %s", err) + } + + portRangeMin := d.Get("port_range_min").(int) + portRangeMax := d.Get("port_range_max").(int) + protocol := d.Get("protocol").(string) + + if protocol == "" { + if portRangeMin != 0 || portRangeMax != 0 { + return fmt.Errorf("A protocol must be specified when using port_range_min and port_range_max") + } + } + + opts := rules.CreateOpts{ + Direction: d.Get("direction").(string), + EtherType: d.Get("ethertype").(string), + SecGroupID: d.Get("security_group_id").(string), + PortRangeMin: d.Get("port_range_min").(int), + PortRangeMax: d.Get("port_range_max").(int), + Protocol: d.Get("protocol").(string), + RemoteGroupID: d.Get("remote_group_id").(string), + RemoteIPPrefix: d.Get("remote_ip_prefix").(string), + TenantID: d.Get("tenant_id").(string), + } + + log.Printf("[DEBUG] Create OpenStack Neutron security group: %#v", opts) + + security_group_rule, err := rules.Create(networkingClient, opts).Extract() + if err != nil { + return err + } + + log.Printf("[DEBUG] OpenStack Neutron Security Group Rule created: %#v", security_group_rule) + + d.SetId(security_group_rule.ID) + + return resourceNetworkingSecGroupRuleV2Read(d, meta) +} + +func resourceNetworkingSecGroupRuleV2Read(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] Retrieve information about security group rule: %s", d.Id()) + + config := meta.(*Config) + networkingClient, err := config.networkingV2Client(d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error creating OpenStack networking client: %s", err) + } + + security_group_rule, err := rules.Get(networkingClient, d.Id()).Extract() + + if err != nil { + return CheckDeleted(d, err, "OpenStack Security Group Rule") + } + + d.Set("protocol", security_group_rule.Protocol) + d.Set("port_range_min", security_group_rule.PortRangeMin) + d.Set("port_range_max", security_group_rule.PortRangeMax) + d.Set("remote_group_id", security_group_rule.RemoteGroupID) + d.Set("remote_ip_prefix", security_group_rule.RemoteIPPrefix) + d.Set("tenant_id", security_group_rule.TenantID) + return nil +} + +func resourceNetworkingSecGroupRuleV2Delete(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] Destroy security group rule: %s", d.Id()) + + config := meta.(*Config) + networkingClient, err := config.networkingV2Client(d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error creating OpenStack networking client: %s", err) + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{"ACTIVE"}, + Target: []string{"DELETED"}, + Refresh: waitForSecGroupRuleDelete(networkingClient, d.Id()), + Timeout: 2 * time.Minute, + Delay: 5 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, err = stateConf.WaitForState() + if err != nil { + return fmt.Errorf("Error deleting OpenStack Neutron Security Group Rule: %s", err) + } + + d.SetId("") + return err +} + +func waitForSecGroupRuleDelete(networkingClient *gophercloud.ServiceClient, secGroupRuleId string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + log.Printf("[DEBUG] Attempting to delete OpenStack Security Group Rule %s.\n", secGroupRuleId) + + r, err := rules.Get(networkingClient, secGroupRuleId).Extract() + if err != nil { + errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) + if !ok { + return r, "ACTIVE", err + } + if errCode.Actual == 404 { + log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId) + return r, "DELETED", nil + } + } + + err = rules.Delete(networkingClient, secGroupRuleId).ExtractErr() + if err != nil { + errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) + if !ok { + return r, "ACTIVE", err + } + if errCode.Actual == 404 { + log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId) + return r, "DELETED", nil + } + } + + log.Printf("[DEBUG] OpenStack Neutron Security Group Rule %s still active.\n", secGroupRuleId) + return r, "ACTIVE", nil + } +} diff --git a/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2_test.go b/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2_test.go new file mode 100644 index 0000000000..5ea0cc3cd4 --- /dev/null +++ b/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2_test.go @@ -0,0 +1,117 @@ +package openstack + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups" + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/rules" +) + +func TestAccNetworkingV2SecGroupRule_basic(t *testing.T) { + var security_group_1 groups.SecGroup + var security_group_2 groups.SecGroup + var security_group_rule_1 rules.SecGroupRule + var security_group_rule_2 rules.SecGroupRule + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNetworkingV2SecGroupRuleDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccNetworkingV2SecGroupRule_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckNetworkingV2SecGroupExists(t, "openstack_networking_secgroup_v2.sg_foo", &security_group_1), + testAccCheckNetworkingV2SecGroupExists(t, "openstack_networking_secgroup_v2.sg_bar", &security_group_2), + testAccCheckNetworkingV2SecGroupRuleExists(t, "openstack_networking_secgroup_rule_v2.sr_foo", &security_group_rule_1), + testAccCheckNetworkingV2SecGroupRuleExists(t, "openstack_networking_secgroup_rule_v2.sr_bar", &security_group_rule_2), + ), + }, + }, + }) +} + +func testAccCheckNetworkingV2SecGroupRuleDestroy(s *terraform.State) error { + config := testAccProvider.Meta().(*Config) + networkingClient, err := config.networkingV2Client(OS_REGION_NAME) + if err != nil { + return fmt.Errorf("(testAccCheckNetworkingV2SecGroupRuleDestroy) Error creating OpenStack networking client: %s", err) + } + + for _, rs := range s.RootModule().Resources { + if rs.Type != "openstack_networking_secgroup_rule_v2" { + continue + } + + _, err := rules.Get(networkingClient, rs.Primary.ID).Extract() + if err == nil { + return fmt.Errorf("Security group rule still exists") + } + } + + return nil +} + +func testAccCheckNetworkingV2SecGroupRuleExists(t *testing.T, n string, security_group_rule *rules.SecGroupRule) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + networkingClient, err := config.networkingV2Client(OS_REGION_NAME) + if err != nil { + return fmt.Errorf("(testAccCheckNetworkingV2SecGroupRuleExists) Error creating OpenStack networking client: %s", err) + } + + found, err := rules.Get(networkingClient, rs.Primary.ID).Extract() + if err != nil { + return err + } + + if found.ID != rs.Primary.ID { + return fmt.Errorf("Security group rule not found") + } + + *security_group_rule = *found + + return nil + } +} + +var testAccNetworkingV2SecGroupRule_basic = fmt.Sprintf(` + resource "openstack_networking_secgroup_v2" "sg_foo" { + name = "security_group_1" + description = "terraform security group rule acceptance test" + } + resource "openstack_networking_secgroup_v2" "sg_bar" { + name = "security_group_2" + description = "terraform security group rule acceptance test" + } + resource "openstack_networking_secgroup_rule_v2" "sr_foo" { + direction = "ingress" + ethertype = "IPv4" + port_range_max = 22 + port_range_min = 22 + protocol = "tcp" + remote_ip_prefix = "0.0.0.0/0" + security_group_id = "${openstack_networking_secgroup_v2.sg_foo.id}" + } + resource "openstack_networking_secgroup_rule_v2" "sr_bar" { + direction = "ingress" + ethertype = "IPv4" + port_range_max = 80 + port_range_min = 80 + protocol = "tcp" + remote_group_id = "${openstack_networking_secgroup_v2.sg_foo.id}" + security_group_id = "${openstack_networking_secgroup_v2.sg_bar.id}" + }`) diff --git a/builtin/providers/openstack/resource_openstack_networking_secgroup_v2.go b/builtin/providers/openstack/resource_openstack_networking_secgroup_v2.go new file mode 100644 index 0000000000..f08e9affc4 --- /dev/null +++ b/builtin/providers/openstack/resource_openstack_networking_secgroup_v2.go @@ -0,0 +1,155 @@ +package openstack + +import ( + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + + "github.com/rackspace/gophercloud" + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups" +) + +func resourceNetworkingSecGroupV2() *schema.Resource { + return &schema.Resource{ + Create: resourceNetworkingSecGroupV2Create, + Read: resourceNetworkingSecGroupV2Read, + Delete: resourceNetworkingSecGroupV2Delete, + + Schema: map[string]*schema.Schema{ + "region": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), + }, + "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{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + }, + } +} + +func resourceNetworkingSecGroupV2Create(d *schema.ResourceData, meta interface{}) error { + + config := meta.(*Config) + networkingClient, err := config.networkingV2Client(d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error creating OpenStack networking client: %s", err) + } + + opts := groups.CreateOpts{ + Name: d.Get("name").(string), + Description: d.Get("description").(string), + TenantID: d.Get("tenant_id").(string), + } + + log.Printf("[DEBUG] Create OpenStack Neutron Security Group: %#v", opts) + + security_group, err := groups.Create(networkingClient, opts).Extract() + if err != nil { + return err + } + + log.Printf("[DEBUG] OpenStack Neutron Security Group created: %#v", security_group) + + d.SetId(security_group.ID) + + return resourceNetworkingSecGroupV2Read(d, meta) +} + +func resourceNetworkingSecGroupV2Read(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] Retrieve information about security group: %s", d.Id()) + + config := meta.(*Config) + networkingClient, err := config.networkingV2Client(d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error creating OpenStack networking client: %s", err) + } + + security_group, err := groups.Get(networkingClient, d.Id()).Extract() + + if err != nil { + return CheckDeleted(d, err, "OpenStack Neutron Security group") + } + + d.Set("description", security_group.Description) + d.Set("tenant_id", security_group.TenantID) + return nil +} + +func resourceNetworkingSecGroupV2Delete(d *schema.ResourceData, meta interface{}) error { + log.Printf("[DEBUG] Destroy security group: %s", d.Id()) + + config := meta.(*Config) + networkingClient, err := config.networkingV2Client(d.Get("region").(string)) + if err != nil { + return fmt.Errorf("Error creating OpenStack networking client: %s", err) + } + + stateConf := &resource.StateChangeConf{ + Pending: []string{"ACTIVE"}, + Target: []string{"DELETED"}, + Refresh: waitForSecGroupDelete(networkingClient, d.Id()), + Timeout: 2 * time.Minute, + Delay: 5 * time.Second, + MinTimeout: 3 * time.Second, + } + + _, err = stateConf.WaitForState() + if err != nil { + return fmt.Errorf("Error deleting OpenStack Neutron Security Group: %s", err) + } + + d.SetId("") + return err +} + +func waitForSecGroupDelete(networkingClient *gophercloud.ServiceClient, secGroupId string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + log.Printf("[DEBUG] Attempting to delete OpenStack Security Group %s.\n", secGroupId) + + r, err := groups.Get(networkingClient, secGroupId).Extract() + if err != nil { + errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) + if !ok { + return r, "ACTIVE", err + } + if errCode.Actual == 404 { + log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group %s", secGroupId) + return r, "DELETED", nil + } + } + + err = groups.Delete(networkingClient, secGroupId).ExtractErr() + if err != nil { + errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError) + if !ok { + return r, "ACTIVE", err + } + if errCode.Actual == 404 { + log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group %s", secGroupId) + return r, "DELETED", nil + } + } + + log.Printf("[DEBUG] OpenStack Neutron Security Group %s still active.\n", secGroupId) + return r, "ACTIVE", nil + } +} diff --git a/builtin/providers/openstack/resource_openstack_networking_secgroup_v2_test.go b/builtin/providers/openstack/resource_openstack_networking_secgroup_v2_test.go new file mode 100644 index 0000000000..198d74a5c2 --- /dev/null +++ b/builtin/providers/openstack/resource_openstack_networking_secgroup_v2_test.go @@ -0,0 +1,100 @@ +package openstack + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + + "github.com/rackspace/gophercloud/openstack/networking/v2/extensions/security/groups" +) + +func TestAccNetworkingV2SecGroup_basic(t *testing.T) { + var security_group groups.SecGroup + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckNetworkingV2SecGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccNetworkingV2SecGroup_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckNetworkingV2SecGroupExists(t, "openstack_networking_secgroup_v2.foo", &security_group), + ), + }, + resource.TestStep{ + Config: testAccNetworkingV2SecGroup_update, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("openstack_networking_secgroup_v2.foo", "name", "security_group_2"), + ), + }, + }, + }) +} + +func testAccCheckNetworkingV2SecGroupDestroy(s *terraform.State) error { + config := testAccProvider.Meta().(*Config) + networkingClient, err := config.networkingV2Client(OS_REGION_NAME) + if err != nil { + return fmt.Errorf("(testAccCheckNetworkingV2SecGroupDestroy) Error creating OpenStack networking client: %s", err) + } + + for _, rs := range s.RootModule().Resources { + if rs.Type != "openstack_networking_secgroup_v2" { + continue + } + + _, err := groups.Get(networkingClient, rs.Primary.ID).Extract() + if err == nil { + return fmt.Errorf("Security group still exists") + } + } + + return nil +} + +func testAccCheckNetworkingV2SecGroupExists(t *testing.T, n string, security_group *groups.SecGroup) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := testAccProvider.Meta().(*Config) + networkingClient, err := config.networkingV2Client(OS_REGION_NAME) + if err != nil { + return fmt.Errorf("(testAccCheckNetworkingV2SecGroupExists) Error creating OpenStack networking client: %s", err) + } + + found, err := groups.Get(networkingClient, rs.Primary.ID).Extract() + if err != nil { + return err + } + + if found.ID != rs.Primary.ID { + return fmt.Errorf("Security group not found") + } + + *security_group = *found + + return nil + } +} + +var testAccNetworkingV2SecGroup_basic = fmt.Sprintf(` + resource "openstack_networking_secgroup_v2" "foo" { + name = "security_group" + description = "terraform security group acceptance test" + }`) + +var testAccNetworkingV2SecGroup_update = fmt.Sprintf(` + resource "openstack_networking_secgroup_v2" "foo" { + name = "security_group_2" + description = "terraform security group acceptance test" + }`) diff --git a/website/source/docs/providers/openstack/r/networking_secgroup_rule_v2.html.markdown b/website/source/docs/providers/openstack/r/networking_secgroup_rule_v2.html.markdown new file mode 100644 index 0000000000..e80ac6cf1f --- /dev/null +++ b/website/source/docs/providers/openstack/r/networking_secgroup_rule_v2.html.markdown @@ -0,0 +1,89 @@ +--- +layout: "openstack" +page_title: "OpenStack: openstack_networking_secgroup_rule_v2" +sidebar_current: "docs-openstack-resource-networking-secgroup-rule-v2" +description: |- + Manages a V2 Neutron security group rule resource within OpenStack. +--- + +# openstack\_networking\_secgroup\_rule_v2 + +Manages a V2 neutron security group rule resource within OpenStack. +Unlike Nova security groups, neutron separates the group from the rules +and also allows an admin to target a specific tenant_id. + +## Example Usage + +``` +resource "openstack_networking_secgroup_v2" "secgroup_1" { + name = "secgroup_1" + description = "My neutron security group" +} + +resource "openstack_networking_secgroup_rule_v2" "secgroup_rule_1" { + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = 22 + port_range_max = 22 + remote_ip_prefix = "0.0.0.0/0" + security_group_id = "${openstack_networking_secgroup_v2.secgroup_1.id}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Required) The region in which to obtain the V2 networking client. + A networking client is needed to create a port. If omitted, the + `OS_REGION_NAME` environment variable is used. Changing this creates a new + security group rule. + +* `direction` - (Required) The direction of the rule, valid values are __ingress__ + or __egress__. Changing this creates a new security group rule. + +* `ethertype` - (Required) The layer 3 protocol type, valid values are __IPv4__ + or __IPv6__. Changing this creates a new security group rule. + +* `protocol` - (Optional) The layer 4 protocol type, valid values are __tcp__, + __udp__ or __icmp__. This is required if you want to specify a port range. + Changing this creates a new security group rule. + +* `port_range_min` - (Optional) The lower part of the allowed port range, valid + integer value needs to be between 1 and 65535. Changing this creates a new + security group rule. + +* `port_range_max` - (Optional) The higher part of the allowed port range, valid + integer value needs to be between 1 and 65535. Changing this creates a new + security group rule. + +* `remote_ip_prefix` - (Optional) The remote CIDR, the value needs to be a valid + CIDR (i.e. 192.168.0.0/16). Changing this creates a new security group rule. + +* `remote_group_id` - (Optional) The remote group id, the value needs to be an + Openstack ID of a security group in the same tenant. Changing this creates + a new security group rule. + +* `security_group_id` - (Required) The security group id the rule shoudl belong + to, the value needs to be an Openstack ID of a security group in the same + tenant. Changing this creates a new security group rule. + +* `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 + security group rule. + +## Attributes Reference + +The following attributes are exported: + +* `region` - See Argument Reference above. +* `direction` - See Argument Reference above. +* `ethertype` - See Argument Reference above. +* `protocol` - See Argument Reference above. +* `port_range_min` - See Argument Reference above. +* `port_range_max` - See Argument Reference above. +* `remote_ip_prefix` - See Argument Reference above. +* `remote_group_id` - See Argument Reference above. +* `security_group_id` - See Argument Reference above. +* `tenant_id` - See Argument Reference above. diff --git a/website/source/docs/providers/openstack/r/networking_secgroup_v2.html.markdown b/website/source/docs/providers/openstack/r/networking_secgroup_v2.html.markdown new file mode 100644 index 0000000000..ca49e4b66b --- /dev/null +++ b/website/source/docs/providers/openstack/r/networking_secgroup_v2.html.markdown @@ -0,0 +1,50 @@ +--- +layout: "openstack" +page_title: "OpenStack: openstack_networking_secgroup_v2" +sidebar_current: "docs-openstack-resource-networking-secgroup-v2" +description: |- + Manages a V2 Neutron security group resource within OpenStack. +--- + +# openstack\_networking\_secgroup_v2 + +Manages a V2 neutron security group resource within OpenStack. +Unlike Nova security groups, neutron separates the group from the rules +and also allows an admin to target a specific tenant_id. + +## Example Usage + +``` +resource "openstack_networking_secgroup_v2" "secgroup_1" { + name = "secgroup_1" + description = "My neutron security group" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `region` - (Required) The region in which to obtain the V2 networking client. + A networking client is needed to create a port. If omitted, the + `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. + +* `description` - (Optional) A unique name for the security group. Changing this + creates a new 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 + security group. + +## Attributes Reference + +The following attributes are exported: + +* `region` - See Argument Reference above. +* `name` - See Argument Reference above. +* `description` - See Argument Reference above. +* `tenant_id` - See Argument Reference above. diff --git a/website/source/layouts/openstack.erb b/website/source/layouts/openstack.erb index 92346a8f51..3be4214716 100644 --- a/website/source/layouts/openstack.erb +++ b/website/source/layouts/openstack.erb @@ -64,6 +64,12 @@ > openstack_networking_subnet_v2 + > + openstack_networking_secgroup_v2 + + > + openstack_networking_secgroup_rule_v2 +