Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.
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
4 changes: 4 additions & 0 deletions openstack/rts/v1/stackevents/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Package stackevents provides operations for finding, listing, and retrieving
// stack events. Stack events are events that take place on stacks such as
// updating and abandoning.
package stackevents
113 changes: 113 additions & 0 deletions openstack/rts/v1/stackevents/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package stackevents

import (
"github.com/huaweicloud/golangsdk"
"github.com/huaweicloud/golangsdk/pagination"
)

// SortDir is a type for specifying in which direction to sort a list of events.
type SortDir string

// SortKey is a type for specifying by which key to sort a list of events.
type SortKey string

// ResourceStatus is a type for specifying by which resource status to filter a
// list of events.
type ResourceStatus string

// ResourceAction is a type for specifying by which resource action to filter a
// list of events.
type ResourceAction string

var (
// ResourceStatusInProgress is used to filter a List request by the 'IN_PROGRESS' status.
ResourceStatusInProgress ResourceStatus = "IN_PROGRESS"
// ResourceStatusComplete is used to filter a List request by the 'COMPLETE' status.
ResourceStatusComplete ResourceStatus = "COMPLETE"
// ResourceStatusFailed is used to filter a List request by the 'FAILED' status.
ResourceStatusFailed ResourceStatus = "FAILED"

// ResourceActionCreate is used to filter a List request by the 'CREATE' action.
ResourceActionCreate ResourceAction = "CREATE"
// ResourceActionDelete is used to filter a List request by the 'DELETE' action.
ResourceActionDelete ResourceAction = "DELETE"
// ResourceActionUpdate is used to filter a List request by the 'UPDATE' action.
ResourceActionUpdate ResourceAction = "UPDATE"
// ResourceActionRollback is used to filter a List request by the 'ROLLBACK' action.
ResourceActionRollback ResourceAction = "ROLLBACK"
// ResourceActionSuspend is used to filter a List request by the 'SUSPEND' action.
ResourceActionSuspend ResourceAction = "SUSPEND"
// ResourceActionResume is used to filter a List request by the 'RESUME' action.
ResourceActionResume ResourceAction = "RESUME"
// ResourceActionAbandon is used to filter a List request by the 'ABANDON' action.
ResourceActionAbandon ResourceAction = "ABANDON"

// SortAsc is used to sort a list of stacks in ascending order.
SortAsc SortDir = "asc"
// SortDesc is used to sort a list of stacks in descending order.
SortDesc SortDir = "desc"

// SortName is used to sort a list of stacks by name.
SortName SortKey = "name"
// SortResourceType is used to sort a list of stacks by resource type.
SortResourceType SortKey = "resource_type"
// SortCreatedAt is used to sort a list of stacks by date created.
SortCreatedAt SortKey = "created_at"
)

// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToStackEventListQuery() (string, error)
}

// ListOpts allows the filtering and sorting of paginated collections through
// the API. Marker and Limit are used for pagination.
type ListOpts struct {
// The stack resource ID with which to start the listing.
Marker string `q:"marker"`
// Integer value for the limit of values to return.
Limit int `q:"limit"`
// Filters the event list by the specified ResourceAction. You can use this
// filter multiple times to filter by multiple resource actions: CREATE, DELETE,
// UPDATE, ROLLBACK, SUSPEND, RESUME or ADOPT.
ResourceActions []ResourceAction `q:"resource_action"`
// Filters the event list by the specified resource_status. You can use this
// filter multiple times to filter by multiple resource statuses: IN_PROGRESS,
// COMPLETE or FAILED.
ResourceStatuses []ResourceStatus `q:"resource_status"`
// Filters the event list by the specified resource_name. You can use this
// filter multiple times to filter by multiple resource names.
ResourceNames []string `q:"resource_name"`
// Filters the event list by the specified resource_type. You can use this
// filter multiple times to filter by multiple resource types: OS::Nova::Server,
// OS::Cinder::Volume, and so on.
ResourceTypes []string `q:"resource_type"`
// Sorts the event list by: resource_type or created_at.
SortKey SortKey `q:"sort_keys"`
// The sort direction of the event list. Which is asc (ascending) or desc (descending).
SortDir SortDir `q:"sort_dir"`
}

// ToStackEventListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToStackEventListQuery() (string, error) {
q, err := golangsdk.BuildQueryString(opts)
return q.String(), err
}

// List makes a request against the API to list resources for the given stack.
func List(client *golangsdk.ServiceClient, stackName, stackID string, opts ListOptsBuilder) pagination.Pager {
url := listURL(client, stackName, stackID)
if opts != nil {
query, err := opts.ToStackEventListQuery()
if err != nil {
return pagination.Pager{Err: err}
}
url += query
}
return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
p := EventPage{pagination.MarkerPageBase{PageResult: r}}
p.MarkerPageBase.Owner = p
return p
})
}
98 changes: 98 additions & 0 deletions openstack/rts/v1/stackevents/results.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package stackevents

import (
"encoding/json"
"time"

"github.com/huaweicloud/golangsdk"
"github.com/huaweicloud/golangsdk/pagination"
)

// Event represents a stack event.
type Event struct {
// The name of the resource for which the event occurred.
ResourceName string `json:"resource_name"`
// The time the event occurred.
Time time.Time `json:"-"`
// The URLs to the event.
Links []golangsdk.Link `json:"links"`
// The logical ID of the stack resource.
LogicalResourceID string `json:"logical_resource_id"`
// The reason of the status of the event.
ResourceStatusReason string `json:"resource_status_reason"`
// The status of the event.
ResourceStatus string `json:"resource_status"`
// The physical ID of the stack resource.
PhysicalResourceID string `json:"physical_resource_id"`
// The event ID.
ID string `json:"id"`
// Properties of the stack resource.
ResourceProperties map[string]interface{} `json:"resource_properties"`
}

func (r *Event) UnmarshalJSON(b []byte) error {
type tmp Event
var s struct {
tmp
Time golangsdk.JSONRFC3339NoZ `json:"event_time"`
}
err := json.Unmarshal(b, &s)
if err != nil {
return err
}

*r = Event(s.tmp)

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

return nil
}

// FindResult represents the result of a Find operation.
type FindResult struct {
golangsdk.Result
}

// Extract returns a slice of Event objects and is called after a
// Find operation.
func (r FindResult) Extract() ([]Event, error) {
var s struct {
Events []Event `json:"events"`
}
err := r.ExtractInto(&s)
return s.Events, err
}

// EventPage abstracts the raw results of making a List() 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 ExtractResources call.
type EventPage struct {
pagination.MarkerPageBase
}

// IsEmpty returns true if a page contains no Server results.
func (r EventPage) IsEmpty() (bool, error) {
events, err := ExtractEvents(r)
return len(events) == 0, err
}

// LastMarker returns the last stack ID in a ListResult.
func (r EventPage) LastMarker() (string, error) {
events, err := ExtractEvents(r)
if err != nil {
return "", err
}
if len(events) == 0 {
return "", nil
}
return events[len(events)-1].ID, nil
}

// ExtractEvents interprets the results of a single page from a List() call, producing a slice of Event entities.
func ExtractEvents(r pagination.Page) ([]Event, error) {
var s struct {
Events []Event `json:"events"`
}
err := (r.(EventPage)).ExtractInto(&s)
return s.Events, err
}
2 changes: 2 additions & 0 deletions openstack/rts/v1/stackevents/testing/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// orchestration_stackevents_v1
package testing
138 changes: 138 additions & 0 deletions openstack/rts/v1/stackevents/testing/fixtures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package testing

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

"github.com/huaweicloud/golangsdk"
"github.com/huaweicloud/golangsdk/openstack/rts/v1/stackevents"
th "github.com/huaweicloud/golangsdk/testhelper"
fake "github.com/huaweicloud/golangsdk/testhelper/client"
)

// ListExpected represents the expected object from a List request.
var ListExpected = []stackevents.Event{
{
ResourceName: "hello_world",
Time: time.Date(2015, 2, 5, 21, 33, 11, 0, time.UTC),
Links: []golangsdk.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
Rel: "self",
},
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world",
Rel: "resource",
},
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b",
Rel: "stack",
},
},
LogicalResourceID: "hello_world",
ResourceStatusReason: "state changed",
ResourceStatus: "CREATE_IN_PROGRESS",
PhysicalResourceID: "",
ID: "06feb26f-9298-4a9b-8749-9d770e5d577a",
},
{
ResourceName: "hello_world",
Time: time.Date(2015, 2, 5, 21, 33, 27, 0, time.UTC),
Links: []golangsdk.Link{
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
Rel: "self",
},
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world",
Rel: "resource",
},
{
Href: "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b",
Rel: "stack",
},
},
LogicalResourceID: "hello_world",
ResourceStatusReason: "state changed",
ResourceStatus: "CREATE_COMPLETE",
PhysicalResourceID: "49181cd6-169a-4130-9455-31185bbfc5bf",
ID: "93940999-7d40-44ae-8de4-19624e7b8d18",
},
}

// ListOutput represents the response body from a List request.
const ListOutput = `
{
"events": [
{
"resource_name": "hello_world",
"event_time": "2015-02-05T21:33:11",
"links": [
{
"href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/06feb26f-9298-4a9b-8749-9d770e5d577a",
"rel": "self"
},
{
"href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world",
"rel": "resource"
},
{
"href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b",
"rel": "stack"
}
],
"logical_resource_id": "hello_world",
"resource_status_reason": "state changed",
"resource_status": "CREATE_IN_PROGRESS",
"physical_resource_id": null,
"id": "06feb26f-9298-4a9b-8749-9d770e5d577a"
},
{
"resource_name": "hello_world",
"event_time": "2015-02-05T21:33:27",
"links": [
{
"href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world/events/93940999-7d40-44ae-8de4-19624e7b8d18",
"rel": "self"
},
{
"href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b/resources/hello_world",
"rel": "resource"
},
{
"href": "http://166.78.160.107:8004/v1/98606384f58d4ad0b3db7d0d779549ac/stacks/postman_stack/5f57cff9-93fc-424e-9f78-df0515e7f48b",
"rel": "stack"
}
],
"logical_resource_id": "hello_world",
"resource_status_reason": "state changed",
"resource_status": "CREATE_COMPLETE",
"physical_resource_id": "49181cd6-169a-4130-9455-31185bbfc5bf",
"id": "93940999-7d40-44ae-8de4-19624e7b8d18"
}
]
}`

// HandleListSuccessfully creates an HTTP handler at `/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/events`
// on the test handler mux that responds with a `List` response.
func HandleListSuccessfully(t *testing.T, output string) {
th.Mux.HandleFunc("/stacks/hello_world/49181cd6-169a-4130-9455-31185bbfc5bf/events", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", fake.TokenID)
th.TestHeader(t, r, "Accept", "application/json")

w.Header().Set("Content-Type", "application/json")
r.ParseForm()
marker := r.Form.Get("marker")
switch marker {
case "":
fmt.Fprintf(w, output)
case "93940999-7d40-44ae-8de4-19624e7b8d18":
fmt.Fprintf(w, `{"events":[]}`)
default:
t.Fatalf("Unexpected marker: [%s]", marker)
}
})
}
29 changes: 29 additions & 0 deletions openstack/rts/v1/stackevents/testing/requests_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package testing

import (
"testing"

"github.com/huaweicloud/golangsdk/openstack/rts/v1/stackevents"
"github.com/huaweicloud/golangsdk/pagination"
th "github.com/huaweicloud/golangsdk/testhelper"
fake "github.com/huaweicloud/golangsdk/testhelper/client"
)

func TestList(t *testing.T) {
th.SetupHTTP()
defer th.TeardownHTTP()
HandleListSuccessfully(t, ListOutput)

count := 0
err := stackevents.List(fake.ServiceClient(), "hello_world", "49181cd6-169a-4130-9455-31185bbfc5bf", nil).EachPage(func(page pagination.Page) (bool, error) {
count++
actual, err := stackevents.ExtractEvents(page)
th.AssertNoErr(t, err)

th.CheckDeepEquals(t, ListExpected, actual)

return true, nil
})
th.AssertNoErr(t, err)
th.CheckEquals(t, count, 1)
}
7 changes: 7 additions & 0 deletions openstack/rts/v1/stackevents/urls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package stackevents

import "github.com/huaweicloud/golangsdk"

func listURL(c *golangsdk.ServiceClient, stackName, stackID string) string {
return c.ServiceURL("stacks", stackName, stackID, "events")
}
Loading