Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit e6e0ec1

Browse files
committed
Rackspace Auto Scale: Add webhooks Create()
1 parent 366a7a0 commit e6e0ec1

File tree

5 files changed

+161
-5
lines changed

5 files changed

+161
-5
lines changed

rackspace/autoscale/v1/webhooks/fixtures.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,24 @@ const WebhookListBody = `
5353
}
5454
`
5555

56+
// WebhookCreateBody contains the canned body of a webhooks.Create response.
57+
const WebhookCreateBody = WebhookListBody
58+
59+
// WebhookCreateRequest contains the canned body of a webhooks.Create request.
60+
const WebhookCreateRequest = `
61+
[
62+
{
63+
"name": "first hook"
64+
},
65+
{
66+
"name": "second hook",
67+
"metadata": {
68+
"notes": "a note about this webhook"
69+
}
70+
}
71+
]
72+
`
73+
5674
var (
5775
// FirstWebhook is a Webhook corresponding to the first result in WebhookListBody.
5876
FirstWebhook = Webhook{
@@ -104,3 +122,22 @@ func HandleWebhookListSuccessfully(t *testing.T) {
104122
fmt.Fprintf(w, WebhookListBody)
105123
})
106124
}
125+
126+
// HandleWebhookCreateSuccessfully sets up the test server to respond to a webhooks Create request.
127+
func HandleWebhookCreateSuccessfully(t *testing.T) {
128+
path := "/groups/10eb3219-1b12-4b34-b1e4-e10ee4f24c65/policies/2b48d247-0282-4b9d-8775-5c4b67e8e649/webhooks"
129+
130+
th.Mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
131+
th.TestMethod(t, r, "POST")
132+
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
133+
th.TestHeader(t, r, "Content-Type", "application/json")
134+
th.TestHeader(t, r, "Accept", "application/json")
135+
136+
th.TestJSONRequest(t, r, WebhookCreateRequest)
137+
138+
w.Header().Add("Content-Type", "application/json")
139+
w.WriteHeader(http.StatusCreated)
140+
141+
fmt.Fprintf(w, WebhookCreateBody)
142+
})
143+
}

rackspace/autoscale/v1/webhooks/requests.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package webhooks
22

33
import (
4+
"errors"
5+
46
"github.com/rackspace/gophercloud"
57
"github.com/rackspace/gophercloud/pagination"
68
)
@@ -15,3 +17,70 @@ func List(client *gophercloud.ServiceClient, groupID, policyID string) paginatio
1517

1618
return pagination.NewPager(client, url, createPageFn)
1719
}
20+
21+
// CreateOptsBuilder is the interface responsible for generating the JSON
22+
// for a Create operation.
23+
type CreateOptsBuilder interface {
24+
ToWebhookCreateMap() ([]map[string]interface{}, error)
25+
}
26+
27+
// CreateOpts is a slice of CreateOpt structs, that allow the user to create
28+
// multiple webhooks in a single operation.
29+
type CreateOpts []CreateOpt
30+
31+
// CreateOpt represents the options to create a webhook.
32+
type CreateOpt struct {
33+
// Name [required] is a name for the webhook.
34+
Name string
35+
36+
// Metadata [optional] is user-provided key-value metadata.
37+
// Maximum length for keys and values is 256 characters.
38+
Metadata map[string]string
39+
}
40+
41+
// ToWebhookCreateMap converts a slice of CreateOpt structs into a map for use
42+
// in the request body of a Create operation.
43+
func (opts CreateOpts) ToWebhookCreateMap() ([]map[string]interface{}, error) {
44+
var webhooks []map[string]interface{}
45+
46+
for _, o := range opts {
47+
if o.Name == "" {
48+
return nil, errors.New("Cannot create a Webhook without a name.")
49+
}
50+
51+
hook := make(map[string]interface{})
52+
53+
hook["name"] = o.Name
54+
55+
if o.Metadata != nil {
56+
hook["metadata"] = o.Metadata
57+
}
58+
59+
webhooks = append(webhooks, hook)
60+
}
61+
62+
return webhooks, nil
63+
}
64+
65+
// Create requests a new webhook be created and associated with the given group
66+
// and scaling policy.
67+
func Create(client *gophercloud.ServiceClient, groupID, policyID string, opts CreateOptsBuilder) CreateResult {
68+
var res CreateResult
69+
70+
reqBody, err := opts.ToWebhookCreateMap()
71+
72+
if err != nil {
73+
res.Err = err
74+
return res
75+
}
76+
77+
resp, err := client.Post(createURL(client, groupID, policyID), reqBody, &res.Body, nil)
78+
79+
if err != nil {
80+
res.Err = err
81+
return res
82+
}
83+
84+
pr := pagination.PageResultFromParsed(resp, res.Body)
85+
return CreateResult{pagination.SinglePageBase(pr)}
86+
}

rackspace/autoscale/v1/webhooks/requests_test.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ import (
88
"github.com/rackspace/gophercloud/testhelper/client"
99
)
1010

11+
const (
12+
groupID = "10eb3219-1b12-4b34-b1e4-e10ee4f24c65"
13+
policyID = "2b48d247-0282-4b9d-8775-5c4b67e8e649"
14+
)
15+
1116
func TestList(t *testing.T) {
1217
th.SetupHTTP()
1318
defer th.TeardownHTTP()
1419
HandleWebhookListSuccessfully(t)
1520

16-
groupID := "10eb3219-1b12-4b34-b1e4-e10ee4f24c65"
17-
policyID := "2b48d247-0282-4b9d-8775-5c4b67e8e649"
18-
1921
pages := 0
2022
pager := List(client.ServiceClient(), groupID, policyID)
2123

@@ -44,3 +46,28 @@ func TestList(t *testing.T) {
4446
t.Errorf("Expected 1 page, saw %d", pages)
4547
}
4648
}
49+
50+
func TestCreate(t *testing.T) {
51+
th.SetupHTTP()
52+
defer th.TeardownHTTP()
53+
HandleWebhookCreateSuccessfully(t)
54+
55+
client := client.ServiceClient()
56+
opts := CreateOpts{
57+
{
58+
Name: "first hook",
59+
},
60+
{
61+
Name: "second hook",
62+
Metadata: map[string]string{
63+
"notes": "a note about this webhook",
64+
},
65+
},
66+
}
67+
68+
webhooks, err := Create(client, groupID, policyID, opts).ExtractWebhooks()
69+
70+
th.AssertNoErr(t, err)
71+
th.CheckDeepEquals(t, FirstWebhook, webhooks[0])
72+
th.CheckDeepEquals(t, SecondWebhook, webhooks[1])
73+
}

rackspace/autoscale/v1/webhooks/results.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,23 @@ type webhookResult struct {
1111
gophercloud.Result
1212
}
1313

14+
// CreateResult represents the result of a create operation. Multiple webhooks
15+
// can be created in a single call, so the result should be treated as a typical
16+
// pagination Page. ExtractWebhooks() can be used to extract a slice of
17+
// Webhooks from a single page.
18+
type CreateResult struct {
19+
pagination.SinglePageBase
20+
}
21+
22+
// ExtractWebhooks extracts a slice of Webhooks from a CreateResult.
23+
func (res CreateResult) ExtractWebhooks() ([]Webhook, error) {
24+
if res.Err != nil {
25+
return nil, res.Err
26+
}
27+
28+
return commonExtractWebhooks(res.Body)
29+
}
30+
1431
// Webhook represents a webhook associted with a scaling policy.
1532
type Webhook struct {
1633
// UUID for the webhook.
@@ -46,13 +63,15 @@ func (page WebhookPage) IsEmpty() (bool, error) {
4663
// ExtractWebhooks interprets the results of a single page from a List() call,
4764
// producing a slice of Webhooks.
4865
func ExtractWebhooks(page pagination.Page) ([]Webhook, error) {
49-
casted := page.(WebhookPage).Body
66+
return commonExtractWebhooks(page.(WebhookPage).Body)
67+
}
5068

69+
func commonExtractWebhooks(body interface{}) ([]Webhook, error) {
5170
var response struct {
5271
Webhooks []Webhook `mapstructure:"webhooks"`
5372
}
5473

55-
err := mapstructure.Decode(casted, &response)
74+
err := mapstructure.Decode(body, &response)
5675

5776
if err != nil {
5877
return nil, err

rackspace/autoscale/v1/webhooks/urls.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ import "github.com/rackspace/gophercloud"
55
func listURL(c *gophercloud.ServiceClient, groupID, policyID string) string {
66
return c.ServiceURL("groups", groupID, "policies", policyID, "webhooks")
77
}
8+
9+
func createURL(c *gophercloud.ServiceClient, groupID, policyID string) string {
10+
return c.ServiceURL("groups", groupID, "policies", policyID, "webhooks")
11+
}

0 commit comments

Comments
 (0)