diff --git a/Gopkg.lock b/Gopkg.lock index f8b5d790..7eb0e945 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -17,6 +17,14 @@ pruneopts = "UT" revision = "2aa6f33b730c79971cfc3c742f279195b0abc627" +[[projects]] + digest = "1:3bb331d3045ee55402a226f6ab0f005cbc09527df714278c3925d4700db79260" + name = "github.com/PagerDuty/go-pagerduty" + packages = ["."] + pruneopts = "UT" + revision = "b4a4067bdbde86de1d3fdf15c3c01e76bee9127c" + version = "1.0.4" + [[projects]] digest = "1:e92f5581902c345eb4ceffdcd4a854fb8f73cf436d47d837d1ec98ef1fe0a214" name = "github.com/StackExchange/wmi" @@ -430,6 +438,7 @@ analyzer-version = 1 input-imports = [ "code.cloudfoundry.org/bytefmt", + "github.com/PagerDuty/go-pagerduty", "github.com/adlio/trello", "github.com/alecthomas/chroma/formatters", "github.com/alecthomas/chroma/lexers", diff --git a/main.go b/main.go index 360a6825..7824a136 100644 --- a/main.go +++ b/main.go @@ -43,6 +43,7 @@ import ( "github.com/wtfutil/wtf/mercurial" "github.com/wtfutil/wtf/newrelic" "github.com/wtfutil/wtf/opsgenie" + "github.com/wtfutil/wtf/pagerduty" "github.com/wtfutil/wtf/power" "github.com/wtfutil/wtf/resourceusage" "github.com/wtfutil/wtf/security" @@ -223,6 +224,8 @@ func addWidget(app *tview.Application, pages *tview.Pages, widgetName string) { widgets = append(widgets, newrelic.NewWidget(app)) case "opsgenie": widgets = append(widgets, opsgenie.NewWidget(app)) + case "pagerduty": + widgets = append(widgets, pagerduty.NewWidget(app)) case "power": widgets = append(widgets, power.NewWidget(app)) case "prettyweather": @@ -256,6 +259,7 @@ func addWidget(app *tview.Application, pages *tview.Pages, widgetName string) { case "zendesk": widgets = append(widgets, zendesk.NewWidget(app)) default: + panic(widgetName) } } diff --git a/pagerduty/client.go b/pagerduty/client.go new file mode 100644 index 00000000..e6945a34 --- /dev/null +++ b/pagerduty/client.go @@ -0,0 +1,45 @@ +package pagerduty + +import ( + "os" + "time" + + "github.com/PagerDuty/go-pagerduty" + "github.com/wtfutil/wtf/wtf" +) + +// GetOnCalls returns a list of people currently on call +func GetOnCalls() ([]pagerduty.OnCall, error) { + client := pagerduty.NewClient(apiKey()) + + var results []pagerduty.OnCall + + var queryOpts pagerduty.ListOnCallOptions + queryOpts.Since = time.Now().Format("2006-01-02T15:04:05Z07:00") + queryOpts.Until = time.Now().Format("2006-01-02T15:04:05Z07:00") + + oncalls, err := client.ListOnCalls(queryOpts) + if err != nil { + return nil, err + } + + results = append(results, oncalls.OnCalls...) + + for oncalls.APIListObject.More == true { + queryOpts.APIListObject.Offset = oncalls.APIListObject.Offset + oncalls, err = client.ListOnCalls(queryOpts) + if err != nil { + return nil, err + } + results = append(results, oncalls.OnCalls...) + } + + return results, nil +} + +func apiKey() string { + return wtf.Config.UString( + "wtf.mods.pagerduty.apiKey", + os.Getenv("WTF_PAGERDUTY_API_KEY"), + ) +} diff --git a/pagerduty/sort.go b/pagerduty/sort.go new file mode 100644 index 00000000..06ccf549 --- /dev/null +++ b/pagerduty/sort.go @@ -0,0 +1,12 @@ +package pagerduty + +import "github.com/PagerDuty/go-pagerduty" + +type ByEscalationLevel []pagerduty.OnCall + +func (s ByEscalationLevel) Len() int { return len(s) } +func (s ByEscalationLevel) Swap(i, j int) { s[i], s[j] = s[j], s[i] } + +func (s ByEscalationLevel) Less(i, j int) bool { + return s[i].EscalationLevel < s[j].EscalationLevel +} diff --git a/pagerduty/widget.go b/pagerduty/widget.go new file mode 100644 index 00000000..38e0fa44 --- /dev/null +++ b/pagerduty/widget.go @@ -0,0 +1,83 @@ +package pagerduty + +import ( + "fmt" + "sort" + + "github.com/PagerDuty/go-pagerduty" + "github.com/rivo/tview" + "github.com/wtfutil/wtf/wtf" +) + +type Widget struct { + wtf.TextWidget +} + +func NewWidget(app *tview.Application) *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(app, "PagerDuty", "pagerduty", false), + } + + return &widget +} + +/* -------------------- Exported Functions -------------------- */ + +func (widget *Widget) Refresh() { + onCalls, err := GetOnCalls() + + widget.View.SetTitle(widget.ContextualTitle(fmt.Sprintf("%s", widget.Name))) + widget.View.Clear() + + var content string + if err != nil { + widget.View.SetWrap(true) + content = err.Error() + } else { + widget.View.SetWrap(false) + content = widget.contentFrom(onCalls) + } + + widget.View.SetText(content) +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(onCalls []pagerduty.OnCall) string { + var str string + + tree := make(map[string][]pagerduty.OnCall) + + filtering := wtf.Config.UList("wtf.mods.pagerduty.escalationFilter") + filter := make(map[string]bool) + for _, item := range filtering { + filter[item.(string)] = true + } + + for _, onCall := range onCalls { + key := onCall.EscalationPolicy.Summary + if len(filtering) == 0 || filter[key] { + tree[key] = append(tree[key], onCall) + } + } + + // We want to sort our escalation policies for predictability/ease of finding + keys := make([]string, 0, len(tree)) + for k := range tree { + keys = append(keys, k) + } + + sort.Strings(keys) + + // Print out policies, and escalation order of users + for _, key := range keys { + str = str + fmt.Sprintf("[red]%s\n", key) + values := tree[key] + sort.Sort(ByEscalationLevel(values)) + for _, item := range values { + str = str + fmt.Sprintf("[white]%d - %s\n", item.EscalationLevel, item.User.Summary) + } + } + + return str +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/.gitignore b/vendor/github.com/PagerDuty/go-pagerduty/.gitignore new file mode 100644 index 00000000..dc0fe944 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/.gitignore @@ -0,0 +1,2 @@ +bin/* +*.swp diff --git a/vendor/github.com/PagerDuty/go-pagerduty/.goreleaser.yml b/vendor/github.com/PagerDuty/go-pagerduty/.goreleaser.yml new file mode 100644 index 00000000..4ecd2cbe --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/.goreleaser.yml @@ -0,0 +1,33 @@ +project_name: go-pagerduty +release: + github: + owner: PagerDuty + name: go-pagerduty + draft: false + prerelease: true + name_template: "{{.ProjectName}}-v{{.Version}}" +builds: +- goos: + - linux + - darwin + - windows + goarch: + - amd64 + - 386 + main: ./command/*.go + binary: pd +archive: + format: tar.gz + format_overrides: + - goos: windows + format: zip + replacements: + amd64: 64-bit + darwin: macOS + linux: Tux + name_template: "{{.Binary}}_{{.Version}}_{{.Os}}-{{.Arch}}" + files: + - LICENSE.txt + - README.md + - examples/* + - CHANGELOG.md \ No newline at end of file diff --git a/vendor/github.com/PagerDuty/go-pagerduty/.travis.yml b/vendor/github.com/PagerDuty/go-pagerduty/.travis.yml new file mode 100644 index 00000000..746f6607 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/.travis.yml @@ -0,0 +1,24 @@ +language: go + +addons: + apt: + packages: + # needed for the nfpm pipe: + - rpm + +# needed for the docker pipe +# services: +# - docker + +# calls goreleaser +deploy: + skip_cleanup: true + provider: script + script: make deploy + on: + tags: true + notifications: + email: false + on: + tags: true + condition: $TRAVIS_OS_NAME = linux \ No newline at end of file diff --git a/vendor/github.com/PagerDuty/go-pagerduty/CHANGELOG.md b/vendor/github.com/PagerDuty/go-pagerduty/CHANGELOG.md new file mode 100644 index 00000000..5936ccc3 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/CHANGELOG.md @@ -0,0 +1,89 @@ +# Change Log + +## [1.0.0](https://github.com/PagerDuty/go-pagerduty/tree/1.0.0) (2018-05-28) +**Fixed bugs:** + +- Escalation Policy's repeat\_enabled Is Ignored [\#57](https://github.com/PagerDuty/go-pagerduty/issues/57) +- Problems running freshly built pd utility [\#39](https://github.com/PagerDuty/go-pagerduty/issues/39) +- Manage Incident gives error [\#32](https://github.com/PagerDuty/go-pagerduty/issues/32) +- Added missing slash to delete integration method url [\#59](https://github.com/PagerDuty/go-pagerduty/pull/59) ([jescochu](https://github.com/jescochu)) + +**Closed issues:** + +- Trouble creating an integration [\#102](https://github.com/PagerDuty/go-pagerduty/issues/102) +- Client does not trigger events [\#101](https://github.com/PagerDuty/go-pagerduty/issues/101) +- Paging help [\#94](https://github.com/PagerDuty/go-pagerduty/issues/94) +- Help with incident creation API [\#89](https://github.com/PagerDuty/go-pagerduty/issues/89) +- Memory leak because of response body is not closed [\#66](https://github.com/PagerDuty/go-pagerduty/issues/66) +- Since and Until don't work for log\_entries [\#61](https://github.com/PagerDuty/go-pagerduty/issues/61) +- service: auto\_resolve\_timeout & acknowledgement\_timeout cannot be set to null [\#51](https://github.com/PagerDuty/go-pagerduty/issues/51) +- Possible to create new service and integration together [\#42](https://github.com/PagerDuty/go-pagerduty/issues/42) +- Documentation does not match code [\#16](https://github.com/PagerDuty/go-pagerduty/issues/16) +- Typo in repo description [\#15](https://github.com/PagerDuty/go-pagerduty/issues/15) +- Webhook decoder [\#14](https://github.com/PagerDuty/go-pagerduty/issues/14) +- incident\_key for create\_event [\#13](https://github.com/PagerDuty/go-pagerduty/issues/13) + +**Merged pull requests:** + +- Fix pagination for ListOnCalls [\#90](https://github.com/PagerDuty/go-pagerduty/pull/90) ([IainCole](https://github.com/IainCole)) +- Revert "Fix inconsistency with some REST Options objects passed by reference …" [\#88](https://github.com/PagerDuty/go-pagerduty/pull/88) ([mimato](https://github.com/mimato)) +- Adding travis config, fixup Makefile [\#87](https://github.com/PagerDuty/go-pagerduty/pull/87) ([mimato](https://github.com/mimato)) +- Fixed invalid JSON descriptor for FirstTriggerLogEntry [\#86](https://github.com/PagerDuty/go-pagerduty/pull/86) ([mwisniewski0](https://github.com/mwisniewski0)) +- \[incidents\] fix entries typo in a few places [\#85](https://github.com/PagerDuty/go-pagerduty/pull/85) ([joeyparsons](https://github.com/joeyparsons)) +- Fix inconsistency with some REST Options objects passed by reference … [\#79](https://github.com/PagerDuty/go-pagerduty/pull/79) ([lowesoftware](https://github.com/lowesoftware)) +- Explicit JSON reference to schedules [\#77](https://github.com/PagerDuty/go-pagerduty/pull/77) ([domudall](https://github.com/domudall)) +- Adding AlertCreation to Service struct [\#76](https://github.com/PagerDuty/go-pagerduty/pull/76) ([domudall](https://github.com/domudall)) +- Add support for escalation rules [\#71](https://github.com/PagerDuty/go-pagerduty/pull/71) ([heimweh](https://github.com/heimweh)) +- Fix maintenance window JSON [\#69](https://github.com/PagerDuty/go-pagerduty/pull/69) ([domudall](https://github.com/domudall)) +- Fixing Maintenance typo [\#68](https://github.com/PagerDuty/go-pagerduty/pull/68) ([domudall](https://github.com/domudall)) +- Update event.go - fix a memory leak [\#65](https://github.com/PagerDuty/go-pagerduty/pull/65) ([AngelRefael](https://github.com/AngelRefael)) +- Add query to vendor [\#64](https://github.com/PagerDuty/go-pagerduty/pull/64) ([heimweh](https://github.com/heimweh)) +- Fix JSON decode \(errorObject\) [\#63](https://github.com/PagerDuty/go-pagerduty/pull/63) ([heimweh](https://github.com/heimweh)) +- fix since and until by adding them to url scheme [\#60](https://github.com/PagerDuty/go-pagerduty/pull/60) ([ethansommer](https://github.com/ethansommer)) +- fix webhook struct member name [\#58](https://github.com/PagerDuty/go-pagerduty/pull/58) ([pgray](https://github.com/pgray)) +- Incident - Add status field to incident [\#56](https://github.com/PagerDuty/go-pagerduty/pull/56) ([heimweh](https://github.com/heimweh)) +- enable fetch log entries via incident api [\#55](https://github.com/PagerDuty/go-pagerduty/pull/55) ([flyinprogrammer](https://github.com/flyinprogrammer)) +- Allow service timeouts to be disabled [\#53](https://github.com/PagerDuty/go-pagerduty/pull/53) ([heimweh](https://github.com/heimweh)) +- Schedule restriction - Add support for start\_day\_of\_week [\#52](https://github.com/PagerDuty/go-pagerduty/pull/52) ([heimweh](https://github.com/heimweh)) +- Add vendor support [\#49](https://github.com/PagerDuty/go-pagerduty/pull/49) ([heimweh](https://github.com/heimweh)) +- Add schedules listing [\#46](https://github.com/PagerDuty/go-pagerduty/pull/46) ([Marc-Morata-Fite](https://github.com/Marc-Morata-Fite)) +- dont declare main twice in examples [\#45](https://github.com/PagerDuty/go-pagerduty/pull/45) ([ranjib](https://github.com/ranjib)) +- add service show [\#44](https://github.com/PagerDuty/go-pagerduty/pull/44) ([cmluciano](https://github.com/cmluciano)) +- \(feat\)implement integration creation [\#43](https://github.com/PagerDuty/go-pagerduty/pull/43) ([ranjib](https://github.com/ranjib)) +- \(chore\)add create event example [\#41](https://github.com/PagerDuty/go-pagerduty/pull/41) ([ranjib](https://github.com/ranjib)) +- \(bug\)Add test. fix version issue [\#40](https://github.com/PagerDuty/go-pagerduty/pull/40) ([ranjib](https://github.com/ranjib)) +- Remove subdomain argument from escalation\_policy example. [\#38](https://github.com/PagerDuty/go-pagerduty/pull/38) ([cmluciano](https://github.com/cmluciano)) +- Skip JSON encoding if no payload was given [\#37](https://github.com/PagerDuty/go-pagerduty/pull/37) ([heimweh](https://github.com/heimweh)) +- \(feat\)add ability API and CLI [\#36](https://github.com/PagerDuty/go-pagerduty/pull/36) ([ranjib](https://github.com/ranjib)) +- Make updates to Escalation Policies work [\#35](https://github.com/PagerDuty/go-pagerduty/pull/35) ([heimweh](https://github.com/heimweh)) +- Fix misspelling in User struct and add JSON tags [\#34](https://github.com/PagerDuty/go-pagerduty/pull/34) ([heimweh](https://github.com/heimweh)) +- \(bug\)allow passing headers in http do call. fix manage incident call [\#33](https://github.com/PagerDuty/go-pagerduty/pull/33) ([ranjib](https://github.com/ranjib)) +- \(chore\)get rid of logrus from all core structs except CLI entries. fix schedule override command [\#31](https://github.com/PagerDuty/go-pagerduty/pull/31) ([ranjib](https://github.com/ranjib)) +- \(bug\)rename override struct [\#30](https://github.com/PagerDuty/go-pagerduty/pull/30) ([ranjib](https://github.com/ranjib)) +- \(bug\)implement schedule override [\#29](https://github.com/PagerDuty/go-pagerduty/pull/29) ([ranjib](https://github.com/ranjib)) +- fix misspelling in trigger\_summary\_data's JSON key. [\#28](https://github.com/PagerDuty/go-pagerduty/pull/28) ([tomwans](https://github.com/tomwans)) +- Correctly set meta flag for incident list [\#26](https://github.com/PagerDuty/go-pagerduty/pull/26) ([afirth](https://github.com/afirth)) +- Add \*.swp to gitignore [\#25](https://github.com/PagerDuty/go-pagerduty/pull/25) ([afirth](https://github.com/afirth)) +- Support the /oncalls endpoint in the CLI [\#24](https://github.com/PagerDuty/go-pagerduty/pull/24) ([afirth](https://github.com/afirth)) +- Refactor to work correctly with V2 API [\#23](https://github.com/PagerDuty/go-pagerduty/pull/23) ([dthagard](https://github.com/dthagard)) +- \(feat\)Add webhook decoding capability [\#22](https://github.com/PagerDuty/go-pagerduty/pull/22) ([ranjib](https://github.com/ranjib)) +- \(chore\)Decode event API response. [\#21](https://github.com/PagerDuty/go-pagerduty/pull/21) ([ranjib](https://github.com/ranjib)) +- \(bug\)add incident\_key field in event api client [\#20](https://github.com/PagerDuty/go-pagerduty/pull/20) ([ranjib](https://github.com/ranjib)) +- \(chore\)nuke sub domain, v2 api does not need one [\#19](https://github.com/PagerDuty/go-pagerduty/pull/19) ([ranjib](https://github.com/ranjib)) +- Implement list users CLI [\#17](https://github.com/PagerDuty/go-pagerduty/pull/17) ([ranjib](https://github.com/ranjib)) +- Add team\_ids\[\] query string arg [\#12](https://github.com/PagerDuty/go-pagerduty/pull/12) ([marklap](https://github.com/marklap)) +- Incidents fix [\#11](https://github.com/PagerDuty/go-pagerduty/pull/11) ([jareksm](https://github.com/jareksm)) +- Added APIListObject to Option types to allow setting offset and [\#10](https://github.com/PagerDuty/go-pagerduty/pull/10) ([jareksm](https://github.com/jareksm)) +- fix typo [\#9](https://github.com/PagerDuty/go-pagerduty/pull/9) ([sjansen](https://github.com/sjansen)) +- implement incident list cli. event posting api [\#8](https://github.com/PagerDuty/go-pagerduty/pull/8) ([ranjib](https://github.com/ranjib)) +- CLI for create escalation policy, maintainenance window , schedule ov… [\#7](https://github.com/PagerDuty/go-pagerduty/pull/7) ([ranjib](https://github.com/ranjib)) +- \(feat\)implement create service cli [\#6](https://github.com/PagerDuty/go-pagerduty/pull/6) ([ranjib](https://github.com/ranjib)) +- \(feat\)list service cli [\#5](https://github.com/PagerDuty/go-pagerduty/pull/5) ([ranjib](https://github.com/ranjib)) +- \(feat\)implement addon update/delete [\#4](https://github.com/PagerDuty/go-pagerduty/pull/4) ([ranjib](https://github.com/ranjib)) +- \(feat\)Show addon cli [\#3](https://github.com/PagerDuty/go-pagerduty/pull/3) ([ranjib](https://github.com/ranjib)) +- \(feat\) addon list api. create cli [\#2](https://github.com/PagerDuty/go-pagerduty/pull/2) ([ranjib](https://github.com/ranjib)) +- \(chore\) list addon [\#1](https://github.com/PagerDuty/go-pagerduty/pull/1) ([ranjib](https://github.com/ranjib)) + + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/vendor/github.com/PagerDuty/go-pagerduty/Dockerfile b/vendor/github.com/PagerDuty/go-pagerduty/Dockerfile new file mode 100644 index 00000000..650a6921 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/Dockerfile @@ -0,0 +1,4 @@ +FROM golang +ADD . /go/src/github.com/PagerDuty/go-pagerduty +WORKDIR /go/src/github.com/PagerDuty/go-pagerduty +RUN go get ./... && go test -v -race -cover ./... diff --git a/vendor/github.com/PagerDuty/go-pagerduty/LICENSE.txt b/vendor/github.com/PagerDuty/go-pagerduty/LICENSE.txt new file mode 100644 index 00000000..0c80aa6c --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright:: Copyright (c) 2016 PagerDuty, Inc. +License:: Apache License, Version 2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/vendor/github.com/PagerDuty/go-pagerduty/Makefile b/vendor/github.com/PagerDuty/go-pagerduty/Makefile new file mode 100644 index 00000000..2e075a69 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/Makefile @@ -0,0 +1,23 @@ +# SOURCEDIR=. +# SOURCES = $(shell find $(SOURCEDIR) -name '*.go') +# VERSION=$(git describe --always --tags) +# BINARY=bin/pd + +# bin: $(BINARY) + +# $(BINARY): $(SOURCES) +# go build -o $(BINARY) command/* + +.PHONY: build +build: + go get ./... + # go test -v -race -cover ./... + # go tool vet $(SOURCES) + +.PHONY: test +test: + go test ./... + +deploy: + - curl -sL https://git.io/goreleaser | bash + diff --git a/vendor/github.com/PagerDuty/go-pagerduty/README.md b/vendor/github.com/PagerDuty/go-pagerduty/README.md new file mode 100644 index 00000000..b1878806 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/README.md @@ -0,0 +1,73 @@ +# go-pagerduty + +go-pagerduty is a CLI and [go](https://golang.org/) client library for [PagerDuty v2 API](https://v2.developer.pagerduty.com/v2/page/api-reference). +[godoc](http://godoc.org/github.com/PagerDuty/go-pagerduty) + +## Installation + +``` +go get github.com/PagerDuty/go-pagerduty +``` + +## Usage + +### CLI + +The CLI requires authentication token, which can be sepcified in `.pd.yml` +file in home directory of the user, or passed as command line argument. +Example of config file: + +```yaml +--- +authtoken: fooBar +``` + +`pd` command provides a single entrypoint for all the API endpoints, with individual +API represented by their own sub commands. For an exhaustive list of sub-commands, try: + +``` +pd --help +``` + +An example of the `service` sub-command + +``` +pd service list +``` + + +### From golang libraries + +```go +package main + +import ( + "fmt" + "github.com/PagerDuty/go-pagerduty" +) + +var authtoken = "" // Set your auth token here + +func main() { + var opts pagerduty.ListEscalationPoliciesOptions + client := pagerduty.NewClient(authtoken) + if eps, err := client.ListEscalationPolicies(opts); err != nil { + panic(err) + } else { + for _, p := range eps.EscalationPolicies { + fmt.Println(p.Name) + } + } +} +``` + +## License +[Apache 2](http://www.apache.org/licenses/LICENSE-2.0) + +## Contributing + +1. Fork it ( https://github.com/PagerDuty/go-pagerduty/fork ) +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Commit your changes (`git commit -am 'Add some feature'`) +4. Push to the branch (`git push origin my-new-feature`) +5. Create a new Pull Request diff --git a/vendor/github.com/PagerDuty/go-pagerduty/ability.go b/vendor/github.com/PagerDuty/go-pagerduty/ability.go new file mode 100644 index 00000000..26fe9096 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/ability.go @@ -0,0 +1,22 @@ +package pagerduty + +// ListAbilityResponse is the response when calling the ListAbility API endpoint. +type ListAbilityResponse struct { + Abilities []string `json:"abilities"` +} + +// ListAbilities lists all abilities on your account. +func (c *Client) ListAbilities() (*ListAbilityResponse, error) { + resp, err := c.get("/abilities") + if err != nil { + return nil, err + } + var result ListAbilityResponse + return &result, c.decodeJSON(resp, &result) +} + +// TestAbility Check if your account has the given ability. +func (c *Client) TestAbility(ability string) error { + _, err := c.get("/abilities/" + ability) + return err +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/addon.go b/vendor/github.com/PagerDuty/go-pagerduty/addon.go new file mode 100644 index 00000000..ae9d4e57 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/addon.go @@ -0,0 +1,96 @@ +package pagerduty + +import ( + "fmt" + "github.com/google/go-querystring/query" + "net/http" +) + +// Addon is a third-party add-on to PagerDuty's UI. +type Addon struct { + APIObject + Name string `json:"name,omitempty"` + Src string `json:"src,omitempty"` + Services []APIObject `json:"services,omitempty"` +} + +// ListAddonOptions are the options available when calling the ListAddons API endpoint. +type ListAddonOptions struct { + APIListObject + Includes []string `url:"include,omitempty,brackets"` + ServiceIDs []string `url:"service_ids,omitempty,brackets"` + Filter string `url:"filter,omitempty"` +} + +// ListAddonResponse is the response when calling the ListAddons API endpoint. +type ListAddonResponse struct { + APIListObject + Addons []Addon `json:"addons"` +} + +// ListAddons lists all of the add-ons installed on your account. +func (c *Client) ListAddons(o ListAddonOptions) (*ListAddonResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/addons?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListAddonResponse + return &result, c.decodeJSON(resp, &result) +} + +// InstallAddon installs an add-on for your account. +func (c *Client) InstallAddon(a Addon) (*Addon, error) { + data := make(map[string]Addon) + data["addon"] = a + resp, err := c.post("/addons", data) + defer resp.Body.Close() + if err != nil { + return nil, err + } + if resp.StatusCode != http.StatusCreated { + return nil, fmt.Errorf("Failed to create. HTTP Status code: %d", resp.StatusCode) + } + return getAddonFromResponse(c, resp) +} + +// DeleteAddon deletes an add-on from your account. +func (c *Client) DeleteAddon(id string) error { + _, err := c.delete("/addons/" + id) + return err +} + +// GetAddon gets details about an existing add-on. +func (c *Client) GetAddon(id string) (*Addon, error) { + resp, err := c.get("/addons/" + id) + if err != nil { + return nil, err + } + return getAddonFromResponse(c, resp) +} + +// UpdateAddon updates an existing add-on. +func (c *Client) UpdateAddon(id string, a Addon) (*Addon, error) { + v := make(map[string]Addon) + v["addon"] = a + resp, err := c.put("/addons/"+id, v, nil) + if err != nil { + return nil, err + } + return getAddonFromResponse(c, resp) +} + +func getAddonFromResponse(c *Client, resp *http.Response) (*Addon, error) { + var result map[string]Addon + if err := c.decodeJSON(resp, &result); err != nil { + return nil, err + } + a, ok := result["addon"] + if !ok { + return nil, fmt.Errorf("JSON response does not have 'addon' field") + } + return &a, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/client.go b/vendor/github.com/PagerDuty/go-pagerduty/client.go new file mode 100644 index 00000000..7613684c --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/client.go @@ -0,0 +1,132 @@ +package pagerduty + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" +) + +const ( + apiEndpoint = "https://api.pagerduty.com" +) + +// APIObject represents generic api json response that is shared by most +// domain object (like escalation +type APIObject struct { + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + Summary string `json:"summary,omitempty"` + Self string `json:"self,omitempty"` + HTMLURL string `json:"html_url,omitempty"` +} + +// APIListObject are the fields used to control pagination when listing objects. +type APIListObject struct { + Limit uint `url:"limit,omitempty"` + Offset uint `url:"offset,omitempty"` + More bool `url:"more,omitempty"` + Total uint `url:"total,omitempty"` +} + +// APIReference are the fields required to reference another API object. +type APIReference struct { + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` +} + +type errorObject struct { + Code int `json:"code,omitempty"` + Message string `json:"message,omitempty"` + Errors interface{} `json:"errors,omitempty"` +} + +// Client wraps http client +type Client struct { + authToken string +} + +// NewClient creates an API client +func NewClient(authToken string) *Client { + return &Client{ + authToken: authToken, + } +} + +func (c *Client) delete(path string) (*http.Response, error) { + return c.do("DELETE", path, nil, nil) +} + +func (c *Client) put(path string, payload interface{}, headers *map[string]string) (*http.Response, error) { + + if payload != nil { + data, err := json.Marshal(payload) + if err != nil { + return nil, err + } + return c.do("PUT", path, bytes.NewBuffer(data), headers) + } + return c.do("PUT", path, nil, headers) +} + +func (c *Client) post(path string, payload interface{}) (*http.Response, error) { + data, err := json.Marshal(payload) + if err != nil { + return nil, err + } + return c.do("POST", path, bytes.NewBuffer(data), nil) +} + +func (c *Client) get(path string) (*http.Response, error) { + return c.do("GET", path, nil, nil) +} + +func (c *Client) do(method, path string, body io.Reader, headers *map[string]string) (*http.Response, error) { + endpoint := apiEndpoint + path + req, _ := http.NewRequest(method, endpoint, body) + req.Header.Set("Accept", "application/vnd.pagerduty+json;version=2") + if headers != nil { + for k, v := range *headers { + req.Header.Set(k, v) + } + } + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Authorization", "Token token="+c.authToken) + + resp, err := http.DefaultClient.Do(req) + return c.checkResponse(resp, err) +} + +func (c *Client) decodeJSON(resp *http.Response, payload interface{}) error { + defer resp.Body.Close() + decoder := json.NewDecoder(resp.Body) + return decoder.Decode(payload) +} + +func (c *Client) checkResponse(resp *http.Response, err error) (*http.Response, error) { + if err != nil { + return resp, fmt.Errorf("Error calling the API endpoint: %v", err) + } + if 199 >= resp.StatusCode || 300 <= resp.StatusCode { + var eo *errorObject + var getErr error + if eo, getErr = c.getErrorFromResponse(resp); getErr != nil { + return resp, fmt.Errorf("Response did not contain formatted error: %s. HTTP response code: %v. Raw response: %+v", getErr, resp.StatusCode, resp) + } + return resp, fmt.Errorf("Failed call API endpoint. HTTP response code: %v. Error: %v", resp.StatusCode, eo) + } + return resp, nil +} + +func (c *Client) getErrorFromResponse(resp *http.Response) (*errorObject, error) { + var result map[string]errorObject + if err := c.decodeJSON(resp, &result); err != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", err) + } + s, ok := result["error"] + if !ok { + return nil, fmt.Errorf("JSON response does not have error field") + } + return &s, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/escalation_policy.go b/vendor/github.com/PagerDuty/go-pagerduty/escalation_policy.go new file mode 100644 index 00000000..a8663df2 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/escalation_policy.go @@ -0,0 +1,186 @@ +package pagerduty + +import ( + "fmt" + "net/http" + + "github.com/google/go-querystring/query" +) + +const ( + escPath = "/escalation_policies" +) + +// EscalationRule is a rule for an escalation policy to trigger. +type EscalationRule struct { + ID string `json:"id,omitempty"` + Delay uint `json:"escalation_delay_in_minutes,omitempty"` + Targets []APIObject `json:"targets"` +} + +// EscalationPolicy is a collection of escalation rules. +type EscalationPolicy struct { + APIObject + Name string `json:"name,omitempty"` + EscalationRules []EscalationRule `json:"escalation_rules,omitempty"` + Services []APIReference `json:"services,omitempty"` + NumLoops uint `json:"num_loops,omitempty"` + Teams []APIReference `json:"teams,omitempty"` + Description string `json:"description,omitempty"` + RepeatEnabled bool `json:"repeat_enabled,omitempty"` +} + +// ListEscalationPoliciesResponse is the data structure returned from calling the ListEscalationPolicies API endpoint. +type ListEscalationPoliciesResponse struct { + APIListObject + EscalationPolicies []EscalationPolicy `json:"escalation_policies"` +} + +type ListEscalationRulesResponse struct { + APIListObject + EscalationRules []EscalationRule `json:"escalation_rules"` +} + +// ListEscalationPoliciesOptions is the data structure used when calling the ListEscalationPolicies API endpoint. +type ListEscalationPoliciesOptions struct { + APIListObject + Query string `url:"query,omitempty"` + UserIDs []string `url:"user_ids,omitempty,brackets"` + TeamIDs []string `url:"team_ids,omitempty,brackets"` + Includes []string `url:"include,omitempty,brackets"` + SortBy string `url:"sort_by,omitempty"` +} + +// GetEscalationRuleOptions is the data structure used when calling the GetEscalationRule API endpoint. +type GetEscalationRuleOptions struct { + Includes []string `url:"include,omitempty,brackets"` +} + +// ListEscalationPolicies lists all of the existing escalation policies. +func (c *Client) ListEscalationPolicies(o ListEscalationPoliciesOptions) (*ListEscalationPoliciesResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get(escPath + "?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListEscalationPoliciesResponse + return &result, c.decodeJSON(resp, &result) +} + +// CreateEscalationPolicy creates a new escalation policy. +func (c *Client) CreateEscalationPolicy(e EscalationPolicy) (*EscalationPolicy, error) { + data := make(map[string]EscalationPolicy) + data["escalation_policy"] = e + resp, err := c.post(escPath, data) + return getEscalationPolicyFromResponse(c, resp, err) +} + +// DeleteEscalationPolicy deletes an existing escalation policy and rules. +func (c *Client) DeleteEscalationPolicy(id string) error { + _, err := c.delete(escPath + "/" + id) + return err +} + +// GetEscalationPolicyOptions is the data structure used when calling the GetEscalationPolicy API endpoint. +type GetEscalationPolicyOptions struct { + Includes []string `url:"include,omitempty,brackets"` +} + +// GetEscalationPolicy gets information about an existing escalation policy and its rules. +func (c *Client) GetEscalationPolicy(id string, o *GetEscalationPolicyOptions) (*EscalationPolicy, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get(escPath + "/" + id + "?" + v.Encode()) + return getEscalationPolicyFromResponse(c, resp, err) +} + +// UpdateEscalationPolicy updates an existing escalation policy and its rules. +func (c *Client) UpdateEscalationPolicy(id string, e *EscalationPolicy) (*EscalationPolicy, error) { + data := make(map[string]EscalationPolicy) + data["escalation_policy"] = *e + resp, err := c.put(escPath+"/"+id, data, nil) + return getEscalationPolicyFromResponse(c, resp, err) +} + +// CreateEscalationRule creates a new escalation rule for an escalation policy +// and appends it to the end of the existing escalation rules. +func (c *Client) CreateEscalationRule(escID string, e EscalationRule) (*EscalationRule, error) { + data := make(map[string]EscalationRule) + data["escalation_rule"] = e + resp, err := c.post(escPath+"/"+escID+"/escalation_rules", data) + return getEscalationRuleFromResponse(c, resp, err) +} + +// GetEscalationRule gets information about an existing escalation rule. +func (c *Client) GetEscalationRule(escID string, id string, o *GetEscalationRuleOptions) (*EscalationRule, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get(escPath + "/" + escID + "/escalation_rules/" + id + "?" + v.Encode()) + return getEscalationRuleFromResponse(c, resp, err) +} + +// DeleteEscalationRule deletes an existing escalation rule. +func (c *Client) DeleteEscalationRule(escID string, id string) error { + _, err := c.delete(escPath + "/" + escID + "/escalation_rules/" + id) + return err +} + +// UpdateEscalationRule updates an existing escalation rule. +func (c *Client) UpdateEscalationRule(escID string, id string, e *EscalationRule) (*EscalationRule, error) { + data := make(map[string]EscalationRule) + data["escalation_rule"] = *e + resp, err := c.put(escPath+"/"+escID+"/escalation_rules/"+id, data, nil) + return getEscalationRuleFromResponse(c, resp, err) +} + +// ListEscalationRules lists all of the escalation rules for an existing escalation policy. +func (c *Client) ListEscalationRules(escID string) (*ListEscalationRulesResponse, error) { + resp, err := c.get(escPath + "/" + escID + "/escalation_rules") + if err != nil { + return nil, err + } + + var result ListEscalationRulesResponse + return &result, c.decodeJSON(resp, &result) +} + +func getEscalationRuleFromResponse(c *Client, resp *http.Response, err error) (*EscalationRule, error) { + defer resp.Body.Close() + if err != nil { + return nil, err + } + var target map[string]EscalationRule + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "escalation_rule" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} + +func getEscalationPolicyFromResponse(c *Client, resp *http.Response, err error) (*EscalationPolicy, error) { + defer resp.Body.Close() + if err != nil { + return nil, err + } + var target map[string]EscalationPolicy + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "escalation_policy" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/event.go b/vendor/github.com/PagerDuty/go-pagerduty/event.go new file mode 100644 index 00000000..a7f73428 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/event.go @@ -0,0 +1,52 @@ +package pagerduty + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +const eventEndPoint = "https://events.pagerduty.com/generic/2010-04-15/create_event.json" + +// Event stores data for problem reporting, acknowledgement, and resolution. +type Event struct { + ServiceKey string `json:"service_key"` + Type string `json:"event_type"` + IncidentKey string `json:"incident_key,omitempty"` + Description string `json:"description"` + Client string `json:"client,omitempty"` + ClientURL string `json:"client_url,omitempty"` + Details interface{} `json:"details,omitempty"` + Contexts []interface{} `json:"contexts,omitempty"` +} + +// EventResponse is the data returned from the CreateEvent API endpoint. +type EventResponse struct { + Status string `json:"status"` + Message string `json:"message"` + IncidentKey string `json:"incident_key"` +} + +// CreateEvent sends PagerDuty an event to report, acknowledge, or resolve a problem. +func CreateEvent(e Event) (*EventResponse, error) { + data, err := json.Marshal(e) + if err != nil { + return nil, err + } + req, _ := http.NewRequest("POST", eventEndPoint, bytes.NewBuffer(data)) + req.Header.Set("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("HTTP Status Code: %d", resp.StatusCode) + } + var eventResponse EventResponse + if err := json.NewDecoder(resp.Body).Decode(&eventResponse); err != nil { + return nil, err + } + return &eventResponse, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/incident.go b/vendor/github.com/PagerDuty/go-pagerduty/incident.go new file mode 100644 index 00000000..3c7a4330 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/incident.go @@ -0,0 +1,177 @@ +package pagerduty + +import ( + "fmt" + + "github.com/google/go-querystring/query" +) + +// Acknowledgement is the data structure of an acknoledgement of an incident. +type Acknowledgement struct { + At string + Acknowledger APIObject +} + +// PendingAction is the data structure for any pending actions on an incident. +type PendingAction struct { + Type string + At string +} + +// Assignment is the data structure for an assignment of an incident +type Assignment struct { + At string + Assignee APIObject +} + +// Incident is a normalized, de-duplicated event generated by a PagerDuty integration. +type Incident struct { + APIObject + IncidentNumber uint `json:"incident_number,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + PendingActions []PendingAction `json:"pending_actions,omitempty"` + IncidentKey string `json:"incident_key,omitempty"` + Service APIObject `json:"service,omitempty"` + Assignments []Assignment `json:"assignments,omitempty"` + Acknowledgements []Acknowledgement `json:"acknowledgements,omitempty"` + LastStatusChangeAt string `json:"last_status_change_at,omitempty"` + LastStatusChangeBy APIObject `json:"last_status_change_by,omitempty"` + FirstTriggerLogEntry APIObject `json:"first_trigger_log_entry,omitempty"` + EscalationPolicy APIObject `json:"escalation_policy,omitempty"` + Teams []APIObject `json:"teams,omitempty"` + Urgency string `json:"urgency,omitempty"` + Status string `json:"status,omitempty"` +} + +// ListIncidentsResponse is the response structure when calling the ListIncident API endpoint. +type ListIncidentsResponse struct { + APIListObject + Incidents []Incident `json:"incidents,omitempty"` +} + +// ListIncidentsOptions is the structure used when passing parameters to the ListIncident API endpoint. +type ListIncidentsOptions struct { + APIListObject + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` + DateRange string `url:"date_range,omitempty"` + Statuses []string `url:"statuses,omitempty,brackets"` + IncidentKey string `url:"incident_key,omitempty"` + ServiceIDs []string `url:"service_ids,omitempty,brackets"` + TeamIDs []string `url:"team_ids,omitempty,brackets"` + UserIDs []string `url:"user_ids,omitempty,brackets"` + Urgencies []string `url:"urgencies,omitempty,brackets"` + TimeZone string `url:"time_zone,omitempty"` + SortBy string `url:"sort_by,omitempty"` + Includes []string `url:"include,omitempty,brackets"` +} + +// ListIncidents lists existing incidents. +func (c *Client) ListIncidents(o ListIncidentsOptions) (*ListIncidentsResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/incidents?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListIncidentsResponse + return &result, c.decodeJSON(resp, &result) +} + +// ManageIncidents acknowledges, resolves, escalates, or reassigns one or more incidents. +func (c *Client) ManageIncidents(from string, incidents []Incident) error { + r := make(map[string][]Incident) + headers := make(map[string]string) + headers["From"] = from + r["incidents"] = incidents + _, e := c.put("/incidents", r, &headers) + return e +} + +// GetIncident shows detailed information about an incident. +func (c *Client) GetIncident(id string) (*Incident, error) { + resp, err := c.get("/incidents/" + id) + if err != nil { + return nil, err + } + var result map[string]Incident + if err := c.decodeJSON(resp, &result); err != nil { + return nil, err + } + i, ok := result["incident"] + if !ok { + return nil, fmt.Errorf("JSON response does not have incident field") + } + return &i, nil +} + +// IncidentNote is a note for the specified incident. +type IncidentNote struct { + ID string `json:"id,omitempty"` + User APIObject `json:"user,omitempty"` + Content string `json:"content,omitempty"` + CreatedAt string `json:"created_at,omitempty"` +} + +// ListIncidentNotes lists existing notes for the specified incident. +func (c *Client) ListIncidentNotes(id string) ([]IncidentNote, error) { + resp, err := c.get("/incidents/" + id + "/notes") + if err != nil { + return nil, err + } + var result map[string][]IncidentNote + if err := c.decodeJSON(resp, &result); err != nil { + return nil, err + } + notes, ok := result["notes"] + if !ok { + return nil, fmt.Errorf("JSON response does not have notes field") + } + return notes, nil +} + +// CreateIncidentNote creates a new note for the specified incident. +func (c *Client) CreateIncidentNote(id string, note IncidentNote) error { + data := make(map[string]IncidentNote) + data["note"] = note + _, err := c.post("/incidents/"+id+"/notes", data) + return err +} + +// SnoozeIncident sets an incident to not alert for a specified period of time. +func (c *Client) SnoozeIncident(id string, duration uint) error { + data := make(map[string]uint) + data["duration"] = duration + _, err := c.post("/incidents/"+id+"/snooze", data) + return err +} + +// ListIncidentLogEntriesResponse is the response structure when calling the ListIncidentLogEntries API endpoint. +type ListIncidentLogEntriesResponse struct { + APIListObject + LogEntries []LogEntry `json:"log_entries,omitempty"` +} + +// ListIncidentLogEntriesOptions is the structure used when passing parameters to the ListIncidentLogEntries API endpoint. +type ListIncidentLogEntriesOptions struct { + APIListObject + Includes []string `url:"include,omitempty,brackets"` + IsOverview bool `url:"is_overview,omitempty"` + TimeZone string `url:"time_zone,omitempty"` +} + +// ListIncidentLogEntries lists existing log entries for the specified incident. +func (c *Client) ListIncidentLogEntries(id string, o ListIncidentLogEntriesOptions) (*ListIncidentLogEntriesResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/incidents/" + id + "/log_entries?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListIncidentLogEntriesResponse + return &result, c.decodeJSON(resp, &result) +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/log_entry.go b/vendor/github.com/PagerDuty/go-pagerduty/log_entry.go new file mode 100644 index 00000000..e1fecc43 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/log_entry.go @@ -0,0 +1,94 @@ +package pagerduty + +import ( + "fmt" + + "github.com/google/go-querystring/query" +) + +// Agent is the actor who carried out the action. +type Agent APIObject + +// Channel is the means by which the action was carried out. +type Channel struct { + Type string +} + +// Context are to be included with the trigger such as links to graphs or images. +type Context struct { + Alt string + Href string + Src string + Text string + Type string +} + +// LogEntry is a list of all of the events that happened to an incident. +type LogEntry struct { + APIObject + CreatedAt string `json:"created_at"` + Agent Agent + Channel Channel + Incident Incident + Teams []Team + Contexts []Context + AcknowledgementTimeout int `json:"acknowledgement_timeout"` + EventDetails map[string]string +} + +// ListLogEntryResponse is the response data when calling the ListLogEntry API endpoint. +type ListLogEntryResponse struct { + APIListObject + LogEntries []LogEntry `json:"log_entries"` +} + +// ListLogEntriesOptions is the data structure used when calling the ListLogEntry API endpoint. +type ListLogEntriesOptions struct { + APIListObject + TimeZone string `url:"time_zone"` + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` + IsOverview bool `url:"is_overview,omitempty"` + Includes []string `url:"include,omitempty,brackets"` +} + +// ListLogEntries lists all of the incident log entries across the entire account. +func (c *Client) ListLogEntries(o ListLogEntriesOptions) (*ListLogEntryResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/log_entries?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListLogEntryResponse + return &result, c.decodeJSON(resp, &result) +} + +// GetLogEntryOptions is the data structure used when calling the GetLogEntry API endpoint. +type GetLogEntryOptions struct { + TimeZone string `url:"timezone,omitempty"` + Includes []string `url:"include,omitempty,brackets"` +} + +// GetLogEntry list log entries for the specified incident. +func (c *Client) GetLogEntry(id string, o GetLogEntryOptions) (*LogEntry, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/log_entries/" + id + "?" + v.Encode()) + if err != nil { + return nil, err + } + var result map[string]LogEntry + if err := c.decodeJSON(resp, &result); err != nil { + return nil, err + } + le, ok := result["log_entry"] + if !ok { + return nil, fmt.Errorf("JSON response does not have log_entry field") + } + return &le, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/maintenance_window.go b/vendor/github.com/PagerDuty/go-pagerduty/maintenance_window.go new file mode 100644 index 00000000..3b7e610d --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/maintenance_window.go @@ -0,0 +1,100 @@ +package pagerduty + +import ( + "fmt" + "github.com/google/go-querystring/query" + "net/http" +) + +// MaintenanceWindow is used to temporarily disable one or more services for a set period of time. +type MaintenanceWindow struct { + APIObject + SequenceNumber uint `json:"sequence_number,omitempty"` + StartTime string `json:"start_time"` + EndTime string `json:"end_time"` + Description string `json:"description"` + Services []APIObject `json:"services"` + Teams []APIListObject `json:"teams"` + CreatedBy APIListObject `json:"created_by"` +} + +// ListMaintenanceWindowsResponse is the data structur returned from calling the ListMaintenanceWindows API endpoint. +type ListMaintenanceWindowsResponse struct { + APIListObject + MaintenanceWindows []MaintenanceWindow `json:"maintenance_windows"` +} + +// ListMaintenanceWindowsOptions is the data structure used when calling the ListMaintenanceWindows API endpoint. +type ListMaintenanceWindowsOptions struct { + APIListObject + Query string `url:"query,omitempty"` + Includes []string `url:"include,omitempty,brackets"` + TeamIDs []string `url:"team_ids,omitempty,brackets"` + ServiceIDs []string `url:"service_ids,omitempty,brackets"` + Filter string `url:"filter,omitempty,brackets"` +} + +// ListMaintenanceWindows lists existing maintenance windows, optionally filtered by service and/or team, or whether they are from the past, present or future. +func (c *Client) ListMaintenanceWindows(o ListMaintenanceWindowsOptions) (*ListMaintenanceWindowsResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/maintenance_windows?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListMaintenanceWindowsResponse + return &result, c.decodeJSON(resp, &result) +} + +// CreateMaintenanceWindows creates a new maintenance window for the specified services. +func (c *Client) CreateMaintenanceWindows(m MaintenanceWindow) (*MaintenanceWindow, error) { + data := make(map[string]MaintenanceWindow) + data["maintenance_window"] = m + resp, err := c.post("/maintenance_windows", data) + return getMaintenanceWindowFromResponse(c, resp, err) +} + +// DeleteMaintenanceWindow deletes an existing maintenance window if it's in the future, or ends it if it's currently on-going. +func (c *Client) DeleteMaintenanceWindow(id string) error { + _, err := c.delete("/maintenance_windows/" + id) + return err +} + +// GetMaintenanceWindowOptions is the data structure used when calling the GetMaintenanceWindow API endpoint. +type GetMaintenanceWindowOptions struct { + Includes []string `url:"include,omitempty,brackets"` +} + +// GetMaintenanceWindow gets an existing maintenance window. +func (c *Client) GetMaintenanceWindow(id string, o GetMaintenanceWindowOptions) (*MaintenanceWindow, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/maintenance_windows/" + id + "?" + v.Encode()) + return getMaintenanceWindowFromResponse(c, resp, err) +} + +// UpdateMaintenanceWindow updates an existing maintenance window. +func (c *Client) UpdateMaintenanceWindow(m MaintenanceWindow) (*MaintenanceWindow, error) { + resp, err := c.put("/maintenance_windows/"+m.ID, m, nil) + return getMaintenanceWindowFromResponse(c, resp, err) +} + +func getMaintenanceWindowFromResponse(c *Client, resp *http.Response, err error) (*MaintenanceWindow, error) { + if err != nil { + return nil, err + } + var target map[string]MaintenanceWindow + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "maintenance_window" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/notification.go b/vendor/github.com/PagerDuty/go-pagerduty/notification.go new file mode 100644 index 00000000..cdd87c12 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/notification.go @@ -0,0 +1,44 @@ +package pagerduty + +import ( + "github.com/google/go-querystring/query" +) + +// Notification is a message containing the details of the incident. +type Notification struct { + ID string `json:"id"` + Type string + StartedAt string `json:"started_at"` + Address string + User APIObject +} + +// ListNotificationOptions is the data structure used when calling the ListNotifications API endpoint. +type ListNotificationOptions struct { + APIListObject + TimeZone string `url:"time_zone,omitempty"` + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` + Filter string `url:"filter,omitempty"` + Includes []string `url:"include,omitempty"` +} + +// ListNotificationsResponse is the data structure returned from the ListNotifications API endpoint. +type ListNotificationsResponse struct { + APIListObject + Notifications []Notification +} + +// ListNotifications lists notifications for a given time range, optionally filtered by type (sms_notification, email_notification, phone_notification, or push_notification). +func (c *Client) ListNotifications(o ListNotificationOptions) (*ListNotificationsResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/notifications?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListNotificationsResponse + return &result, c.decodeJSON(resp, &result) +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/on_call.go b/vendor/github.com/PagerDuty/go-pagerduty/on_call.go new file mode 100644 index 00000000..6c7c3caf --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/on_call.go @@ -0,0 +1,48 @@ +package pagerduty + +import ( + "github.com/google/go-querystring/query" +) + +// OnCall represents a contiguous unit of time for which a user will be on call for a given escalation policy and escalation rule. +type OnCall struct { + User APIObject `json:"user,omitempty"` + Schedule APIObject `json:"schedule,omitempty"` + EscalationPolicy APIObject `json:"escalation_policy,omitempty"` + EscalationLevel uint `json:"escalation_level,omitempty"` + Start string `json:"start,omitempty"` + End string `json:"end,omitempty"` +} + +// ListOnCallsResponse is the data structure returned from calling the ListOnCalls API endpoint. +type ListOnCallsResponse struct { + APIListObject + OnCalls []OnCall `json:"oncalls"` +} + +// ListOnCallOptions is the data structure used when calling the ListOnCalls API endpoint. +type ListOnCallOptions struct { + APIListObject + TimeZone string `url:"time_zone,omitempty"` + Includes []string `url:"include,omitempty,brackets"` + UserIDs []string `url:"user_ids,omitempty,brackets"` + EscalationPolicyIDs []string `url:"escalation_policy_ids,omitempty,brackets"` + ScheduleIDs []string `url:"schedule_ids,omitempty,brackets"` + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` + Earliest bool `url:"earliest,omitempty"` +} + +// ListOnCalls list the on-call entries during a given time range. +func (c *Client) ListOnCalls(o ListOnCallOptions) (*ListOnCallsResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/oncalls?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListOnCallsResponse + return &result, c.decodeJSON(resp, &result) +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/schedule.go b/vendor/github.com/PagerDuty/go-pagerduty/schedule.go new file mode 100644 index 00000000..d6f76d06 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/schedule.go @@ -0,0 +1,264 @@ +package pagerduty + +import ( + "fmt" + "net/http" + + "github.com/google/go-querystring/query" +) + +// Restriction limits on-call responsibility for a layer to certain times of the day or week. +type Restriction struct { + Type string `json:"type,omitempty"` + StartTimeOfDay string `json:"start_time_of_day,omitempty"` + StartDayOfWeek uint `json:"start_day_of_week,omitempty"` + DurationSeconds uint `json:"duration_seconds,omitempty"` +} + +// RenderedScheduleEntry represents the computed set of schedule layer entries that put users on call for a schedule, and cannot be modified directly. +type RenderedScheduleEntry struct { + Start string `json:"start,omitempty"` + End string `json:"end,omitempty"` + User APIObject `json:"user,omitempty"` +} + +// ScheduleLayer is an entry that puts users on call for a schedule. +type ScheduleLayer struct { + APIObject + Name string `json:"name,omitempty"` + Start string `json:"start,omitempty"` + End string `json:"end,omitempty"` + RotationVirtualStart string `json:"rotation_virtual_start,omitempty"` + RotationTurnLengthSeconds uint `json:"rotation_turn_length_seconds,omitempty"` + Users []UserReference `json:"users,omitempty"` + Restrictions []Restriction `json:"restrictions,omitempty"` + RenderedScheduleEntries []RenderedScheduleEntry `json:"rendered_schedule_entries,omitempty"` + RenderedCoveragePercentage float64 `json:"rendered_coverage_percentage,omitempty"` +} + +// Schedule determines the time periods that users are on call. +type Schedule struct { + APIObject + Name string `json:"name,omitempty"` + TimeZone string `json:"time_zone,omitempty"` + Description string `json:"description,omitempty"` + EscalationPolicies []APIObject `json:"escalation_policies,omitempty"` + Users []APIObject `json:"users,omitempty"` + ScheduleLayers []ScheduleLayer `json:"schedule_layers,omitempty"` + OverrideSubschedule ScheduleLayer `json:"override_subschedule,omitempty"` + FinalSchedule ScheduleLayer `json:"final_schedule,omitempty"` +} + +// ListSchedulesOptions is the data structure used when calling the ListSchedules API endpoint. +type ListSchedulesOptions struct { + APIListObject + Query string `url:"query,omitempty"` +} + +// ListSchedulesResponse is the data structure returned from calling the ListSchedules API endpoint. +type ListSchedulesResponse struct { + APIListObject + Schedules []Schedule `json:"schedules"` +} + +// UserReference is a reference to an authorized PagerDuty user. +type UserReference struct { + User APIObject `json:"user"` +} + +// ListSchedules lists the on-call schedules. +func (c *Client) ListSchedules(o ListSchedulesOptions) (*ListSchedulesResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/schedules?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListSchedulesResponse + return &result, c.decodeJSON(resp, &result) +} + +// CreateSchedule creates a new on-call schedule. +func (c *Client) CreateSchedule(s Schedule) (*Schedule, error) { + data := make(map[string]Schedule) + data["schedule"] = s + resp, err := c.post("/schedules", data) + if err != nil { + return nil, err + } + return getScheduleFromResponse(c, resp) +} + +// PreviewScheduleOptions is the data structure used when calling the PreviewSchedule API endpoint. +type PreviewScheduleOptions struct { + APIListObject + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` + Overflow bool `url:"overflow,omitempty"` +} + +// PreviewSchedule previews what an on-call schedule would look like without saving it. +func (c *Client) PreviewSchedule(s Schedule, o PreviewScheduleOptions) error { + v, err := query.Values(o) + if err != nil { + return err + } + var data map[string]Schedule + data["schedule"] = s + _, e := c.post("/schedules/preview?"+v.Encode(), data) + return e +} + +// DeleteSchedule deletes an on-call schedule. +func (c *Client) DeleteSchedule(id string) error { + _, err := c.delete("/schedules/" + id) + return err +} + +// GetScheduleOptions is the data structure used when calling the GetSchedule API endpoint. +type GetScheduleOptions struct { + APIListObject + TimeZone string `url:"time_zone,omitempty"` + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` +} + +// GetSchedule shows detailed information about a schedule, including entries for each layer and sub-schedule. +func (c *Client) GetSchedule(id string, o GetScheduleOptions) (*Schedule, error) { + v, err := query.Values(o) + if err != nil { + return nil, fmt.Errorf("Could not parse values for query: %v", err) + } + resp, err := c.get("/schedules/" + id + "?" + v.Encode()) + if err != nil { + return nil, err + } + return getScheduleFromResponse(c, resp) +} + +// UpdateScheduleOptions is the data structure used when calling the UpdateSchedule API endpoint. +type UpdateScheduleOptions struct { + Overflow bool `url:"overflow,omitempty"` +} + +// UpdateSchedule updates an existing on-call schedule. +func (c *Client) UpdateSchedule(id string, s Schedule) (*Schedule, error) { + v := make(map[string]Schedule) + v["schedule"] = s + resp, err := c.put("/schedules/"+id, v, nil) + if err != nil { + return nil, err + } + return getScheduleFromResponse(c, resp) +} + +// ListOverridesOptions is the data structure used when calling the ListOverrides API endpoint. +type ListOverridesOptions struct { + APIListObject + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` + Editable bool `url:"editable,omitempty"` + Overflow bool `url:"overflow,omitempty"` +} + +// Overrides are any schedule layers from the override layer. +type Override struct { + ID string `json:"id,omitempty"` + Start string `json:"start,omitempty"` + End string `json:"end,omitempty"` + User APIObject `json:"user,omitempty"` +} + +// ListOverrides lists overrides for a given time range. +func (c *Client) ListOverrides(id string, o ListOverridesOptions) ([]Override, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/schedules/" + id + "/overrides?" + v.Encode()) + if err != nil { + return nil, err + } + var result map[string][]Override + if err := c.decodeJSON(resp, &result); err != nil { + return nil, err + } + overrides, ok := result["overrides"] + if !ok { + return nil, fmt.Errorf("JSON response does not have overrides field") + } + return overrides, nil +} + +// CreateOverride creates an override for a specific user covering the specified time range. +func (c *Client) CreateOverride(id string, o Override) (*Override, error) { + data := make(map[string]Override) + data["override"] = o + resp, err := c.post("/schedules/"+id+"/overrides", data) + if err != nil { + return nil, err + } + return getOverrideFromResponse(c, resp) +} + +// DeleteOverride removes an override. +func (c *Client) DeleteOverride(scheduleID, overrideID string) error { + _, err := c.delete("/schedules/" + scheduleID + "/overrides/" + overrideID) + return err +} + +// ListOnCallUsersOptions is the data structure used when calling the ListOnCallUsers API endpoint. +type ListOnCallUsersOptions struct { + APIListObject + Since string `url:"since,omitempty"` + Until string `url:"until,omitempty"` +} + +// ListOnCallUsers lists all of the users on call in a given schedule for a given time range. +func (c *Client) ListOnCallUsers(id string, o ListOnCallUsersOptions) ([]User, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/schedules/" + id + "/users?" + v.Encode()) + if err != nil { + return nil, err + } + var result map[string][]User + if err := c.decodeJSON(resp, &result); err != nil { + return nil, err + } + u, ok := result["users"] + if !ok { + return nil, fmt.Errorf("JSON response does not have users field") + } + return u, nil +} + +func getScheduleFromResponse(c *Client, resp *http.Response) (*Schedule, error) { + var target map[string]Schedule + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "schedule" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} + +func getOverrideFromResponse(c *Client, resp *http.Response) (*Override, error) { + var target map[string]Override + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "override" + o, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &o, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/service.go b/vendor/github.com/PagerDuty/go-pagerduty/service.go new file mode 100644 index 00000000..704762df --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/service.go @@ -0,0 +1,204 @@ +package pagerduty + +import ( + "fmt" + "net/http" + + "github.com/google/go-querystring/query" +) + +// Integration is an endpoint (like Nagios, email, or an API call) that generates events, which are normalized and de-duplicated by PagerDuty to create incidents. +type Integration struct { + APIObject + Name string `json:"name,omitempty"` + Service *APIObject `json:"service,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + Vendor *APIObject `json:"vendor,omitempty"` + Type string `json:"type,omitempty"` + IntegrationKey string `json:"integration_key,omitempty"` + IntegrationEmail string `json:"integration_email,omitempty"` +} + +// InlineModel represents when a scheduled action will occur. +type InlineModel struct { + Type string `json:"type,omitempty"` + Name string `json:"name,omitempty"` +} + +// ScheduledAction contains scheduled actions for the service. +type ScheduledAction struct { + Type string `json:"type,omitempty"` + At InlineModel `json:"at,omitempty"` + ToUrgency string `json:"to_urgency"` +} + +// IncidentUrgencyType are the incidents urgency during or outside support hours. +type IncidentUrgencyType struct { + Type string `json:"type,omitempty"` + Urgency string `json:"urgency,omitempty"` +} + +// SupportHours are the support hours for the service. +type SupportHours struct { + Type string `json:"type,omitempty"` + Timezone string `json:"time_zone,omitempty"` + StartTime string `json:"start_time,omitempty"` + EndTime string `json:"end_time,omitempty"` + DaysOfWeek []uint `json:"days_of_week,omitempty"` +} + +// IncidentUrgencyRule is the default urgency for new incidents. +type IncidentUrgencyRule struct { + Type string `json:"type,omitempty"` + Urgency string `json:"urgency,omitempty"` + DuringSupportHours *IncidentUrgencyType `json:"during_support_hours,omitempty"` + OutsideSupportHours *IncidentUrgencyType `json:"outside_support_hours,omitempty"` +} + +// Service represents something you monitor (like a web service, email service, or database service). +type Service struct { + APIObject + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + AutoResolveTimeout *uint `json:"auto_resolve_timeout"` + AcknowledgementTimeout *uint `json:"acknowledgement_timeout"` + CreateAt string `json:"created_at,omitempty"` + Status string `json:"status,omitempty"` + LastIncidentTimestamp string `json:"last_incident_timestamp,omitempty"` + Integrations []Integration `json:"integrations,omitempty"` + EscalationPolicy EscalationPolicy `json:"escalation_policy,omitempty"` + Teams []Team `json:"teams,omitempty"` + IncidentUrgencyRule *IncidentUrgencyRule `json:"incident_urgency_rule,omitempty"` + SupportHours *SupportHours `json:"support_hours,omitempty"` + ScheduledActions []ScheduledAction `json:"scheduled_actions,omitempty"` + AlertCreation string `json:"alert_creation,omitempty"` +} + +// ListServiceOptions is the data structure used when calling the ListServices API endpoint. +type ListServiceOptions struct { + APIListObject + TeamIDs []string `url:"team_ids,omitempty,brackets"` + TimeZone string `url:"time_zone,omitempty"` + SortBy string `url:"sort_by,omitempty"` + Query string `url:"query,omitempty"` + Includes []string `url:"include,omitempty,brackets"` +} + +// ListServiceResponse is the data structure returned from calling the ListServices API endpoint. +type ListServiceResponse struct { + APIListObject + Services []Service +} + +// ListServices lists existing services. +func (c *Client) ListServices(o ListServiceOptions) (*ListServiceResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/services?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListServiceResponse + return &result, c.decodeJSON(resp, &result) +} + +// GetServiceOptions is the data structure used when calling the GetService API endpoint. +type GetServiceOptions struct { + Includes []string `url:"include,brackets,omitempty"` +} + +// GetService gets details about an existing service. +func (c *Client) GetService(id string, o *GetServiceOptions) (*Service, error) { + v, err := query.Values(o) + resp, err := c.get("/services/" + id + "?" + v.Encode()) + return getServiceFromResponse(c, resp, err) +} + +// CreateService creates a new service. +func (c *Client) CreateService(s Service) (*Service, error) { + data := make(map[string]Service) + data["service"] = s + resp, err := c.post("/services", data) + return getServiceFromResponse(c, resp, err) +} + +// UpdateService updates an existing service. +func (c *Client) UpdateService(s Service) (*Service, error) { + resp, err := c.put("/services/"+s.ID, s, nil) + return getServiceFromResponse(c, resp, err) +} + +// DeleteService deletes an existing service. +func (c *Client) DeleteService(id string) error { + _, err := c.delete("/services/" + id) + return err +} + +// CreateIntegration creates a new integration belonging to a service. +func (c *Client) CreateIntegration(id string, i Integration) (*Integration, error) { + data := make(map[string]Integration) + data["integration"] = i + resp, err := c.post("/services/"+id+"/integrations", data) + return getIntegrationFromResponse(c, resp, err) +} + +// GetIntegrationOptions is the data structure used when calling the GetIntegration API endpoint. +type GetIntegrationOptions struct { + Includes []string `url:"include,omitempty,brackets"` +} + +// GetIntegration gets details about an integration belonging to a service. +func (c *Client) GetIntegration(serviceID, integrationID string, o GetIntegrationOptions) (*Integration, error) { + v, queryErr := query.Values(o) + if queryErr != nil { + return nil, queryErr + } + resp, err := c.get("/services/" + serviceID + "/integrations/" + integrationID + "?" + v.Encode()) + return getIntegrationFromResponse(c, resp, err) +} + +// UpdateIntegration updates an integration belonging to a service. +func (c *Client) UpdateIntegration(serviceID string, i Integration) (*Integration, error) { + resp, err := c.put("/services/"+serviceID+"/integrations/"+i.ID, i, nil) + return getIntegrationFromResponse(c, resp, err) +} + +// DeleteIntegration deletes an existing integration. +func (c *Client) DeleteIntegration(serviceID string, integrationID string) error { + _, err := c.delete("/services/" + serviceID + "/integrations/" + integrationID) + return err +} + +func getServiceFromResponse(c *Client, resp *http.Response, err error) (*Service, error) { + if err != nil { + return nil, err + } + var target map[string]Service + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "service" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} + +func getIntegrationFromResponse(c *Client, resp *http.Response, err error) (*Integration, error) { + if err != nil { + return nil, err + } + var target map[string]Integration + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", err) + } + rootNode := "integration" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/team.go b/vendor/github.com/PagerDuty/go-pagerduty/team.go new file mode 100644 index 00000000..096d4e8b --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/team.go @@ -0,0 +1,105 @@ +package pagerduty + +import ( + "fmt" + "github.com/google/go-querystring/query" + "net/http" +) + +// Team is a collection of users and escalation policies that represent a group of people within an organization. +type Team struct { + APIObject + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` +} + +// ListTeamResponse is the structure used when calling the ListTeams API endpoint. +type ListTeamResponse struct { + APIListObject + Teams []Team +} + +// ListTeamOptions are the input parameters used when calling the ListTeams API endpoint. +type ListTeamOptions struct { + APIListObject + Query string `url:"query,omitempty"` +} + +// ListTeams lists teams of your PagerDuty account, optionally filtered by a search query. +func (c *Client) ListTeams(o ListTeamOptions) (*ListTeamResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + + resp, err := c.get("/teams?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListTeamResponse + return &result, c.decodeJSON(resp, &result) +} + +// CreateTeam creates a new team. +func (c *Client) CreateTeam(t *Team) (*Team, error) { + resp, err := c.post("/teams", t) + return getTeamFromResponse(c, resp, err) +} + +// DeleteTeam removes an existing team. +func (c *Client) DeleteTeam(id string) error { + _, err := c.delete("/teams/" + id) + return err +} + +// GetTeam gets details about an existing team. +func (c *Client) GetTeam(id string) (*Team, error) { + resp, err := c.get("/teams/" + id) + return getTeamFromResponse(c, resp, err) +} + +// UpdateTeam updates an existing team. +func (c *Client) UpdateTeam(id string, t *Team) (*Team, error) { + resp, err := c.put("/teams/"+id, t, nil) + return getTeamFromResponse(c, resp, err) +} + +// RemoveEscalationPolicyFromTeam removes an escalation policy from a team. +func (c *Client) RemoveEscalationPolicyFromTeam(teamID, epID string) error { + _, err := c.delete("/teams/" + teamID + "/escalation_policies/" + epID) + return err +} + +// AddEscalationPolicyToTeam adds an escalation policy to a team. +func (c *Client) AddEscalationPolicyToTeam(teamID, epID string) error { + _, err := c.put("/teams/"+teamID+"/escalation_policies/"+epID, nil, nil) + return err +} + +// RemoveUserFromTeam removes a user from a team. +func (c *Client) RemoveUserFromTeam(teamID, userID string) error { + _, err := c.delete("/teams/" + teamID + "/users/" + userID) + return err +} + +// AddUserToTeam adds a user to a team. +func (c *Client) AddUserToTeam(teamID, userID string) error { + _, err := c.put("/teams/"+teamID+"/users/"+userID, nil, nil) + return err +} + +func getTeamFromResponse(c *Client, resp *http.Response, err error) (*Team, error) { + if err != nil { + return nil, err + } + var target map[string]Team + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "team" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/user.go b/vendor/github.com/PagerDuty/go-pagerduty/user.go new file mode 100644 index 00000000..2f7bad4c --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/user.go @@ -0,0 +1,124 @@ +package pagerduty + +import ( + "fmt" + "github.com/google/go-querystring/query" + "net/http" +) + +// ContactMethod is a way of contacting the user. +type ContactMethod struct { + ID string + Label string + Address string + Type string + SendShortEmail bool `json:"send_short_email"` +} + +// NotificationRule is a rule for notifying the user. +type NotificationRule struct { + ID string + StartDelayInMinutes uint `json:"start_delay_in_minutes"` + CreatedAt string `json:"created_at"` + ContactMethod ContactMethod `json:"contact_method"` + Urgency string + Type string +} + +// User is a member of a PagerDuty account that has the ability to interact with incidents and other data on the account. +type User struct { + APIObject + Name string `json:"name"` + Email string `json:"email"` + Timezone string `json:"timezone,omitempty"` + Color string `json:"color,omitempty"` + Role string `json:"role,omitempty"` + AvatarURL string `json:"avatar_url,omitempty"` + Description string `json:"description,omitempty"` + InvitationSent bool + ContactMethods []ContactMethod `json:"contact_methods"` + NotificationRules []NotificationRule `json:"notification_rules"` + JobTitle string `json:"job_title,omitempty"` + Teams []Team +} + +// ListUsersResponse is the data structure returned from calling the ListUsers API endpoint. +type ListUsersResponse struct { + APIListObject + Users []User +} + +// ListUsersOptions is the data structure used when calling the ListUsers API endpoint. +type ListUsersOptions struct { + APIListObject + Query string `url:"query,omitempty"` + TeamIDs []string `url:"team_ids,omitempty,brackets"` + Includes []string `url:"include,omitempty,brackets"` +} + +// GetUserOptions is the data structure used when calling the GetUser API endpoint. +type GetUserOptions struct { + Includes []string `url:"include,omitempty,brackets"` +} + +// ListUsers lists users of your PagerDuty account, optionally filtered by a search query. +func (c *Client) ListUsers(o ListUsersOptions) (*ListUsersResponse, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/users?" + v.Encode()) + if err != nil { + return nil, err + } + var result ListUsersResponse + return &result, c.decodeJSON(resp, &result) +} + +// CreateUser creates a new user. +func (c *Client) CreateUser(u User) (*User, error) { + data := make(map[string]User) + data["user"] = u + resp, err := c.post("/users", data) + return getUserFromResponse(c, resp, err) +} + +// DeleteUser deletes a user. +func (c *Client) DeleteUser(id string) error { + _, err := c.delete("/users/" + id) + return err +} + +// GetUser gets details about an existing user. +func (c *Client) GetUser(id string, o GetUserOptions) (*User, error) { + v, err := query.Values(o) + if err != nil { + return nil, err + } + resp, err := c.get("/users/" + id + "?" + v.Encode()) + return getUserFromResponse(c, resp, err) +} + +// UpdateUser updates an existing user. +func (c *Client) UpdateUser(u User) (*User, error) { + v := make(map[string]User) + v["user"] = u + resp, err := c.put("/users/"+u.ID, v, nil) + return getUserFromResponse(c, resp, err) +} + +func getUserFromResponse(c *Client, resp *http.Response, err error) (*User, error) { + if err != nil { + return nil, err + } + var target map[string]User + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "user" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/vendor.go b/vendor/github.com/PagerDuty/go-pagerduty/vendor.go new file mode 100644 index 00000000..7a5bdd81 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/vendor.go @@ -0,0 +1,74 @@ +package pagerduty + +import ( + "fmt" + "net/http" + + "github.com/google/go-querystring/query" +) + +// Vendor represents a specific type of integration. AWS Cloudwatch, Splunk, Datadog, etc are all examples of vendors that can be integrated in PagerDuty by making an integration. +type Vendor struct { + APIObject + Name string `json:"name,omitempty"` + LogoURL string `json:"logo_url,omitempty"` + LongName string `json:"long_name,omitempty"` + WebsiteURL string `json:"website_url,omitempty"` + Description string `json:"description,omitempty"` + Connectable bool `json:"connectable,omitempty"` + ThumbnailURL string `json:"thumbnail_url,omitempty"` + GenericServiceType string `json:"generic_service_type,omitempty"` + IntegrationGuideURL string `json:"integration_guide_url,omitempty"` +} + +// ListVendorResponse is the data structure returned from calling the ListVendors API endpoint. +type ListVendorResponse struct { + APIListObject + Vendors []Vendor +} + +// ListVendorOptions is the data structure used when calling the ListVendors API endpoint. +type ListVendorOptions struct { + APIListObject + Query string `url:"query,omitempty"` +} + +// ListVendors lists existing vendors. +func (c *Client) ListVendors(o ListVendorOptions) (*ListVendorResponse, error) { + v, err := query.Values(o) + + if err != nil { + return nil, err + } + + resp, err := c.get("/vendors?" + v.Encode()) + + if err != nil { + return nil, err + } + + var result ListVendorResponse + return &result, c.decodeJSON(resp, &result) +} + +// GetVendor gets details about an existing vendor. +func (c *Client) GetVendor(id string) (*Vendor, error) { + resp, err := c.get("/vendors/" + id) + return getVendorFromResponse(c, resp, err) +} + +func getVendorFromResponse(c *Client, resp *http.Response, err error) (*Vendor, error) { + if err != nil { + return nil, err + } + var target map[string]Vendor + if dErr := c.decodeJSON(resp, &target); dErr != nil { + return nil, fmt.Errorf("Could not decode JSON response: %v", dErr) + } + rootNode := "vendor" + t, nodeOK := target[rootNode] + if !nodeOK { + return nil, fmt.Errorf("JSON response does not have %s field", rootNode) + } + return &t, nil +} diff --git a/vendor/github.com/PagerDuty/go-pagerduty/webhook.go b/vendor/github.com/PagerDuty/go-pagerduty/webhook.go new file mode 100644 index 00000000..010b1a79 --- /dev/null +++ b/vendor/github.com/PagerDuty/go-pagerduty/webhook.go @@ -0,0 +1,37 @@ +package pagerduty + +import ( + "encoding/json" + "io" +) + +// IncidentDetail contains a representation of the incident associated with the action that caused this webhook message. +type IncidentDetail struct { + ID string `json:"id"` + IncidentNumber uint `json:"incident_number"` + CreatedOn string `json:"created_on"` + Status string `json:"status"` + HTMLUrl string `json:"html_url"` + Service string `json:"service"` + AssignedToUser *json.RawMessage `json:"assigned_to_user"` + AssignedTo []string `json:"assigned_to"` + TriggerSummaryData *json.RawMessage `json:"trigger_summary_data"` + TriggerDetailsHTMLUrl string `json:"trigger_details_html_url"` +} + +// WebhookPayload is a single message array for a webhook. +type WebhookPayload struct { + ID string `json:"id"` + Type string `json:"type"` + CreatedOn string `json:"created_on"` + Data *json.RawMessage `json:"data"` +} + +// DecodeWebhook decodes a webhook from a response object. +func DecodeWebhook(r io.Reader) (*WebhookPayload, error) { + var payload WebhookPayload + if err := json.NewDecoder(r).Decode(&payload); err != nil { + return nil, err + } + return &payload, nil +}