Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compute: Lists and gets detailed availability zone information #327

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions openstack/compute/v2/extensions/availabilityzones/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package availabilityzones
20 changes: 20 additions & 0 deletions openstack/compute/v2/extensions/availabilityzones/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package availabilityzones

import (
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)

// List will return the existing availability zones.
func List(client *gophercloud.ServiceClient) pagination.Pager {
return pagination.NewPager(client, listURL(client), func(r pagination.PageResult) pagination.Page {
return OSAvailabilityZonePage{pagination.SinglePageBase(r)}
})
}

// ListDetail will return the existing availability zones with detailed information.
func ListDetail(client *gophercloud.ServiceClient) pagination.Pager {
return pagination.NewPager(client, listDetailURL(client), func(r pagination.PageResult) pagination.Page {
return OSAvailabilityZonePage{pagination.SinglePageBase(r)}
})
}
95 changes: 95 additions & 0 deletions openstack/compute/v2/extensions/availabilityzones/results.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
package availabilityzones

import (
"encoding/json"
"time"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/pagination"
)

// ServerExt is an extension to the base Server object
type ServerExt struct {
// AvailabilityZone is the availabilty zone the server is in.
Expand All @@ -10,3 +18,90 @@ type ServerExt struct {
func (r *ServerExt) UnmarshalJSON(b []byte) error {
return nil
}

type StateofService struct {
Active bool `json:"active"`
Available bool `json:"available"`
UpdatedAt time.Time `json:"updated_at"`
}

// UnmarshalJSON to override default
func (r *StateofService) UnmarshalJSON(b []byte) error {
type tmp StateofService
var s struct {
tmp
UpdatedAt gophercloud.JSONRFC3339MilliNoZ `json:"updated_at"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*r = StateofService(s.tmp)

r.UpdatedAt = time.Time(s.UpdatedAt)

return nil
}

type Conductor struct {
NovaConductor StateofService `json:"nova-conductor"`
}

type Consoleauth struct {
NovaConsoleauth StateofService `json:"nova-consoleauth"`
}

type Network struct {
NovaNetwork StateofService `json:"nova-network"`
}

type Scheduler struct {
NovaScheduler StateofService `json:"nova-scheduler"`
}

type Compute struct {
NovaCompute StateofService `json:"nova-compute"`
}

// An object containing a list of host information. The host information is comprised of host and service objects.
// The service object returns three parameters representing the states of the
// service: active, available, and updated_at.
// It is always null for `/os-availability-zone`
type Hosts struct {
Conductor `json:"conductor"`
Consoleauth `json:"consoleauth"`
Network `json:"network"`
Scheduler `json:"scheduler"`
Compute `json:"compute"`
}

// The current state of the availability zone
type ZoneState struct {
// Returns true if the availability zone is available
Available bool `json:"available"`
}

// AvailabilityZone contains all the information associated with an OpenStack
// AvailabilityZone.
type AvailabilityZone struct {
Hosts `json:"hosts"`
// The availability zone name
ZoneName string `json:"zoneName"`
ZoneState `json:"zoneState"`
}

type OSAvailabilityZone struct {
// The list of availability zone information
AvailabilityZoneInfo []AvailabilityZone `json:"availabilityZoneInfo"`
}

type OSAvailabilityZonePage struct {
pagination.SinglePageBase
}

// ExtractOSAvailabilityZones will get the OSAvailabilityZone objects out of the shareTypeAccessResult object.
func ExtractOSAvailabilityZones(r pagination.Page) (OSAvailabilityZone, error) {
var a OSAvailabilityZone
err := (r.(OSAvailabilityZonePage)).ExtractInto(&a)
return a, err
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package testing
171 changes: 171 additions & 0 deletions openstack/compute/v2/extensions/availabilityzones/testing/fixtures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package testing

import (
"fmt"
"net/http"
"testing"
"time"

az "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
th "github.com/gophercloud/gophercloud/testhelper"
"github.com/gophercloud/gophercloud/testhelper/client"
)

const GetOutput = `
{
"availabilityZoneInfo": [
{
"hosts": null,
"zoneName": "nova",
"zoneState": {
"available": true
}
}
]
}
`

const GetDetailOutput = `
{
"availabilityZoneInfo": [
{
"hosts": {
"conductor": {
"nova-conductor": {
"active": true,
"available": true,
"updated_at": null
}
},
"consoleauth": {
"nova-consoleauth": {
"active": true,
"available": true,
"updated_at": null
}
},
"network": {
"nova-network": {
"active": true,
"available": true,
"updated_at": "2015-09-18T09:50:55.000000"
}
},
"scheduler": {
"nova-scheduler": {
"active": true,
"available": true,
"updated_at": null
}
}
},
"zoneName": "internal",
"zoneState": {
"available": true
}
},
{
"hosts": {
"compute": {
"nova-compute": {
"active": true,
"available": true,
"updated_at": null
}
}
},
"zoneName": "nova",
"zoneState": {
"available": true
}
}
]
}
`

var OSAZResult = az.OSAvailabilityZone{
AvailabilityZoneInfo: []az.AvailabilityZone{
{
Hosts: az.Hosts{},
ZoneName: "nova",
ZoneState: az.ZoneState{Available: true},
},
},
}

var nilTime time.Time
var OSAZDetailResult = az.OSAvailabilityZone{
AvailabilityZoneInfo: []az.AvailabilityZone{
{
Hosts: az.Hosts{
Conductor: az.Conductor{
NovaConductor: az.StateofService{
Active: true,
Available: true,
UpdatedAt: nilTime,
},
},
Consoleauth: az.Consoleauth{
NovaConsoleauth: az.StateofService{
Active: true,
Available: true,
UpdatedAt: nilTime,
},
},
Network: az.Network{
NovaNetwork: az.StateofService{
Active: true,
Available: true,
UpdatedAt: time.Date(2015, 9, 18, 9, 50, 55, 0, time.UTC),
},
},
Scheduler: az.Scheduler{
NovaScheduler: az.StateofService{
Active: true,
Available: true,
UpdatedAt: nilTime,
},
},
},
ZoneName: "internal",
ZoneState: az.ZoneState{Available: true},
},
{
Hosts: az.Hosts{
Compute: az.Compute{
NovaCompute: az.StateofService{
Active: true,
Available: true,
UpdatedAt: nilTime,
},
},
},
ZoneName: "nova",
ZoneState: az.ZoneState{Available: true},
},
},
}

// HandleGetSuccessfully configures the test server to respond to a Get request
// for availability zone information.
func HandleGetSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/os-availability-zone", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)

w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, GetOutput)
})
}

// HandleGetDetailSuccessfully configures the test server to respond to a Get request
// for detailed availability zone information.
func HandleGetDetailSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/os-availability-zone/detail", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)

w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, GetDetailOutput)
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package testing

import (
"testing"

az "github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
th "github.com/gophercloud/gophercloud/testhelper"
"github.com/gophercloud/gophercloud/testhelper/client"
)

// Verifies that availability zones can be listed correctly
func TestList(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()

HandleGetSuccessfully(t)

allPages, err := az.List(client.ServiceClient()).AllPages()
th.AssertNoErr(t, err)
actual, err := az.ExtractOSAvailabilityZones(allPages)
th.AssertNoErr(t, err)

th.CheckDeepEquals(t, OSAZResult, actual)
}

// Verifies that detailed availability zones can be listed correctly
func TestListDetail(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()

HandleGetDetailSuccessfully(t)

allPages, err := az.ListDetail(client.ServiceClient()).AllPages()
th.AssertNoErr(t, err)
actual, err := az.ExtractOSAvailabilityZones(allPages)
th.AssertNoErr(t, err)

th.CheckDeepEquals(t, OSAZDetailResult, actual)
}
11 changes: 11 additions & 0 deletions openstack/compute/v2/extensions/availabilityzones/urls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package availabilityzones

import "github.com/gophercloud/gophercloud"

func listURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("os-availability-zone")
}

func listDetailURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("os-availability-zone", "detail")
}