move unit tests into 'testing' directories
diff --git a/openstack/compute/v2/extensions/secgroups/testing/doc.go b/openstack/compute/v2/extensions/secgroups/testing/doc.go
new file mode 100644
index 0000000..7603f83
--- /dev/null
+++ b/openstack/compute/v2/extensions/secgroups/testing/doc.go
@@ -0,0 +1 @@
+package testing
diff --git a/openstack/compute/v2/extensions/secgroups/testing/fixtures.go b/openstack/compute/v2/extensions/secgroups/testing/fixtures.go
new file mode 100644
index 0000000..8a83ca8
--- /dev/null
+++ b/openstack/compute/v2/extensions/secgroups/testing/fixtures.go
@@ -0,0 +1,303 @@
+package testing
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ th "github.com/gophercloud/gophercloud/testhelper"
+ fake "github.com/gophercloud/gophercloud/testhelper/client"
+)
+
+const rootPath = "/os-security-groups"
+
+const listGroupsJSON = `
+{
+ "security_groups": [
+ {
+ "description": "default",
+ "id": "{groupID}",
+ "name": "default",
+ "rules": [],
+ "tenant_id": "openstack"
+ }
+ ]
+}
+`
+
+func mockListGroupsResponse(t *testing.T) {
+ th.Mux.HandleFunc(rootPath, func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "GET")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, listGroupsJSON)
+ })
+}
+
+func mockListGroupsByServerResponse(t *testing.T, serverID string) {
+ url := fmt.Sprintf("/servers/%s%s", serverID, rootPath)
+ th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "GET")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, listGroupsJSON)
+ })
+}
+
+func mockCreateGroupResponse(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": {
+ "name": "test",
+ "description": "something"
+ }
+}
+ `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "security_group": {
+ "description": "something",
+ "id": "{groupID}",
+ "name": "test",
+ "rules": [],
+ "tenant_id": "openstack"
+ }
+}
+`)
+ })
+}
+
+func mockUpdateGroupResponse(t *testing.T, groupID string) {
+ url := fmt.Sprintf("%s/%s", rootPath, groupID)
+ th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "PUT")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+ th.TestJSONRequest(t, r, `
+{
+ "security_group": {
+ "name": "new_name",
+ "description": "new_desc"
+ }
+}
+ `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "security_group": {
+ "description": "something",
+ "id": "{groupID}",
+ "name": "new_name",
+ "rules": [],
+ "tenant_id": "openstack"
+ }
+}
+`)
+ })
+}
+
+func mockGetGroupsResponse(t *testing.T, groupID string) {
+ url := fmt.Sprintf("%s/%s", rootPath, groupID)
+ th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "GET")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "security_group": {
+ "description": "default",
+ "id": "{groupID}",
+ "name": "default",
+ "rules": [
+ {
+ "from_port": 80,
+ "group": {
+ "tenant_id": "openstack",
+ "name": "default"
+ },
+ "ip_protocol": "TCP",
+ "to_port": 85,
+ "parent_group_id": "{groupID}",
+ "ip_range": {
+ "cidr": "0.0.0.0"
+ },
+ "id": "{ruleID}"
+ }
+ ],
+ "tenant_id": "openstack"
+ }
+}
+ `)
+ })
+}
+
+func mockGetNumericIDGroupResponse(t *testing.T, groupID int) {
+ url := fmt.Sprintf("%s/%d", rootPath, groupID)
+ th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "GET")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "security_group": {
+ "id": "12345"
+ }
+}
+ `)
+ })
+}
+
+func mockDeleteGroupResponse(t *testing.T, groupID string) {
+ url := fmt.Sprintf("%s/%s", rootPath, groupID)
+ th.Mux.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "DELETE")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusAccepted)
+ })
+}
+
+func mockAddRuleResponse(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": 22,
+ "ip_protocol": "TCP",
+ "to_port": 22,
+ "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": 22,
+ "group": {},
+ "ip_protocol": "TCP",
+ "to_port": 22,
+ "parent_group_id": "{groupID}",
+ "ip_range": {
+ "cidr": "0.0.0.0/0"
+ },
+ "id": "{ruleID}"
+ }
+}`)
+ })
+}
+
+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) {
+ th.TestMethod(t, r, "DELETE")
+ th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusAccepted)
+ })
+}
+
+func mockAddServerToGroupResponse(t *testing.T, serverID string) {
+ url := fmt.Sprintf("/servers/%s/action", serverID)
+ th.Mux.HandleFunc(url, 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, `
+{
+ "addSecurityGroup": {
+ "name": "test"
+ }
+}
+ `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusAccepted)
+ fmt.Fprintf(w, `{}`)
+ })
+}
+
+func mockRemoveServerFromGroupResponse(t *testing.T, serverID string) {
+ url := fmt.Sprintf("/servers/%s/action", serverID)
+ th.Mux.HandleFunc(url, 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, `
+{
+ "removeSecurityGroup": {
+ "name": "test"
+ }
+}
+ `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusAccepted)
+ fmt.Fprintf(w, `{}`)
+ })
+}
diff --git a/openstack/compute/v2/extensions/secgroups/testing/requests_test.go b/openstack/compute/v2/extensions/secgroups/testing/requests_test.go
new file mode 100644
index 0000000..b7ffa20
--- /dev/null
+++ b/openstack/compute/v2/extensions/secgroups/testing/requests_test.go
@@ -0,0 +1,279 @@
+package testing
+
+import (
+ "testing"
+
+ "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
+ "github.com/gophercloud/gophercloud/pagination"
+ th "github.com/gophercloud/gophercloud/testhelper"
+ "github.com/gophercloud/gophercloud/testhelper/client"
+)
+
+const (
+ serverID = "{serverID}"
+ groupID = "{groupID}"
+ ruleID = "{ruleID}"
+)
+
+func TestList(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockListGroupsResponse(t)
+
+ count := 0
+
+ err := secgroups.List(client.ServiceClient()).EachPage(func(page pagination.Page) (bool, error) {
+ count++
+ actual, err := secgroups.ExtractSecurityGroups(page)
+ if err != nil {
+ t.Errorf("Failed to extract users: %v", err)
+ return false, err
+ }
+
+ expected := []secgroups.SecurityGroup{
+ {
+ ID: groupID,
+ Description: "default",
+ Name: "default",
+ Rules: []secgroups.Rule{},
+ TenantID: "openstack",
+ },
+ }
+
+ th.CheckDeepEquals(t, expected, actual)
+
+ return true, nil
+ })
+
+ th.AssertNoErr(t, err)
+ th.AssertEquals(t, 1, count)
+}
+
+func TestListByServer(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockListGroupsByServerResponse(t, serverID)
+
+ count := 0
+
+ err := secgroups.ListByServer(client.ServiceClient(), serverID).EachPage(func(page pagination.Page) (bool, error) {
+ count++
+ actual, err := secgroups.ExtractSecurityGroups(page)
+ if err != nil {
+ t.Errorf("Failed to extract users: %v", err)
+ return false, err
+ }
+
+ expected := []secgroups.SecurityGroup{
+ {
+ ID: groupID,
+ Description: "default",
+ Name: "default",
+ Rules: []secgroups.Rule{},
+ TenantID: "openstack",
+ },
+ }
+
+ th.CheckDeepEquals(t, expected, actual)
+
+ return true, nil
+ })
+
+ th.AssertNoErr(t, err)
+ th.AssertEquals(t, 1, count)
+}
+
+func TestCreate(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockCreateGroupResponse(t)
+
+ opts := secgroups.CreateOpts{
+ Name: "test",
+ Description: "something",
+ }
+
+ group, err := secgroups.Create(client.ServiceClient(), opts).Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &secgroups.SecurityGroup{
+ ID: groupID,
+ Name: "test",
+ Description: "something",
+ TenantID: "openstack",
+ Rules: []secgroups.Rule{},
+ }
+ th.AssertDeepEquals(t, expected, group)
+}
+
+func TestUpdate(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockUpdateGroupResponse(t, groupID)
+
+ opts := secgroups.UpdateOpts{
+ Name: "new_name",
+ Description: "new_desc",
+ }
+
+ group, err := secgroups.Update(client.ServiceClient(), groupID, opts).Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &secgroups.SecurityGroup{
+ ID: groupID,
+ Name: "new_name",
+ Description: "something",
+ TenantID: "openstack",
+ Rules: []secgroups.Rule{},
+ }
+ th.AssertDeepEquals(t, expected, group)
+}
+
+func TestGet(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockGetGroupsResponse(t, groupID)
+
+ group, err := secgroups.Get(client.ServiceClient(), groupID).Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &secgroups.SecurityGroup{
+ ID: groupID,
+ Description: "default",
+ Name: "default",
+ TenantID: "openstack",
+ Rules: []secgroups.Rule{
+ {
+ FromPort: 80,
+ ToPort: 85,
+ IPProtocol: "TCP",
+ IPRange: secgroups.IPRange{CIDR: "0.0.0.0"},
+ Group: secgroups.Group{TenantID: "openstack", Name: "default"},
+ ParentGroupID: groupID,
+ ID: ruleID,
+ },
+ },
+ }
+
+ th.AssertDeepEquals(t, expected, group)
+}
+
+func TestGetNumericID(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ numericGroupID := 12345
+
+ mockGetNumericIDGroupResponse(t, numericGroupID)
+
+ group, err := secgroups.Get(client.ServiceClient(), "12345").Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &secgroups.SecurityGroup{ID: "12345"}
+ th.AssertDeepEquals(t, expected, group)
+}
+
+func TestDelete(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockDeleteGroupResponse(t, groupID)
+
+ err := secgroups.Delete(client.ServiceClient(), groupID).ExtractErr()
+ th.AssertNoErr(t, err)
+}
+
+func TestAddRule(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockAddRuleResponse(t)
+
+ opts := secgroups.CreateRuleOpts{
+ ParentGroupID: groupID,
+ FromPort: 22,
+ ToPort: 22,
+ IPProtocol: "TCP",
+ CIDR: "0.0.0.0/0",
+ }
+
+ rule, err := secgroups.CreateRule(client.ServiceClient(), opts).Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &secgroups.Rule{
+ FromPort: 22,
+ ToPort: 22,
+ Group: secgroups.Group{},
+ IPProtocol: "TCP",
+ ParentGroupID: groupID,
+ IPRange: secgroups.IPRange{CIDR: "0.0.0.0/0"},
+ ID: ruleID,
+ }
+
+ th.AssertDeepEquals(t, expected, rule)
+}
+
+func TestAddRuleICMPZero(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockAddRuleResponseICMPZero(t)
+
+ opts := secgroups.CreateRuleOpts{
+ ParentGroupID: groupID,
+ FromPort: 0,
+ ToPort: 0,
+ IPProtocol: "ICMP",
+ CIDR: "0.0.0.0/0",
+ }
+
+ rule, err := secgroups.CreateRule(client.ServiceClient(), opts).Extract()
+ th.AssertNoErr(t, err)
+
+ expected := &secgroups.Rule{
+ FromPort: 0,
+ ToPort: 0,
+ Group: secgroups.Group{},
+ IPProtocol: "ICMP",
+ ParentGroupID: groupID,
+ IPRange: secgroups.IPRange{CIDR: "0.0.0.0/0"},
+ ID: ruleID,
+ }
+
+ th.AssertDeepEquals(t, expected, rule)
+}
+
+func TestDeleteRule(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockDeleteRuleResponse(t, ruleID)
+
+ err := secgroups.DeleteRule(client.ServiceClient(), ruleID).ExtractErr()
+ th.AssertNoErr(t, err)
+}
+
+func TestAddServer(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockAddServerToGroupResponse(t, serverID)
+
+ err := secgroups.AddServer(client.ServiceClient(), serverID, "test").ExtractErr()
+ th.AssertNoErr(t, err)
+}
+
+func TestRemoveServer(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+
+ mockRemoveServerFromGroupResponse(t, serverID)
+
+ err := secgroups.RemoveServer(client.ServiceClient(), serverID, "test").ExtractErr()
+ th.AssertNoErr(t, err)
+}