From 75c4c0394b16c875970e14a410d57be499c641b3 Mon Sep 17 00:00:00 2001 From: Scott McAllister Date: Wed, 29 Apr 2020 15:47:00 -0700 Subject: [PATCH 1/5] adding priority to erb nav --- website/pagerduty.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/pagerduty.erb b/website/pagerduty.erb index ac3fe0f3d..167d5cb67 100644 --- a/website/pagerduty.erb +++ b/website/pagerduty.erb @@ -19,6 +19,9 @@ > pagerduty_extension_schema + > + pagerduty_priority + > pagerduty_schedule From 103f3f5aed16f194782b3e4502b9c1972d2c845f Mon Sep 17 00:00:00 2001 From: Scott McAllister Date: Thu, 28 May 2020 16:35:56 -0700 Subject: [PATCH 2/5] adding data_source_pagerduty_ruleset with tests and docs --- pagerduty/data_source_pagerduty_ruleset.go | 53 +++++++++++++++ .../data_source_pagerduty_ruleset_test.go | 64 +++++++++++++++++++ pagerduty/provider.go | 1 + website/docs/d/ruleset.html.markdown | 60 +++++++++++++++++ website/pagerduty.erb | 3 + 5 files changed, 181 insertions(+) create mode 100644 pagerduty/data_source_pagerduty_ruleset.go create mode 100644 pagerduty/data_source_pagerduty_ruleset_test.go create mode 100644 website/docs/d/ruleset.html.markdown diff --git a/pagerduty/data_source_pagerduty_ruleset.go b/pagerduty/data_source_pagerduty_ruleset.go new file mode 100644 index 000000000..c618876ae --- /dev/null +++ b/pagerduty/data_source_pagerduty_ruleset.go @@ -0,0 +1,53 @@ +package pagerduty + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/heimweh/go-pagerduty/pagerduty" +) + +func dataSourcePagerDutyRuleset() *schema.Resource { + return &schema.Resource{ + Read: dataSourcePagerDutyRulesetRead, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func dataSourcePagerDutyRulesetRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*pagerduty.Client) + + log.Printf("[INFO] Reading PagerDuty ruleset") + + searchName := d.Get("name").(string) + + resp, _, err := client.Rulesets.List() + if err != nil { + return err + } + + var found *pagerduty.Ruleset + + for _, ruleset := range resp.Rulesets { + if ruleset.Name == searchName { + found = ruleset + break + } + } + + if found == nil { + return fmt.Errorf("Unable to locate any ruleset with the name: %s", searchName) + } + + d.SetId(found.ID) + d.Set("name", found.Name) + + return nil +} diff --git a/pagerduty/data_source_pagerduty_ruleset_test.go b/pagerduty/data_source_pagerduty_ruleset_test.go new file mode 100644 index 000000000..a86a73d11 --- /dev/null +++ b/pagerduty/data_source_pagerduty_ruleset_test.go @@ -0,0 +1,64 @@ +package pagerduty + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccDataSourcePagerDutyRuleset_Basic(t *testing.T) { + ruleset := fmt.Sprintf("tf-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourcePagerDutyRulesetConfig(ruleset), + Check: resource.ComposeTestCheckFunc( + testAccDataSourcePagerDutyRuleset("pagerduty_ruleset.test", "data.pagerduty_ruleset.by_name"), + ), + }, + }, + }) +} + +func testAccDataSourcePagerDutyRuleset(src, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + srcR := s.RootModule().Resources[src] + srcA := srcR.Primary.Attributes + + r := s.RootModule().Resources[n] + a := r.Primary.Attributes + + if a["id"] == "" { + return fmt.Errorf("Expected to get a ruleset ID from PagerDuty") + } + + testAtts := []string{"id", "name"} + + for _, att := range testAtts { + if a[att] != srcA[att] { + return fmt.Errorf("Expected the ruleset %s to be: %s, but got: %s", att, srcA[att], a[att]) + } + } + + return nil + } +} + +func testAccDataSourcePagerDutyRulesetConfig(ruleset string) string { + return fmt.Sprintf(` +resource "pagerduty_ruleset" "test" { + name = "%s" +} + +data "pagerduty_ruleset" "by_name" { + name = pagerduty_ruleset.test.name +} +`, ruleset) +} diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 14a25fd8b..7e9e3f937 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -37,6 +37,7 @@ func Provider() terraform.ResourceProvider { "pagerduty_service": dataSourcePagerDutyService(), "pagerduty_business_service": dataSourcePagerDutyBusinessService(), "pagerduty_priority": dataSourcePagerDutyPriority(), + "pagerduty_ruleset": dataSourcePagerDutyRuleset(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/website/docs/d/ruleset.html.markdown b/website/docs/d/ruleset.html.markdown new file mode 100644 index 000000000..bb2045ec4 --- /dev/null +++ b/website/docs/d/ruleset.html.markdown @@ -0,0 +1,60 @@ +--- +layout: "pagerduty" +page_title: "PagerDuty: pagerduty_ruleset" +sidebar_current: "docs-pagerduty-datasource-ruleset" +description: |- + Get information about a ruleset that you have created. +--- + +# pagerduty\_ruleset + +Use this data source to get information about a specific [ruleset][1] that you can use for managing and grouping [event rules][2]. + +## Example Usage + +```hcl +data "pagerduty_ruleset" "example" { + name = "My Ruleset" +} + +resource "pagerduty_ruleset_rule" "foo" { + ruleset = data.pagerduty_ruleset.example.id + position = 0 + disabled = "false" + conditions { + operator = "and" + subconditions { + operator = "contains" + parameter { + value = "disk space" + path = "payload.summary" + } + } + subconditions { + operator = "contains" + parameter { + value = "db" + path = "payload.source" + } + } + } + actions { + route { + value = "P5DTL0K" + } + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the ruleset to find in the PagerDuty API. + +## Attributes Reference +* `id` - The ID of the found ruleset. +* `name` - The name of the found ruleset. + +[1]: https://developer.pagerduty.com/api-reference/reference/REST/openapiv3.json/paths/~1rulesets/get +[2]: https://developer.pagerduty.com/api-reference/reference/REST/openapiv3.json/paths/~1rulesets~1%7Bid%7D~1rules/get diff --git a/website/pagerduty.erb b/website/pagerduty.erb index 167d5cb67..9d284eb70 100644 --- a/website/pagerduty.erb +++ b/website/pagerduty.erb @@ -21,6 +21,9 @@ > pagerduty_priority + + > + pagerduty_ruleset > pagerduty_schedule From 3d81df8f15bf3876faeb7dcc9d54f04ee34f9f42 Mon Sep 17 00:00:00 2001 From: Scott McAllister Date: Thu, 28 May 2020 17:12:46 -0700 Subject: [PATCH 3/5] updating go-pagerduty library dependency --- go.mod | 2 +- go.sum | 2 + pagerduty/provider.go | 2 +- .../heimweh/go-pagerduty/pagerduty/error.go | 2 +- .../go-pagerduty/pagerduty/pagerduty.go | 79 +++++++++++++++---- .../heimweh/go-pagerduty/pagerduty/ruleset.go | 30 ++++++- vendor/modules.txt | 2 +- 7 files changed, 98 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index 0918795e7..214abafc1 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/terraform-providers/terraform-provider-pagerduty require ( github.com/google/go-querystring v1.0.0 // indirect github.com/hashicorp/terraform-plugin-sdk v1.7.0 - github.com/heimweh/go-pagerduty v0.0.0-20200429000711-fdd3a48907e7 + github.com/heimweh/go-pagerduty v0.0.0-20200528011640-24a6d8472a24 ) go 1.13 diff --git a/go.sum b/go.sum index 85683e470..babf2ee12 100644 --- a/go.sum +++ b/go.sum @@ -194,6 +194,8 @@ github.com/heimweh/go-pagerduty v0.0.0-20200415004831-bc2b3224a572 h1:UPbUDXwtlg github.com/heimweh/go-pagerduty v0.0.0-20200415004831-bc2b3224a572/go.mod h1:6+bccpjQ/PM8uQY9m8avM4MJea+3vo3ta9r8kGQ4XFY= github.com/heimweh/go-pagerduty v0.0.0-20200429000711-fdd3a48907e7 h1:8groiuI/kigz8jYT46EKNqDYVcEfSDnhv5p+VgZfPGU= github.com/heimweh/go-pagerduty v0.0.0-20200429000711-fdd3a48907e7/go.mod h1:6+bccpjQ/PM8uQY9m8avM4MJea+3vo3ta9r8kGQ4XFY= +github.com/heimweh/go-pagerduty v0.0.0-20200528011640-24a6d8472a24 h1:ga84s0DaOnrYN7IL7jMug6ins5QpiMuNpXFxCKqFAvg= +github.com/heimweh/go-pagerduty v0.0.0-20200528011640-24a6d8472a24/go.mod h1:6+bccpjQ/PM8uQY9m8avM4MJea+3vo3ta9r8kGQ4XFY= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= diff --git a/pagerduty/provider.go b/pagerduty/provider.go index 7e9e3f937..ab990153a 100644 --- a/pagerduty/provider.go +++ b/pagerduty/provider.go @@ -75,7 +75,7 @@ func Provider() terraform.ResourceProvider { } func isErrCode(err error, code int) bool { - if e, ok := err.(*pagerduty.Error); ok && e.ErrorResponse.StatusCode == code { + if e, ok := err.(*pagerduty.Error); ok && e.ErrorResponse.Response.StatusCode == code { return true } diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/error.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/error.go index e959e40f8..d5a93d160 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/error.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/error.go @@ -28,5 +28,5 @@ type Error struct { } func (e *Error) Error() string { - return fmt.Sprintf("%s API call to %s failed %v. Code: %d, Errors: %v, Message: %s", e.ErrorResponse.Request.Method, e.ErrorResponse.Request.URL.String(), e.ErrorResponse.Response.Status, e.Code, e.Errors, e.Message) + return fmt.Sprintf("%s API call to %s failed %v. Code: %d, Errors: %v, Message: %s", e.ErrorResponse.Response.Request.Method, e.ErrorResponse.Response.Request.URL.String(), e.ErrorResponse.Response.Status, e.Code, e.Errors, e.Message) } diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go index d3f06ba54..9fff32dd8 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/pagerduty.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "io/ioutil" "log" "net/http" "net/url" @@ -54,7 +55,8 @@ type Client struct { // Response is a wrapper around http.Response type Response struct { - *http.Response + Response *http.Response + BodyBytes []byte } // NewClient returns a new PagerDuty API client. @@ -156,16 +158,21 @@ func (c *Client) do(req *http.Request, v interface{}) (*Response, error) { if err != nil { return nil, err } - defer resp.Body.Close() - - response := &Response{resp} + bodyBytes, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + response := &Response{ + Response: resp, + BodyBytes: bodyBytes, + } - if err := checkResponse(response); err != nil { + if err := c.checkResponse(response); err != nil { return response, err } if v != nil { - if err := decodeJSON(response, v); err != nil { + if err := c.DecodeJSON(response, v); err != nil { return response, err } } @@ -173,29 +180,73 @@ func (c *Client) do(req *http.Request, v interface{}) (*Response, error) { return response, nil } +// ListResp represents a list response from the PagerDuty API +type ListResp struct { + Offset int `json:"offset,omitempty"` + Limit int `json:"limit,omitempty"` + More bool `json:"more,omitempty"` + Total int `json:"total,omitempty"` +} + +// responseHandler is capable of parsing a response. At a minimum it must +// extract the page information for the current page. It can also execute +// additional necessary handling; for example, if a closure, it has access +// to the scope in which it was defined, and can be used to append data to +// a specific slice. The responseHandler is responsible for closing the response. +type responseHandler func(response *Response) (ListResp, *Response, error) + +func (c *Client) newRequestPagedGetDo(basePath string, handler responseHandler) error { + // Indicates whether there are still additional pages associated with request. + var stillMore bool + + // Offset to set for the next page request. + var nextOffset int + + // While there are more pages, keep adjusting the offset to get all results. + for stillMore, nextOffset = true, 0; stillMore; { + response, err := c.newRequestDo("GET", fmt.Sprintf("%s?offset=%d", basePath, nextOffset), nil, nil, nil) + if err != nil { + return err + } + + // Call handler to extract page information and execute additional necessary handling. + pageInfo, _, err := handler(response) + if err != nil { + return err + } + + // Bump the offset as necessary and set whether more results exist. + nextOffset = pageInfo.Offset + pageInfo.Limit + stillMore = pageInfo.More + } + + return nil +} + // ValidateAuth validates a token against the PagerDuty API func (c *Client) ValidateAuth() error { _, _, err := c.Abilities.List() return err } -func decodeJSON(res *Response, v interface{}) error { - return json.NewDecoder(res.Body).Decode(v) +// DecodeJSON decodes json body to given interface +func (c *Client) DecodeJSON(res *Response, v interface{}) error { + return json.Unmarshal(res.BodyBytes, v) } -func checkResponse(res *Response) error { - if res.StatusCode >= 200 && res.StatusCode <= 299 { +func (c *Client) checkResponse(res *Response) error { + if res.Response.StatusCode >= 200 && res.Response.StatusCode <= 299 { return nil } - return decodeErrorResponse(res) + return c.decodeErrorResponse(res) } -func decodeErrorResponse(res *Response) error { +func (c *Client) decodeErrorResponse(res *Response) error { // Try to decode error response or fallback with standard error v := &errorResponse{Error: &Error{ErrorResponse: res}} - if err := decodeJSON(res, v); err != nil { - return fmt.Errorf("%s API call to %s failed: %v", res.Request.Method, res.Request.URL.String(), res.Status) + if err := c.DecodeJSON(res, v); err != nil { + return fmt.Errorf("%s API call to %s failed: %v", res.Response.Request.Method, res.Response.Request.URL.String(), res.Response.Status) } return v.Error diff --git a/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go b/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go index a5e93d0e0..0d4891b68 100644 --- a/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go +++ b/vendor/github.com/heimweh/go-pagerduty/pagerduty/ruleset.go @@ -1,6 +1,8 @@ package pagerduty -import "fmt" +import ( + "fmt" +) // RulesetService handles the communication with rulesets // related methods of the PagerDuty API. @@ -138,12 +140,34 @@ func (s *RulesetService) List() (*ListRulesetsResponse, *Response, error) { u := "/rulesets" v := new(ListRulesetsResponse) - resp, err := s.client.newRequestDo("GET", u, nil, nil, &v) + rulesets := make([]*Ruleset, 0) + + // Create a handler closure capable of parsing data from the rulesets endpoint + // and appending resultant rulesets to the return slice. + responseHandler := func(response *Response) (ListResp, *Response, error) { + var result ListRulesetsResponse + + if err := s.client.DecodeJSON(response, &result); err != nil { + return ListResp{}, response, err + } + + rulesets = append(rulesets, result.Rulesets...) + + // Return stats on the current page. Caller can use this information to + // adjust for requesting additional pages. + return ListResp{ + More: result.More, + Offset: result.Offset, + Limit: result.Limit, + }, response, nil + } + err := s.client.newRequestPagedGetDo(u, responseHandler) if err != nil { return nil, nil, err } + v.Rulesets = rulesets - return v, resp, nil + return v, nil, nil } // Create creates a new ruleset. diff --git a/vendor/modules.txt b/vendor/modules.txt index 7e6ecf916..ab8992cc6 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -182,7 +182,7 @@ github.com/hashicorp/terraform-svchost/auth github.com/hashicorp/terraform-svchost/disco # github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d github.com/hashicorp/yamux -# github.com/heimweh/go-pagerduty v0.0.0-20200429000711-fdd3a48907e7 +# github.com/heimweh/go-pagerduty v0.0.0-20200528011640-24a6d8472a24 github.com/heimweh/go-pagerduty/pagerduty # github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af github.com/jmespath/go-jmespath From 34103b3a123fd70c3475c401a3e3578202922f37 Mon Sep 17 00:00:00 2001 From: Scott McAllister Date: Fri, 29 May 2020 08:44:08 -0700 Subject: [PATCH 4/5] updating team_membership and user docs --- website/docs/r/team_membership.html.markdown | 4 +++- website/docs/r/user.html.markdown | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/website/docs/r/team_membership.html.markdown b/website/docs/r/team_membership.html.markdown index 9d6e0c3cc..9dd87e4e3 100644 --- a/website/docs/r/team_membership.html.markdown +++ b/website/docs/r/team_membership.html.markdown @@ -36,7 +36,9 @@ The following arguments are supported: * `user_id` - (Required) The ID of the user to add to the team. * `team_id` - (Required) The ID of the team in which the user will belong. - * `role` - (Optional) The role of the user in the team. One of `observer`, `responder`, or `manager`. Defaults to `manager`. + * `role` - (Optional) The role of the user in the team. One of `observer`, `responder`, or `manager`. Defaults to `manager`. These roles match up to user roles in the following ways: + * User role of `user` is a Team role of `manager` + * User role of `limited_user` is a Team role of `responder` ## Attributes Reference diff --git a/website/docs/r/user.html.markdown b/website/docs/r/user.html.markdown index 0eca710d0..fd9d8b9d8 100644 --- a/website/docs/r/user.html.markdown +++ b/website/docs/r/user.html.markdown @@ -27,7 +27,7 @@ The following arguments are supported: * `name` - (Required) The name of the user. * `email` - (Required) The user's email address. * `color` - (Optional) The schedule color for the user. Valid options are purple, red, green, blue, teal, orange, brown, turquoise, dark-slate-blue, cayenne, orange-red, dark-orchid, dark-slate-grey, lime, dark-magenta, lime-green, midnight-blue, deep-pink, dark-green, dark-orange, dark-cyan, darkolive-green, dark-slate-gray, grey20, firebrick, maroon, crimson, dark-red, dark-goldenrod, chocolate, medium-violet-red, sea-green, olivedrab, forest-green, dark-olive-green, blue-violet, royal-blue, indigo, slate-blue, saddle-brown, or steel-blue. - * `role` - (Optional) The user role. Account must have the `read_only_users` ability to set a user as a `read_only_user`. Can be `admin`, `limited_user`, `observer`, `owner`, `read_only_user` or `user` + * `role` - (Optional) The user role. Account must have the `read_only_users` ability to set a user as a `read_only_user`. Can be `admin`, `limited_user`, `observer`, `owner`, `read_only_user`, `restricted_user`, or `user` * `job_title` - (Optional) The user's title. * `teams` - (Optional, **DEPRECATED**) A list of teams the user should belong to. Please use `pagerduty_team_membership` instead. * `description` - (Optional) A human-friendly description of the user. From 40655a7e07d152f5065ae83b8fb88cd7ce98c524 Mon Sep 17 00:00:00 2001 From: Scott McAllister Date: Fri, 29 May 2020 14:58:08 -0700 Subject: [PATCH 5/5] added account info to priority docs --- website/docs/d/priority.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/d/priority.html.markdown b/website/docs/d/priority.html.markdown index 797a4f09e..d3cf3b675 100644 --- a/website/docs/d/priority.html.markdown +++ b/website/docs/d/priority.html.markdown @@ -8,7 +8,7 @@ description: |- # pagerduty\_priority -Use this data source to get information about a specific [priority][1] that you can use for other PagerDuty resources. +Use this data source to get information about a specific [priority][1] that you can use for other PagerDuty resources. A priority is a label representing the importance and impact of an incident. This feature is only available on Standard and Enterprise plans. ## Example Usage