diff --git a/docs/index.md b/docs/index.md index 4eafad5..a3bdc9a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -25,6 +25,7 @@ Changelog is available [here](https://github.com/Yelp/terraform-provider-signalf * [Text Note](https://yelp.github.io/terraform-provider-signalform/resources/text_note.html) * [Dashboard](https://yelp.github.io/terraform-provider-signalform/resources/dashboard.html) * [Dashboard Group](https://yelp.github.io/terraform-provider-signalform/resources/dashboard_group.html) + * [Integration](https://yelp.github.io/terraform-provider-signalform/resources/integration.html) * [Build And Install](#build-and-install) * [Build binary from source](#build-binary-from-source) * [Build debian package from source](#build-debian-package-from-source) diff --git a/docs/resources/integration.md b/docs/resources/integration.md new file mode 100644 index 0000000..6725091 --- /dev/null +++ b/docs/resources/integration.md @@ -0,0 +1,27 @@ +# Integration + +SignalFx supports integrations to ingest metrics from other monitoring systems, connect to Single Sign-On providers, and to report notifications for messaging and incident management. Note that your SignalForm API key must have admin permissions to use the SignalFx integration API. + +## Example Usage + +```terraform +resource "signalform_integration" "pagerduty_myteam" { + provider = "signalform" + name = "PD - My Team" + enabled = true + type = "PagerDuty" + api_key = "1234567890" +} +``` + +## Argument Reference + +* `name` - (Required) Name of the integration. +* `enabled` - (Required) Whether the integration is enabled. +* `type` - (Required) Type of the integration. See the full list at . +* `api_key` - (Required for `PagerDuty`) PagerDuty API key. +* `webhook_url` - (Required for `Slack`) Slack incoming webhook URL. + +**Notes** + +This resource does not support all known types of integration. Contributions are welcome to implement more types. diff --git a/src/terraform-provider-signalform/signalform/integration.go b/src/terraform-provider-signalform/signalform/integration.go new file mode 100644 index 0000000..536da1f --- /dev/null +++ b/src/terraform-provider-signalform/signalform/integration.go @@ -0,0 +1,131 @@ +package signalform + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/hashicorp/terraform/helper/schema" +) + +const ( + INTEGRATION_API_URL = "https://api.signalfx.com/v2/integration" +) + +func integrationResource() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "synced": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: "Whether the resource in SignalForm and SignalFx are identical or not. Used internally for syncing.", + }, + "last_updated": &schema.Schema{ + Type: schema.TypeFloat, + Computed: true, + Description: "Latest timestamp the resource was updated", + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Name of the integration", + }, + "enabled": &schema.Schema{ + Type: schema.TypeBool, + Required: true, + Description: "Whether the integration is enabled or not", + }, + "type": &schema.Schema{ + Type: schema.TypeString, + Required: true, + Description: "Type of the integration", + ValidateFunc: validateIntegrationType, + }, + "api_key": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "PagerDuty API key", + Sensitive: true, + ConflictsWith: []string{"webhook_url"}, + }, + "webhook_url": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "Slack Incoming Webhook URL", + Sensitive: true, + ConflictsWith: []string{"api_key"}, + }, + }, + + Create: integrationCreate, + Read: integrationRead, + Update: integrationUpdate, + Delete: integrationDelete, + } +} + +func validateIntegrationType(v interface{}, k string) (we []string, errors []error) { + value := v.(string) + allowedWords := []string{"PagerDuty", "Slack"} + for _, word := range allowedWords { + if value == word { + return + } + } + errors = append(errors, fmt.Errorf("%s not allowed; must be one of: %s", value, strings.Join(allowedWords, ", "))) + return +} + +func getPayloadIntegration(d *schema.ResourceData) ([]byte, error) { + integrationType := d.Get("type").(string) + payload := map[string]interface{}{ + "name": d.Get("name").(string), + "enabled": d.Get("enabled").(bool), + "type": integrationType, + } + + switch integrationType { + case "PagerDuty": + payload["apiKey"] = d.Get("api_key").(string) + case "Slack": + payload["webhookUrl"] = d.Get("webhook_url").(string) + } + + return json.Marshal(payload) +} + +func integrationCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*signalformConfig) + payload, err := getPayloadIntegration(d) + if err != nil { + return fmt.Errorf("Failed creating json payload: %s", err.Error()) + } + url := fmt.Sprintf("%s?skipValidation=true", INTEGRATION_API_URL) + + return resourceCreate(url, config.AuthToken, payload, d) +} + +func integrationRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*signalformConfig) + url := fmt.Sprintf("%s/%s", INTEGRATION_API_URL, d.Id()) + + return resourceRead(url, config.AuthToken, d) +} + +func integrationUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*signalformConfig) + payload, err := getPayloadIntegration(d) + if err != nil { + return fmt.Errorf("Failed creating json payload: %s", err.Error()) + } + url := fmt.Sprintf("%s/%s", INTEGRATION_API_URL, d.Id()) + + return resourceUpdate(url, config.AuthToken, payload, d) +} + +func integrationDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*signalformConfig) + url := fmt.Sprintf("%s/%s", INTEGRATION_API_URL, d.Id()) + return resourceDelete(url, config.AuthToken, d) +} diff --git a/src/terraform-provider-signalform/signalform/provider.go b/src/terraform-provider-signalform/signalform/provider.go index e9e9f32..910fb98 100644 --- a/src/terraform-provider-signalform/signalform/provider.go +++ b/src/terraform-provider-signalform/signalform/provider.go @@ -40,6 +40,7 @@ func Provider() terraform.ResourceProvider { "signalform_text_chart": textChartResource(), "signalform_dashboard": dashboardResource(), "signalform_dashboard_group": dashboardGroupResource(), + "signalform_integration": integrationResource(), }, ConfigureFunc: signalformConfigure, }