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

List instance actions #1845 #1

Merged
merged 1 commit into from
Feb 13, 2020
Merged
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
23 changes: 23 additions & 0 deletions openstack/compute/v2/extensions/instanceactions/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package instanceactions

/*
Package instanceactions provides the ability to list or get a server instance-action.
Example:

pages, err := instanceactions.List(client, "server-id").AllPages()
if err != nil {
panic("fail to get actions pages")
}
actions, err := instanceactions.ExtractInstanceActions(pages)
if err != nil {
panic("fail to list instance actions")
}

for _, action := range actions {
action, err = instanceactions.Get(client, "server-id", action.RequestID).Extract()
if err != nil {
panic("fail to get instance action")
}
fmt.Println(action)
}
*/
21 changes: 21 additions & 0 deletions openstack/compute/v2/extensions/instanceactions/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package instanceactions

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

// List makes a request against the API to list the servers actions.
func List(client *gophercloud.ServiceClient, id string) pagination.Pager {
return pagination.NewPager(client, ListURL(client, id), func(r pagination.PageResult) pagination.Page {
return InstanceActionPage{pagination.SinglePageBase(r)}
})
}

// Get makes a request against the API to get a server action.
func Get(client *gophercloud.ServiceClient, serverID, requestID string) (r InstanceActionResult) {
_, r.Err = client.Get(instanceActionsURL(client, serverID, requestID), &r.Body, &gophercloud.RequestOpts{
OkCodes: []int{200},
})
return
}
78 changes: 78 additions & 0 deletions openstack/compute/v2/extensions/instanceactions/results.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package instanceactions

import (
"encoding/json"
"time"

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

// InstanceAction represents an instance action.
type InstanceAction struct {
Action string `json:"action"`
InstanceUUID string `json:"instance_uuid"`
Message string `json:"message"`
ProjectID string `json:"project_id"`
RequestID string `json:"request_id"`
StartTime time.Time `json:"-"`
UserID string `json:"user_id"`
}

// UnmarshalJSON converts our JSON API response into our instance action struct
func (i *InstanceAction) UnmarshalJSON(b []byte) error {
type tmp InstanceAction
var s struct {
tmp
StartTime gophercloud.JSONRFC3339MilliNoZ `json:"start_time"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
*i = InstanceAction(s.tmp)

i.StartTime = time.Time(s.StartTime)

return err
}

// InstanceActionPage abstracts the raw results of making a ListInstanceActiones() request
// against the API. As OpenStack extensions may freely alter the response bodies
// of structures returned to the client, you may only safely access the data
// provided through the ExtractInstanceActions call.
type InstanceActionPage struct {
pagination.SinglePageBase
}

// IsEmpty returns true if an InstanceActionPage contains no instance actions.
func (r InstanceActionPage) IsEmpty() (bool, error) {
instanceactions, err := ExtractInstanceActions(r)
return len(instanceactions) == 0, err
}

// ListInstanceActiones() call, producing a map of instanceActions.
func ExtractInstanceActions(r pagination.Page) ([]InstanceAction, error) {
var resp []InstanceAction
err := ExtractInstanceActionsInto(r, &resp)
return resp, err
}

type InstanceActionResult struct {
gophercloud.Result
}

// Extract interprets any instanceActionResult as an InstanceAction, if possible.
func (r InstanceActionResult) Extract() (InstanceAction, error) {
var s InstanceAction
err := r.ExtractInto(&s)
return s, err
}

func (r InstanceActionResult) ExtractInto(v interface{}) error {
return r.Result.ExtractIntoStructPtr(v, "instanceAction")
}

func ExtractInstanceActionsInto(r pagination.Page, v interface{}) error {
return r.(InstanceActionPage).Result.ExtractIntoSlicePtr(v, "instanceActions")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// instanceactions unit tests
package testing
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package testing

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

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

// ListExpected represents an expected repsonse from a List request.
var ListExpected = []instanceactions.InstanceAction{
{
Action: "stop",
InstanceUUID: "fcd19ef2-b593-40b1-90a5-fc31063fa95c",
Message: "",
ProjectID: "6f70656e737461636b20342065766572",
RequestID: "req-f8a59f03-76dc-412f-92c2-21f8612be728",
StartTime: time.Date(2018, 04, 25, 1, 26, 29, 000000, time.UTC),
UserID: "admin",
},
{
Action: "create",
InstanceUUID: "fcd19ef2-b593-40b1-90a5-fc31063fa95c",
Message: "test",
ProjectID: "6f70656e737461636b20342065766572",
RequestID: "req-50189019-626d-47fb-b944-b8342af09679",
StartTime: time.Date(2018, 04, 25, 1, 26, 25, 000000, time.UTC),
UserID: "admin",
},
}

// HandleAddressListSuccessfully sets up the test server to respond to a ListAddresses request.
func HandleInstanceActionListSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/servers/asdfasdfasdf/os-instance-actions", 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, `{
"instanceActions": [
{
"action": "stop",
"instance_uuid": "fcd19ef2-b593-40b1-90a5-fc31063fa95c",
"message": null,
"project_id": "6f70656e737461636b20342065766572",
"request_id": "req-f8a59f03-76dc-412f-92c2-21f8612be728",
"start_time": "2018-04-25T01:26:29.000000",
"user_id": "admin"
},
{
"action": "create",
"instance_uuid": "fcd19ef2-b593-40b1-90a5-fc31063fa95c",
"message": "test",
"project_id": "6f70656e737461636b20342065766572",
"request_id": "req-50189019-626d-47fb-b944-b8342af09679",
"start_time": "2018-04-25T01:26:25.000000",
"user_id": "admin"
}
]
}`)
})
}

// GetExpected represents an expected repsonse from a Get request.
var GetExpected = instanceactions.InstanceAction{
Action: "stop",
InstanceUUID: "fcd19ef2-b593-40b1-90a5-fc31063fa95c",
Message: "",
ProjectID: "6f70656e737461636b20342065766572",
RequestID: "req-f8a59f03-76dc-412f-92c2-21f8612be728",
StartTime: time.Date(2018, 04, 25, 1, 26, 29, 000000, time.UTC),
UserID: "admin",
}

// HandleInstanceActionGetSuccessfully sets up the test server to respond to a Get request.
func HandleInstanceActionGetSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/servers/asdfasdfasdf/os-instance-actions/okzeorkmkfs", 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, `{
"instanceAction":
{
"action": "stop",
"instance_uuid": "fcd19ef2-b593-40b1-90a5-fc31063fa95c",
"message": null,
"project_id": "6f70656e737461636b20342065766572",
"request_id": "req-f8a59f03-76dc-412f-92c2-21f8612be728",
"start_time": "2018-04-25T01:26:29.000000",
"user_id": "admin"
}
}`)
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package testing

import (
"testing"

"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/instanceactions"
"github.com/gophercloud/gophercloud/pagination"
th "github.com/gophercloud/gophercloud/testhelper"
"github.com/gophercloud/gophercloud/testhelper/client"
)

func TestList(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
HandleInstanceActionListSuccessfully(t)

expected := ListExpected
pages := 0
err := instanceactions.List(client.ServiceClient(), "asdfasdfasdf").EachPage(func(page pagination.Page) (bool, error) {
pages++

actual, err := instanceactions.ExtractInstanceActions(page)
th.AssertNoErr(t, err)

if len(actual) != 2 {
t.Fatalf("Expected 2 instance actions, got %d", len(actual))
}
th.CheckDeepEquals(t, expected, actual)

return true, nil
})
th.AssertNoErr(t, err)
th.CheckEquals(t, 1, pages)
}

func TestGet(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
HandleInstanceActionGetSuccessfully(t)

client := client.ServiceClient()
actual, err := instanceactions.Get(client, "asdfasdfasdf", "okzeorkmkfs").Extract()
if err != nil {
t.Fatalf("Unexpected Get error: %v", err)
}

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

import "github.com/gophercloud/gophercloud"

func ListURL(client *gophercloud.ServiceClient, id string) string {
return client.ServiceURL("servers", id, "os-instance-actions")
}

func instanceActionsURL(client *gophercloud.ServiceClient, serverID, requestID string) string {
return client.ServiceURL("servers", serverID, "os-instance-actions", requestID)
}