Merge pull request #522 from deniszh/master
[rfr] From Port and To Port should accept values of 0
diff --git a/acceptance/openstack/compute/v2/secgroup_test.go b/acceptance/openstack/compute/v2/secgroup_test.go
index 4f50739..6ec3149 100644
--- a/acceptance/openstack/compute/v2/secgroup_test.go
+++ b/acceptance/openstack/compute/v2/secgroup_test.go
@@ -107,6 +107,24 @@
th.AssertNoErr(t, err)
t.Logf("Deleted rule %s from group %s", rule.ID, id)
+
+ icmpOpts := secgroups.CreateRuleOpts{
+ ParentGroupID: id,
+ FromPort: 0,
+ ToPort: 0,
+ IPProtocol: "ICMP",
+ CIDR: "0.0.0.0/0",
+ }
+
+ icmpRule, err := secgroups.CreateRule(client, icmpOpts).Extract()
+ th.AssertNoErr(t, err)
+
+ t.Logf("Adding ICMP rule %s to group %s", icmpRule.ID, id)
+
+ err = secgroups.DeleteRule(client, icmpRule.ID).ExtractErr()
+ th.AssertNoErr(t, err)
+
+ t.Logf("Deleted ICMP rule %s from group %s", icmpRule.ID, id)
}
func findServer(t *testing.T, client *gophercloud.ServiceClient) (string, bool) {
diff --git a/openstack/compute/v2/extensions/defsecrules/fixtures.go b/openstack/compute/v2/extensions/defsecrules/fixtures.go
index c28e492..2870b6a 100644
--- a/openstack/compute/v2/extensions/defsecrules/fixtures.go
+++ b/openstack/compute/v2/extensions/defsecrules/fixtures.go
@@ -72,6 +72,41 @@
})
}
+func mockCreateRuleResponseICMPZero(t *testing.T) {
+ th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "POST")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+ th.TestJSONRequest(t, r, `
+{
+ "security_group_default_rule": {
+ "ip_protocol": "ICMP",
+ "from_port": 0,
+ "to_port": 0,
+ "cidr": "10.10.12.0/24"
+ }
+}
+ `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "security_group_default_rule": {
+ "from_port": 0,
+ "id": "{ruleID}",
+ "ip_protocol": "ICMP",
+ "ip_range": {
+ "cidr": "10.10.12.0/24"
+ },
+ "to_port": 0
+ }
+}
+`)
+ })
+}
+
func mockGetRuleResponse(t *testing.T, ruleID string) {
url := rootPath + "/" + ruleID
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
diff --git a/openstack/compute/v2/extensions/defsecrules/requests.go b/openstack/compute/v2/extensions/defsecrules/requests.go
index 9f27ef1..d0098e6 100644
--- a/openstack/compute/v2/extensions/defsecrules/requests.go
+++ b/openstack/compute/v2/extensions/defsecrules/requests.go
@@ -2,6 +2,7 @@
import (
"errors"
+ "strings"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
@@ -42,10 +43,10 @@
func (opts CreateOpts) ToRuleCreateMap() (map[string]interface{}, error) {
rule := make(map[string]interface{})
- if opts.FromPort == 0 {
+ if opts.FromPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" {
return rule, errors.New("A FromPort must be set")
}
- if opts.ToPort == 0 {
+ if opts.ToPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" {
return rule, errors.New("A ToPort must be set")
}
if opts.IPProtocol == "" {
diff --git a/openstack/compute/v2/extensions/defsecrules/requests_test.go b/openstack/compute/v2/extensions/defsecrules/requests_test.go
index d4ebe87..1ab6637 100644
--- a/openstack/compute/v2/extensions/defsecrules/requests_test.go
+++ b/openstack/compute/v2/extensions/defsecrules/requests_test.go
@@ -69,6 +69,32 @@
th.AssertDeepEquals(t, expected, group)
}
+func TestCreateICMPZero(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockCreateRuleResponseICMPZero(t)
+
+ opts := CreateOpts{
+ IPProtocol: "ICMP",
+ FromPort: 0,
+ ToPort: 0,
+ CIDR: "10.10.12.0/24",
+ }
+
+ group, err := Create(client.ServiceClient(), opts).Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &DefaultRule{
+ ID: ruleID,
+ FromPort: 0,
+ ToPort: 0,
+ IPProtocol: "ICMP",
+ IPRange: secgroups.IPRange{CIDR: "10.10.12.0/24"},
+ }
+ th.AssertDeepEquals(t, expected, group)
+}
+
func TestGet(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
diff --git a/openstack/compute/v2/extensions/secgroups/fixtures.go b/openstack/compute/v2/extensions/secgroups/fixtures.go
index 8c42e48..28b1c06 100644
--- a/openstack/compute/v2/extensions/secgroups/fixtures.go
+++ b/openstack/compute/v2/extensions/secgroups/fixtures.go
@@ -216,6 +216,42 @@
})
}
+func mockAddRuleResponseICMPZero(t *testing.T) {
+ th.Mux.HandleFunc("/os-security-group-rules", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "POST")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+ th.TestJSONRequest(t, r, `
+{
+ "security_group_rule": {
+ "from_port": 0,
+ "ip_protocol": "ICMP",
+ "to_port": 0,
+ "parent_group_id": "{groupID}",
+ "cidr": "0.0.0.0/0"
+ }
+} `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "security_group_rule": {
+ "from_port": 0,
+ "group": {},
+ "ip_protocol": "ICMP",
+ "to_port": 0,
+ "parent_group_id": "{groupID}",
+ "ip_range": {
+ "cidr": "0.0.0.0/0"
+ },
+ "id": "{ruleID}"
+ }
+}`)
+ })
+}
+
func mockDeleteRuleResponse(t *testing.T, ruleID string) {
url := fmt.Sprintf("/os-security-group-rules/%s", ruleID)
th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
diff --git a/openstack/compute/v2/extensions/secgroups/requests.go b/openstack/compute/v2/extensions/secgroups/requests.go
index 4cef480..120dcae 100644
--- a/openstack/compute/v2/extensions/secgroups/requests.go
+++ b/openstack/compute/v2/extensions/secgroups/requests.go
@@ -2,6 +2,7 @@
import (
"errors"
+ "strings"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"
@@ -181,10 +182,10 @@
if opts.ParentGroupID == "" {
return rule, errors.New("A ParentGroupID must be set")
}
- if opts.FromPort == 0 {
+ if opts.FromPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" {
return rule, errors.New("A FromPort must be set")
}
- if opts.ToPort == 0 {
+ if opts.ToPort == 0 && strings.ToUpper(opts.IPProtocol) != "ICMP" {
return rule, errors.New("A ToPort must be set")
}
if opts.IPProtocol == "" {
diff --git a/openstack/compute/v2/extensions/secgroups/requests_test.go b/openstack/compute/v2/extensions/secgroups/requests_test.go
index 4e21d5d..c9b93a2 100644
--- a/openstack/compute/v2/extensions/secgroups/requests_test.go
+++ b/openstack/compute/v2/extensions/secgroups/requests_test.go
@@ -217,6 +217,36 @@
th.AssertDeepEquals(t, expected, rule)
}
+func TestAddRuleICMPZero(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockAddRuleResponseICMPZero(t)
+
+ opts := CreateRuleOpts{
+ ParentGroupID: groupID,
+ FromPort: 0,
+ ToPort: 0,
+ IPProtocol: "ICMP",
+ CIDR: "0.0.0.0/0",
+ }
+
+ rule, err := CreateRule(client.ServiceClient(), opts).Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &Rule{
+ FromPort: 0,
+ ToPort: 0,
+ Group: Group{},
+ IPProtocol: "ICMP",
+ ParentGroupID: groupID,
+ IPRange: IPRange{CIDR: "0.0.0.0/0"},
+ ID: ruleID,
+ }
+
+ th.AssertDeepEquals(t, expected, rule)
+}
+
func TestDeleteRule(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()