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

Config Generation: Support for OnCall and Synthetic Monitoring #1639

Merged
merged 5 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
34 changes: 31 additions & 3 deletions cmd/generate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,30 @@ This supports a glob format. Examples:
Category: "Grafana",
EnvVars: []string{"TFGEN_GRAFANA_AUTH"},
},
&cli.StringFlag{
Name: "synthetic-monitoring-url",
Usage: "URL of the Synthetic Monitoring instance to generate resources from",
Category: "Grafana",
EnvVars: []string{"TFGEN_SYNTHETIC_MONITORING_URL"},
},
&cli.StringFlag{
Name: "synthetic-monitoring-access-token",
Usage: "API token for the Synthetic Monitoring instance",
Category: "Grafana",
EnvVars: []string{"TFGEN_SYNTHETIC_MONITORING_ACCESS_TOKEN"},
},
&cli.StringFlag{
Name: "oncall-url",
Usage: "URL of the OnCall instance to generate resources from",
Category: "Grafana",
EnvVars: []string{"TFGEN_ONCALL_URL"},
},
&cli.StringFlag{
Name: "oncall-access-token",
Usage: "API token for the OnCall instance",
Category: "Grafana",
EnvVars: []string{"TFGEN_ONCALL_ACCESS_TOKEN"},
},

// Grafana Cloud flags
&cli.StringFlag{
Expand Down Expand Up @@ -132,8 +156,12 @@ func parseFlags(ctx *cli.Context) (*generate.Config, error) {
Format: generate.OutputFormat(ctx.String("output-format")),
ProviderVersion: ctx.String("terraform-provider-version"),
Grafana: &generate.GrafanaConfig{
URL: ctx.String("grafana-url"),
Auth: ctx.String("grafana-auth"),
URL: ctx.String("grafana-url"),
Auth: ctx.String("grafana-auth"),
SMURL: ctx.String("synthetic-monitoring-url"),
SMAccessToken: ctx.String("synthetic-monitoring-access-token"),
OnCallURL: ctx.String("oncall-url"),
OnCallAccessToken: ctx.String("oncall-access-token"),
},
Cloud: &generate.CloudConfig{
AccessPolicyToken: ctx.String("cloud-access-policy-token"),
Expand All @@ -152,7 +180,7 @@ func parseFlags(ctx *cli.Context) (*generate.Config, error) {
err := newFlagValidations().
atLeastOne("grafana-url", "cloud-access-policy-token").
conflicting(
[]string{"grafana-url", "grafana-auth"},
[]string{"grafana-url", "grafana-auth", "synthetic-monitoring-url", "synthetic-monitoring-access-token", "oncall-url", "oncall-access-token"},
[]string{"cloud-access-policy-token", "cloud-org", "cloud-create-stack-service-account", "cloud-stack-service-account-name"},
).
requiredWhenSet("grafana-url", "grafana-auth").
Expand Down
34 changes: 34 additions & 0 deletions internal/resources/oncall/common_lister.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package oncall

import (
"context"
"fmt"

onCallAPI "github.com/grafana/amixr-api-go-client"
"github.com/grafana/terraform-provider-grafana/v3/internal/common"
)

type listerFunc func(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error)

// oncallListerFunction is a helper function that wraps a lister function be used more easily in oncall resources.
func oncallListerFunction(listerFunc listerFunc) common.ResourceListIDsFunc {
return func(ctx context.Context, client *common.Client, data any) ([]string, error) {
if client.OnCallClient == nil {
return nil, fmt.Errorf("client not configured for Grafana OnCall API")
}
ids := []string{}
page := 1
for {
newIDs, nextPage, err := listerFunc(client.OnCallClient, onCallAPI.ListOptions{Page: page})
if err != nil {
return nil, err
}
ids = append(ids, newIDs...)
if nextPage == nil {
break
}
page++
}
return ids, nil
}
}
13 changes: 12 additions & 1 deletion internal/resources/oncall/resource_escalation.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,18 @@ func resourceEscalation() *common.Resource {
"grafana_oncall_escalation",
resourceID,
schema,
)
).WithLister(oncallListerFunction(listEscalations))
}

func listEscalations(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error) {
resp, _, err := client.Escalations.ListEscalations(&onCallAPI.ListEscalationOptions{ListOptions: listOptions})
if err != nil {
return nil, nil, err
}
for _, i := range resp.Escalations {
ids = append(ids, i.ID)
}
return ids, resp.Next, nil
}

func resourceEscalationCreate(ctx context.Context, d *schema.ResourceData, client *onCallAPI.Client) diag.Diagnostics {
Expand Down
13 changes: 12 additions & 1 deletion internal/resources/oncall/resource_escalation_chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,18 @@ func resourceEscalationChain() *common.Resource {
"grafana_oncall_escalation_chain",
resourceID,
schema,
)
).WithLister(oncallListerFunction(listEscalationChains))
}

func listEscalationChains(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error) {
resp, _, err := client.EscalationChains.ListEscalationChains(&onCallAPI.ListEscalationChainOptions{ListOptions: listOptions})
if err != nil {
return nil, nil, err
}
for _, i := range resp.EscalationChains {
ids = append(ids, i.ID)
}
return ids, resp.Next, nil
}

func resourceEscalationChainCreate(ctx context.Context, d *schema.ResourceData, client *onCallAPI.Client) diag.Diagnostics {
Expand Down
13 changes: 12 additions & 1 deletion internal/resources/oncall/resource_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,18 @@ func resourceIntegration() *common.Resource {
"grafana_oncall_integration",
resourceID,
schema,
)
).WithLister(oncallListerFunction(listIntegrations))
}

func listIntegrations(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error) {
resp, _, err := client.Integrations.ListIntegrations(&onCallAPI.ListIntegrationOptions{ListOptions: listOptions})
if err != nil {
return nil, nil, err
}
for _, i := range resp.Integrations {
ids = append(ids, i.ID)
}
return ids, resp.Next, nil
}

func onCallTemplate(description string, hasMessage, hasImage bool) *schema.Schema {
Expand Down
13 changes: 12 additions & 1 deletion internal/resources/oncall/resource_outgoing_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,18 @@ func resourceOutgoingWebhook() *common.Resource {
"grafana_oncall_outgoing_webhook",
resourceID,
schema,
)
).WithLister(oncallListerFunction(listWebhooks))
}

func listWebhooks(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error) {
resp, _, err := client.Webhooks.ListWebhooks(&onCallAPI.ListWebhookOptions{ListOptions: listOptions})
if err != nil {
return nil, nil, err
}
for _, i := range resp.Webhooks {
ids = append(ids, i.ID)
}
return ids, resp.Next, nil
}

func resourceOutgoingWebhookCreate(ctx context.Context, d *schema.ResourceData, client *onCallAPI.Client) diag.Diagnostics {
Expand Down
13 changes: 12 additions & 1 deletion internal/resources/oncall/resource_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,18 @@ func resourceRoute() *common.Resource {
"grafana_oncall_route",
resourceID,
schema,
)
).WithLister(oncallListerFunction(listRoutes))
}

func listRoutes(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error) {
resp, _, err := client.Routes.ListRoutes(&onCallAPI.ListRouteOptions{ListOptions: listOptions})
if err != nil {
return nil, nil, err
}
for _, i := range resp.Routes {
ids = append(ids, i.ID)
}
return ids, resp.Next, nil
}

func resourceRouteCreate(ctx context.Context, d *schema.ResourceData, client *onCallAPI.Client) diag.Diagnostics {
Expand Down
13 changes: 12 additions & 1 deletion internal/resources/oncall/resource_schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,18 @@ func resourceSchedule() *common.Resource {
"grafana_oncall_schedule",
resourceID,
schema,
)
).WithLister(oncallListerFunction(listSchedules))
}

func listSchedules(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error) {
resp, _, err := client.Schedules.ListSchedules(&onCallAPI.ListScheduleOptions{ListOptions: listOptions})
if err != nil {
return nil, nil, err
}
for _, i := range resp.Schedules {
ids = append(ids, i.ID)
}
return ids, resp.Next, nil
}

func resourceScheduleCreate(ctx context.Context, d *schema.ResourceData, client *onCallAPI.Client) diag.Diagnostics {
Expand Down
13 changes: 12 additions & 1 deletion internal/resources/oncall/resource_shift.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,18 @@ func resourceOnCallShift() *common.Resource {
"grafana_oncall_on_call_shift",
resourceID,
schema,
)
).WithLister(oncallListerFunction(listShifts))
}

func listShifts(client *onCallAPI.Client, listOptions onCallAPI.ListOptions) (ids []string, nextPage *string, err error) {
resp, _, err := client.OnCallShifts.ListOnCallShifts(&onCallAPI.ListOnCallShiftOptions{ListOptions: listOptions})
if err != nil {
return nil, nil, err
}
for _, i := range resp.OnCallShifts {
ids = append(ids, i.ID)
}
return ids, resp.Next, nil
}

func resourceOnCallShiftCreate(ctx context.Context, d *schema.ResourceData, client *onCallAPI.Client) diag.Diagnostics {
Expand Down
3 changes: 3 additions & 0 deletions pkg/generate/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ type stack struct {
managementKey string
smURL string
smToken string

onCallURL string
onCallToken string
}

func generateCloudResources(ctx context.Context, cfg *Config) ([]stack, error) {
Expand Down
8 changes: 6 additions & 2 deletions pkg/generate/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ const (
var OutputFormats = []OutputFormat{OutputFormatJSON, OutputFormatHCL, OutputFormatCrossplane}

type GrafanaConfig struct {
URL string
Auth string
URL string
Auth string
SMURL string
SMAccessToken string
OnCallURL string
OnCallAccessToken string
}

type CloudConfig struct {
Expand Down
6 changes: 4 additions & 2 deletions pkg/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ func Generate(ctx context.Context, cfg *Config) error {
stack := stack{
managementKey: cfg.Grafana.Auth,
url: cfg.Grafana.URL,
smToken: "",
smURL: "",
smToken: cfg.Grafana.SMAccessToken,
smURL: cfg.Grafana.SMURL,
onCallToken: cfg.Grafana.OnCallAccessToken,
onCallURL: cfg.Grafana.OnCallURL,
}
if err := generateGrafanaResources(ctx, cfg, stack, true); err != nil {
return err
Expand Down
22 changes: 17 additions & 5 deletions pkg/generate/grafana.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/grafana/terraform-provider-grafana/v3/internal/resources/grafana"
"github.com/grafana/terraform-provider-grafana/v3/internal/resources/machinelearning"
"github.com/grafana/terraform-provider-grafana/v3/internal/resources/oncall"
"github.com/grafana/terraform-provider-grafana/v3/internal/resources/slo"
"github.com/grafana/terraform-provider-grafana/v3/internal/resources/syntheticmonitoring"
"github.com/grafana/terraform-provider-grafana/v3/pkg/provider"
Expand All @@ -28,6 +29,14 @@ func generateGrafanaResources(ctx context.Context, cfg *Config, stack stack, gen
providerBlock := hclwrite.NewBlock("provider", []string{"grafana"})
providerBlock.Body().SetAttributeValue("url", cty.StringVal(stack.url))
providerBlock.Body().SetAttributeValue("auth", cty.StringVal(stack.managementKey))
if stack.smToken != "" && stack.smURL != "" {
providerBlock.Body().SetAttributeValue("sm_url", cty.StringVal(stack.smURL))
providerBlock.Body().SetAttributeValue("sm_access_token", cty.StringVal(stack.smToken))
}
if stack.onCallToken != "" && stack.onCallURL != "" {
providerBlock.Body().SetAttributeValue("oncall_url", cty.StringVal(stack.onCallURL))
providerBlock.Body().SetAttributeValue("oncall_access_token", cty.StringVal(stack.onCallToken))
}
if stack.name != "" {
providerBlock.Body().SetAttributeValue("alias", cty.StringVal(stack.name))
}
Expand All @@ -44,11 +53,16 @@ func generateGrafanaResources(ctx context.Context, cfg *Config, stack stack, gen
URL: types.StringValue(stack.url),
Auth: types.StringValue(stack.managementKey),
}
if stack.smToken != "" {
resources := grafana.Resources
if stack.smToken != "" && stack.smURL != "" {
resources = append(resources, syntheticmonitoring.Resources...)
config.SMURL = types.StringValue(stack.smURL)
config.SMAccessToken = types.StringValue(stack.smToken)
}
if stack.smURL != "" {
config.SMURL = types.StringValue(stack.smURL)
if stack.onCallToken != "" && stack.onCallURL != "" {
resources = append(resources, oncall.Resources...)
config.OncallAccessToken = types.StringValue(stack.onCallToken)
config.OncallURL = types.StringValue(stack.onCallURL)
}
if err := config.SetDefaults(); err != nil {
return err
Expand All @@ -59,11 +73,9 @@ func generateGrafanaResources(ctx context.Context, cfg *Config, stack stack, gen
return err
}

resources := grafana.Resources
if strings.HasPrefix(stack.name, "stack-") { // TODO: is cloud. Find a better way to detect this
resources = append(resources, slo.Resources...)
resources = append(resources, machinelearning.Resources...)
resources = append(resources, syntheticmonitoring.Resources...)
}
if err := generateImportBlocks(ctx, client, listerData, resources, cfg, stack.name); err != nil {
return err
Expand Down
Loading