Unit tests for Endpoint CRUD operations.
diff --git a/openstack/identity/v3/endpoints/requests.go b/openstack/identity/v3/endpoints/requests.go
index a29b68f..e3d0eb2 100644
--- a/openstack/identity/v3/endpoints/requests.go
+++ b/openstack/identity/v3/endpoints/requests.go
@@ -1 +1,59 @@
package endpoints
+
+import (
+ "errors"
+
+ "github.com/rackspace/gophercloud"
+)
+
+// Interface describes the availability of a specific service endpoint.
+type Interface string
+
+const (
+ // InterfaceAdmin makes an endpoint only available to administrators.
+ InterfaceAdmin Interface = "admin"
+
+ // InterfacePublic makes an endpoint available to everyone.
+ InterfacePublic Interface = "public"
+
+ // InterfaceInternal makes an endpoint only available within the cluster.
+ InterfaceInternal Interface = "internal"
+)
+
+// EndpointOpts contains the subset of Endpoint attributes that should be used to create or update an Endpoint.
+type EndpointOpts struct {
+ Interface Interface
+ Name string
+ Region string
+ URL string
+ ServiceID string
+}
+
+// Create inserts a new Endpoint into the service catalog.
+func Create(client *gophercloud.ServiceClient, opts EndpointOpts) (*Endpoint, error) {
+ return nil, errors.New("Not implemented")
+}
+
+// ListOpts allows finer control over the the endpoints returned by a List call.
+// All fields are optional.
+type ListOpts struct {
+ Interface Interface
+ ServiceID string
+ Page int
+ PerPage int
+}
+
+// List enumerates endpoints in a paginated collection, optionally filtered by ListOpts criteria.
+func List(client *gophercloud.ServiceClient, opts ListOpts) (*EndpointList, error) {
+ return nil, errors.New("Not implemented")
+}
+
+// Update changes an existing endpoint with new data.
+func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointOpts) (*Endpoint, error) {
+ return nil, errors.New("Not implemented")
+}
+
+// Delete removes an endpoint from the service catalog.
+func Delete(client *gophercloud.ServiceClient, endpointID string) error {
+ return errors.New("Not implemented")
+}
diff --git a/openstack/identity/v3/endpoints/requests_test.go b/openstack/identity/v3/endpoints/requests_test.go
new file mode 100644
index 0000000..77a2292
--- /dev/null
+++ b/openstack/identity/v3/endpoints/requests_test.go
@@ -0,0 +1,224 @@
+package endpoints
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "testing"
+
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/testhelper"
+)
+
+const tokenID = "abcabcabcabc"
+
+func serviceClient() *gophercloud.ServiceClient {
+ return &gophercloud.ServiceClient{
+ Provider: &gophercloud.ProviderClient{TokenID: tokenID},
+ Endpoint: testhelper.Endpoint(),
+ }
+}
+
+func TestCreateSuccessful(t *testing.T) {
+ testhelper.SetupHTTP()
+ defer testhelper.TeardownHTTP()
+
+ testhelper.Mux.HandleFunc("/endpoints", func(w http.ResponseWriter, r *http.Request) {
+ testhelper.TestMethod(t, r, "POST")
+ testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+ testhelper.TestJSONRequest(t, r, `
+ {
+ "endpoint": {
+ "interface": "public",
+ "name": "the-endiest-of-points",
+ "region": "underground",
+ "url": "https://1.2.3.4:9000/",
+ "service_id": "asdfasdfasdfasdf"
+ }
+ }
+ `)
+
+ fmt.Fprintf(w, `
+ {
+ "endpoint": {
+ "id": "12",
+ "interface": "public",
+ "links": {
+ "self": "https://localhost:5000/v3/endpoints/12"
+ },
+ "name": "the-endiest-of-points",
+ "region": "underground",
+ "service_id": "asdfasdfasdfasdf",
+ "url": "https://1.2.3.4:9000/"
+ }
+ }
+ `)
+ })
+
+ client := serviceClient()
+
+ result, err := Create(client, EndpointOpts{
+ Interface: InterfacePublic,
+ Name: "the-endiest-of-points",
+ Region: "underground",
+ URL: "https://1.2.3.4:9000/",
+ ServiceID: "asdfasdfasdfasdf",
+ })
+ if err != nil {
+ t.Fatalf("Unable to create an endpoint: %v", err)
+ }
+
+ expected := Endpoint{
+ ID: "12",
+ Interface: InterfacePublic,
+ Name: "the-endiest-of-points",
+ Region: "underground",
+ ServiceID: "asdfasdfasdfasdf",
+ URL: "https://1.2.3.4:9000/",
+ }
+
+ if !reflect.DeepEqual(result, expected) {
+ t.Errorf("Expected %#v, was %#v", expected, result)
+ }
+}
+
+func TestListEndpoints(t *testing.T) {
+ testhelper.SetupHTTP()
+ defer testhelper.TeardownHTTP()
+
+ testhelper.Mux.HandleFunc("/endpoints", func(w http.ResponseWriter, r *http.Request) {
+ testhelper.TestMethod(t, r, "GET")
+ testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+
+ fmt.Fprintf(w, `
+ [
+ {
+ "id": "12",
+ "interface": "public",
+ "links": {
+ "self": "https://localhost:5000/v3/endpoints/12"
+ },
+ "name": "the-endiest-of-points",
+ "region": "underground",
+ "service_id": "asdfasdfasdfasdf",
+ "url": "https://1.2.3.4:9000/"
+ },
+ {
+ "id": "13",
+ "interface": "internal",
+ "links": {
+ "self": "https://localhost:5000/v3/endpoints/13"
+ },
+ "name": "shhhh",
+ "region": "underground",
+ "service_id": "asdfasdfasdfasdf",
+ "url": "https://1.2.3.4:9001/"
+ }
+ ]
+ `)
+ })
+
+ client := serviceClient()
+
+ actual, err := List(client, ListOpts{})
+ if err != nil {
+ t.Fatalf("Unexpected error listing endpoints: %v", err)
+ }
+
+ expected := []Endpoint{
+ Endpoint{
+ ID: "12",
+ Interface: InterfacePublic,
+ Name: "the-endiest-of-points",
+ Region: "underground",
+ ServiceID: "asdfasdfasdfasdf",
+ URL: "https://1.2.3.4:9000/",
+ },
+ Endpoint{
+ ID: "13",
+ Interface: InterfaceInternal,
+ Name: "shhhh",
+ Region: "underground",
+ ServiceID: "asdfasdfasdfasdf",
+ URL: "https://1.2.3.4:9001/",
+ },
+ }
+
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Expected %#v, got %#v", expected, actual)
+ }
+}
+
+func TestUpdateEndpoint(t *testing.T) {
+ testhelper.SetupHTTP()
+ defer testhelper.TeardownHTTP()
+
+ testhelper.Mux.HandleFunc("/endpoints/12", func(w http.ResponseWriter, r *http.Request) {
+ testhelper.TestMethod(t, r, "GET")
+ testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+ testhelper.TestJSONRequest(t, r, `
+ {
+ "endpoint": {
+ "name": "renamed",
+ "region": "somewhere-else"
+ }
+ }
+ `)
+
+ fmt.Fprintf(w, `
+ {
+ "endpoint": {
+ "id": "12",
+ "interface": "public",
+ "links": {
+ "self": "https://localhost:5000/v3/endpoints/12"
+ },
+ "name": "renamed",
+ "region": "somewhere-else",
+ "service_id": "asdfasdfasdfasdf",
+ "url": "https://1.2.3.4:9000/"
+ }
+ }
+ `)
+ })
+
+ client := serviceClient()
+ actual, err := Update(client, "12", EndpointOpts{
+ Name: "renamed",
+ Region: "somewhere-else",
+ })
+ if err != nil {
+ t.Fatalf("Unexpected error from Update: %v", err)
+ }
+
+ expected := Endpoint{
+ ID: "12",
+ Interface: InterfacePublic,
+ Name: "renamed",
+ Region: "somewhere-else",
+ ServiceID: "asdfasdfasdfasdf",
+ URL: "https://1.2.3.4:9000/",
+ }
+ if !reflect.DeepEqual(expected, actual) {
+ t.Errorf("Expected %#v, was %#v", expected, actual)
+ }
+}
+
+func TestDeleteEndpoint(t *testing.T) {
+ testhelper.SetupHTTP()
+ defer testhelper.TeardownHTTP()
+
+ testhelper.Mux.HandleFunc("/endpoints/34", func(w http.ResponseWriter, r *http.Request) {
+ testhelper.TestMethod(t, r, "DELETE")
+ testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ client := serviceClient()
+
+ err := Delete(client, "34")
+ if err != nil {
+ t.Fatalf("Unexpected error from Delete: %v", err)
+ }
+}
diff --git a/openstack/identity/v3/endpoints/results.go b/openstack/identity/v3/endpoints/results.go
new file mode 100644
index 0000000..b7074df
--- /dev/null
+++ b/openstack/identity/v3/endpoints/results.go
@@ -0,0 +1,19 @@
+package endpoints
+
+import "github.com/rackspace/gophercloud"
+
+// Endpoint describes the entry point for another service's API.
+type Endpoint struct {
+ ID string `json:"id"`
+ Interface Interface `json:"interface"`
+ Name string `json:"name"`
+ Region string `json:"region"`
+ ServiceID string `json:"service_id"`
+ URL string `json:"url"`
+}
+
+// EndpointList contains a page of Endpoint results.
+type EndpointList struct {
+ gophercloud.Pagination
+ Endpoints []Endpoint
+}