Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding in bascis for victorops #3

Merged
merged 5 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ var importFlags = []cli.Flag{
EnvVars: []string{"PROVIDER_API_KEY"},
Required: true,
},
&cli.StringFlag{
Name: "provider-app-id",
Usage: "Provider APP ID",
EnvVars: []string{"PROVIDER_APP_ID"},
Required: false,
},
&cli.StringFlag{
Name: "provider",
Usage: "The alerting provider to generate from",
Expand Down Expand Up @@ -45,7 +51,7 @@ func importAction(ctx *cli.Context) error {
}

providerName := ctx.String("provider")
provider, err := pager.NewPager(providerName, ctx.String("provider-api-key"))
provider, err := pager.NewPager(providerName, ctx.String("provider-api-key"), ctx.String("provider-app-id"))
if err != nil {
return fmt.Errorf("initializing pager provider: %w", err)
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 // indirect
github.com/victorops/go-victorops v1.0.7 // indirect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting... this shouldn't be indirect. might need to run go mod tidy, which reminds me i should add that in CI.

github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
github.com/vmihailenco/tagparser v0.1.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/victorops/go-victorops v1.0.7 h1:qZCq9lLBAj1OWFVPQwLmXeO4dfzcP6sLTQo7NDyj3BQ=
github.com/victorops/go-victorops v1.0.7/go.mod h1:f597oumLjVOdxJ38mg6dQ/1rV6wpEYW4XY3K8o/QJNQ=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
Expand Down
4 changes: 3 additions & 1 deletion pager/pager.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ type Pager interface {
PopulateTeamSchedules(ctx context.Context, team *Team) error
}

func NewPager(kind string, apiKey string) (Pager, error) {
func NewPager(kind string, apiKey string, appId string) (Pager, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

switch strings.ToLower(kind) {
case "pagerduty":
return NewPagerDuty(apiKey), nil
case "victorops":
return NewVictorOps(apiKey, appId), nil
}
return nil, fmt.Errorf("%w '%s'", ErrUnknownProvider, kind)
}
96 changes: 96 additions & 0 deletions pager/victorops.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package pager

import (
"context"

"github.com/gosimple/slug"
"github.com/victorops/go-victorops/victorops"
)

type VictorOps struct {
client *victorops.Client
}

func NewVictorOps(apiKey string, appId string) *VictorOps {
return &VictorOps{
client: victorops.NewClient(appId, apiKey, "https://api.victorops.com"),
}
}

func (v *VictorOps) Kind() string {
return "victorops"
}

func (v *VictorOps) PopulateTeamMembers(ctx context.Context, team *Team) error {
members := []*User{}

vmembers, _, err := v.client.GetTeamMembers(team.ID)
if err != nil {
return err
}

for _, member := range vmembers.Members {
members = append(members, &User{Resource: Resource{ID: member.Username}})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this use toUser as well?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh i made the bad example on pagerduty for this one huh woops

}

team.Members = members
return nil
}

func (v *VictorOps) PopulateTeamSchedules(ctx context.Context, team *Team) error {
// TODO: implement
return nil
}

func (v *VictorOps) ListTeams(ctx context.Context) ([]*Team, error) {
teams := []*Team{}

vteams, _, err := v.client.GetAllTeams()
if err != nil {
return nil, err
}

for _, team := range *vteams {
teams = append(teams, v.toTeam(team))
}

return teams, nil
}

func (v *VictorOps) toTeam(team victorops.Team) *Team {
return &Team{
// PagerDuty does not expose a slug, so generate one.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// PagerDuty does not expose a slug, so generate one.
// VictorOps does not expose a slug, so generate one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this with my last push

Slug: slug.Make(team.Name),
Resource: Resource{
ID: team.Slug,
Name: team.Name,
},
}
}

func (v *VictorOps) ListUsers(ctx context.Context) ([]*User, error) {
users := []*User{}

vusers, _, err := v.client.GetAllUsers()
if err != nil {
return nil, err
}

for _, userSlice := range vusers.Users {
for _, user := range userSlice {
users = append(users, v.toUser(user))
}
}
Copy link
Member

@wilsonehusin wilsonehusin Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops I missed this first time around: probably should use GetAllUserV2 here https://pkg.go.dev/github.com/victorops/go-victorops@v1.0.7/victorops#Client.GetAllUserV2


return users, nil
}

func (v *VictorOps) toUser(user victorops.User) *User {
return &User{
Email: user.Email,
Resource: Resource{
ID: user.Username,
Name: user.FirstName + " " + user.LastName,
},
}
}
38 changes: 21 additions & 17 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,47 @@ This can be used to import resources from legacy alerting providers into Signals

# Todo

* Add support for getting transposer URLs (specifically for Datadog) to the team data resource or a signals ingest URL data resource
* Deduplicate FireHydrant team definitions
* Add support for importing escalation policies -- a default is created
* Test coverage
* Build + publish Docker image to simplify usage down to `docker run firehydrant/signals-migrator import`
- Add support for getting transposer URLs (specifically for Datadog) to the team data resource or a signals ingest URL data resource
- Deduplicate FireHydrant team definitions
- Add support for importing escalation policies -- a default is created
- Test coverage
- Build + publish Docker image to simplify usage down to `docker run firehydrant/signals-migrator import`

## Usage

## Generate Datadog Webhooks

A Datadog API key and application key with the `create_webhook` scope are required.

Ensure FIREHYDRANT_API_KEY, DATADOG_API_KEY and DATADOG_APP_KEY are exported and run `go run main.go datadog`. This will generate Terraform files in output/*.tf.
Ensure FIREHYDRANT_API_KEY, DATADOG_API_KEY and DATADOG_APP_KEY are exported and run `go run main.go datadog`. This will generate Terraform files in output/\*.tf.

*They will not be valid TF until ingest URL support is added to the provider and can not be applied*
_They will not be valid TF until ingest URL support is added to the provider and can not be applied_

## Generate Signals resources from PagerDuty
Ensure PAGERDUTY_API_KEY and FIREHYDRANT_API_KEY are exported and run `go run main.go import`. This will generate Terraform files in output/*.tf

Ensure PAGERDUTY_API_KEY and FIREHYDRANT_API_KEY are exported and run `go run main.go import`. This will generate Terraform files in output/\*.tf

### Process
* Fetch users from provider
* Fetch teams from provider
* Fetch schedules for each team from provider
* Map any users that don't exist in FH with the same email address
* Map any teams that don't exist in FH with the same name
* Render data resources for each user in the organization
* Render data resources for eacn team in the organization
* Render on_call_schedule resources for each schedule, referencing the users and teams above

- Fetch users from provider
- Fetch teams from provider
- Fetch schedules for each team from provider
- Map any users that don't exist in FH with the same email address
- Map any teams that don't exist in FH with the same name
- Render data resources for each user in the organization
- Render data resources for eacn team in the organization
- Render on_call_schedule resources for each schedule, referencing the users and teams above

## Debugging

Debugging this is a little tricky if you end up in the bubbletea resource picker because no TTY is available. You need to run the applicationw with delve and then `start debugging` to attach VSCode to it.

`dlv debug github.com/firehydrant/signals-migrator --headless --listen=0.0.0.0:2345 --log --api-version 2 -- import`


## Sample outputs

### Datadog

```
provider "datadog" {
}
Expand All @@ -63,6 +66,7 @@ resource "datadog_webhook" "team-with-no-service" {
```

### PagerDuty

```
provider "firehydrant" {
}
Expand Down
Loading