From 3a0a78d33b31d902a9c87831a25f34701c249338 Mon Sep 17 00:00:00 2001 From: "Wilson E. Husin" <14004487+wilsonehusin@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:31:20 -0700 Subject: [PATCH] pager: add demo mode (#25) --- Justfile | 4 + cmd/import.go | 9 +- pager/pager.go | 15 --- pager/pager_demo.go | 63 +++++++++++ pager/pager_new.go | 22 ++++ ...lation_policies-include-5b-5d-targets.json | 103 ++++++++++++++++++ .../TeamWithSchedules_seed.sql | 2 +- 7 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 pager/pager_demo.go create mode 100644 pager/pager_new.go create mode 100644 pager/testdata/TestPagerDuty/apiserver/escalation_policies-include-5b-5d-targets.json diff --git a/Justfile b/Justfile index 0e9aae0..68ff94c 100644 --- a/Justfile +++ b/Justfile @@ -4,6 +4,10 @@ set positional-arguments dev *args='': generate go run -tags dev . "$@" +# Run demo mode, which uses pre-recorded responses for all pager.Pager instances +demo *args='': generate + go run -tags demo . "$@" + # Run a regular build run *args='': generate go run . "$@" diff --git a/cmd/import.go b/cmd/import.go index ab855db..99bd828 100644 --- a/cmd/import.go +++ b/cmd/import.go @@ -4,6 +4,8 @@ import ( "context" "database/sql" "fmt" + "os" + "os/signal" "path/filepath" "strings" @@ -50,9 +52,12 @@ var ImportCommand = &cli.Command{ } func importAction(cliCtx *cli.Context) error { + ctx, cancel := signal.NotifyContext(cliCtx.Context, os.Interrupt) + defer cancel() + providerName := cliCtx.String("provider") provider, err := pager.NewPager( - providerName, + ctx, providerName, cliCtx.String("provider-api-key"), cliCtx.String("provider-app-id"), ) @@ -64,7 +69,7 @@ func importAction(cliCtx *cli.Context) error { return fmt.Errorf("initializing FireHydrant client: %w", err) } - ctx := store.WithContext(cliCtx.Context) + ctx = store.WithContext(ctx) defer store.FromContext(ctx).Close() if err := importUsers(ctx, provider, fh); err != nil { diff --git a/pager/pager.go b/pager/pager.go index 6bb4450..8f52466 100644 --- a/pager/pager.go +++ b/pager/pager.go @@ -3,8 +3,6 @@ package pager import ( "context" "errors" - "fmt" - "strings" "github.com/firehydrant/signals-migrator/store" ) @@ -27,16 +25,3 @@ type Pager interface { Teams(context.Context) ([]store.ExtTeam, error) } - -func NewPager(kind string, apiKey string, appId string) (Pager, error) { - switch strings.ToLower(kind) { - case "pagerduty": - return NewPagerDuty(apiKey), nil - case "victorops": - return NewVictorOps(apiKey, appId), nil - case "opsgenie": - return NewOpsgenie(apiKey), nil - } - - return nil, fmt.Errorf("%w '%s'", ErrUnknownProvider, kind) -} diff --git a/pager/pager_demo.go b/pager/pager_demo.go new file mode 100644 index 0000000..a879ed8 --- /dev/null +++ b/pager/pager_demo.go @@ -0,0 +1,63 @@ +//go:build demo + +package pager + +import ( + "context" + "embed" + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" + + "github.com/firehydrant/signals-migrator/console" + "github.com/gosimple/slug" +) + +func NewPager(ctx context.Context, kind string, apiKey string, appId string) (Pager, error) { + switch strings.ToLower(kind) { + case "pagerduty": + rs := recorderServer(ctx, "PagerDuty") + return NewPagerDutyWithURL(apiKey, rs.URL), nil + case "opsgenie": + rs := recorderServer(ctx, "Opsgenie") + return NewOpsgenieWithURL(apiKey, rs.URL), nil + } + + return nil, fmt.Errorf("%w '%s'", ErrUnknownProvider, kind) +} + +//go:embed testdata/*/apiserver +var testdata embed.FS + +// recorderServer is a hack mostly taken from pager_test.go to serve recorded responses. +// Only use for demo purposes, see build tags. +func recorderServer(ctx context.Context, provider string) *httptest.Server { + h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + baseDir := fmt.Sprintf("Test%s", provider) + urlPath := r.URL.Path + if r.URL.RawQuery != "" { + urlPath += "?" + r.URL.RawQuery + } + filename, err := url.JoinPath("testdata", baseDir, "apiserver", slug.Make(urlPath)+".json") + if err != nil { + console.Warnf("[httptest] error joining path for expected response: %s\n", err) + } + data, err := testdata.ReadFile(filename) + if err != nil { + console.Warnf("[httptest] error reading file '%s': %s\n", filename, err.Error()) + http.NotFound(w, r) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(data) + }) + s := httptest.NewServer(h) + go func() { + <-ctx.Done() + s.Close() + }() + return s +} diff --git a/pager/pager_new.go b/pager/pager_new.go new file mode 100644 index 0000000..b493467 --- /dev/null +++ b/pager/pager_new.go @@ -0,0 +1,22 @@ +//go:build !demo + +package pager + +import ( + "context" + "fmt" + "strings" +) + +func NewPager(_ context.Context, kind string, apiKey string, appId string) (Pager, error) { + switch strings.ToLower(kind) { + case "pagerduty": + return NewPagerDuty(apiKey), nil + case "victorops": + return NewVictorOps(apiKey, appId), nil + case "opsgenie": + return NewOpsgenie(apiKey), nil + } + + return nil, fmt.Errorf("%w '%s'", ErrUnknownProvider, kind) +} diff --git a/pager/testdata/TestPagerDuty/apiserver/escalation_policies-include-5b-5d-targets.json b/pager/testdata/TestPagerDuty/apiserver/escalation_policies-include-5b-5d-targets.json new file mode 100644 index 0000000..f237e24 --- /dev/null +++ b/pager/testdata/TestPagerDuty/apiserver/escalation_policies-include-5b-5d-targets.json @@ -0,0 +1,103 @@ +{ + "escalation_policies": [ + { + "id": "P6F7EI2", + "type": "escalation_policy", + "summary": "Endeavour", + "self": "https://api.pagerduty.com/escalation_policies/P6F7EI2", + "html_url": "https://pdt-apidocs.pagerduty.com/escalation_policies/P6F7EI2", + "name": "Endeavour", + "escalation_rules": [ + { + "id": "PFN10S6", + "escalation_delay_in_minutes": 1, + "targets": [ + { + "name": "Douglas Hurley", + "email": "douglas.hurley@nasa.example", + "time_zone": "America/Los_Angeles", + "color": "teal", + "avatar_url": "https://secure.gravatar.com/avatar/ab94dd438eb6d722012e6155fb46d931.png?d=mm&r=PG", + "billed": true, + "role": "limited_user", + "description": null, + "invitation_sent": true, + "job_title": null, + "teams": [ + { + "id": "PQZPQGI", + "type": "team_reference", + "summary": "North American Space Agency (NASA)", + "self": "https://api.pagerduty.com/teams/PQZPQGI", + "html_url": "https://pdt-apidocs.pagerduty.com/teams/PQZPQGI" + } + ], + "contact_methods": [ + { + "id": "P92PVVL", + "type": "email_contact_method_reference", + "summary": "Default", + "self": "https://api.pagerduty.com/users/PRF4164/contact_methods/P92PVVL", + "html_url": null + }, + { + "id": "PRYGTVV", + "type": "phone_contact_method_reference", + "summary": "Work", + "self": "https://api.pagerduty.com/users/PRF4164/contact_methods/PRYGTVV", + "html_url": null + }, + { + "id": "PNMVSG5", + "type": "sms_contact_method_reference", + "summary": "Mobile", + "self": "https://api.pagerduty.com/users/PRF4164/contact_methods/PNMVSG5", + "html_url": null + } + ], + "notification_rules": [ + { + "id": "PNFV1JA", + "type": "assignment_notification_rule_reference", + "summary": "0 minutes: channel P92PVVL", + "self": "https://api.pagerduty.com/users/PRF4164/notification_rules/PNFV1JA", + "html_url": null + }, + { + "id": "PRRG2Z0", + "type": "assignment_notification_rule_reference", + "summary": "0 minutes: channel P92PVVL", + "self": "https://api.pagerduty.com/users/PRF4164/notification_rules/PRRG2Z0", + "html_url": null + }, + { + "id": "P4FC8CY", + "type": "assignment_notification_rule_reference", + "summary": "0 minutes: channel PRYGTVV", + "self": "https://api.pagerduty.com/users/PRF4164/notification_rules/P4FC8CY", + "html_url": null + }, + { + "id": "P16R808", + "type": "assignment_notification_rule_reference", + "summary": "0 minutes: channel PNMVSG5", + "self": "https://api.pagerduty.com/users/PRF4164/notification_rules/P16R808", + "html_url": null + } + ], + "id": "P4CMCAU", + "type": "user", + "summary": "Douglas Hurley", + "self": "https://api.pagerduty.com/users/PRF4164", + "html_url": "https://pdt-apidocs.pagerduty.com/users/PRF4164" + } + ] + } + ] + } + ], + "limit": 25, + "offset": 0, + "more": false, + "total": null +} diff --git a/tfrender/testdata/TestRenderOpsgenie/TeamWithSchedules_seed.sql b/tfrender/testdata/TestRenderOpsgenie/TeamWithSchedules_seed.sql index fc026f5..e98fe32 100644 --- a/tfrender/testdata/TestRenderOpsgenie/TeamWithSchedules_seed.sql +++ b/tfrender/testdata/TestRenderOpsgenie/TeamWithSchedules_seed.sql @@ -57,4 +57,4 @@ INSERT INTO ext_schedule_members VALUES('8ab5a183-8ef5-47db-9de0-56663cfbae7c-9b INSERT INTO ext_schedule_members VALUES('8ab5a183-8ef5-47db-9de0-56663cfbae7c-9b488cc6-efa0-44f3-a432-b913acab9147','1dc37638-ab52-44f3-848e-a16bcc584fb7'); INSERT INTO ext_schedule_members VALUES('8ab5a183-8ef5-47db-9de0-56663cfbae7c-9b488cc6-efa0-44f3-a432-b913acab9147','e94e17aa-418c-44f7-8e47-1eaebf6b5343'); -COMMIT; \ No newline at end of file +COMMIT;