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

Add Webhook resource #1205

Merged
merged 5 commits into from Sep 29, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions datadog/provider.go
Expand Up @@ -167,6 +167,7 @@ func Provider() *schema.Provider {
"datadog_synthetics_global_variable": resourceDatadogSyntheticsGlobalVariable(),
"datadog_synthetics_private_location": resourceDatadogSyntheticsPrivateLocation(),
"datadog_user": resourceDatadogUser(),
"datadog_webhook": resourceDatadogWebhook(),
},

DataSourcesMap: map[string]*schema.Resource{
Expand Down
204 changes: 204 additions & 0 deletions datadog/resource_datadog_webhook.go
@@ -0,0 +1,204 @@
package datadog

import (
"context"
"io/ioutil"
"strings"

"github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils"
"github.com/terraform-providers/terraform-provider-datadog/datadog/internal/validators"

datadogV1 "github.com/DataDog/datadog-api-client-go/api/v1/datadog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceDatadogWebhook() *schema.Resource {
return &schema.Resource{
Description: "Provides a Datadog webhook resource. This can be used to create and manage Datadog webhooks.",
CreateContext: resourceDatadogWebhookCreate,
ReadContext: resourceDatadogWebhookRead,
UpdateContext: resourceDatadogWebhookUpdate,
DeleteContext: resourceDatadogWebhookDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
"name": {
Description: "The name of the webhook. It corresponds with `<WEBHOOK_NAME>`.",
Type: schema.TypeString,
Required: true,
},
"url": {
Description: "The URL of the webhook.",
Type: schema.TypeString,
Required: true,
},
"payload": {
Description: "The payload of the webhook.",
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"custom_headers": {
Description: "The headers attached to the webhook.",
Type: schema.TypeString,
Optional: true,
},
"encode_as": {
Description: "Encoding type. Can be given either `json` or `form`.",
skarimo marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: validators.ValidateEnumValue(datadogV1.NewWebhooksIntegrationEncodingFromValue),
Computed: true,
},
},
}
}

func updateWebhookState(d *schema.ResourceData, webhook *datadogV1.WebhooksIntegration) diag.Diagnostics {
// Required attributes
if err := d.Set("name", webhook.GetName()); err != nil {
return diag.FromErr(err)
}
if err := d.Set("url", webhook.GetUrl()); err != nil {
return diag.FromErr(err)
}

// Optional attributes
if v, ok := webhook.GetPayloadOk(); ok {
if err := d.Set("payload", v); err != nil {
return diag.FromErr(err)
}
}
if v, ok := webhook.GetCustomHeadersOk(); ok {
if err := d.Set("custom_headers", v); err != nil {
return diag.FromErr(err)
}
}
if v, ok := webhook.GetEncodeAsOk(); ok {
if err := d.Set("encode_as", v); err != nil {
return diag.FromErr(err)
}
}

return nil
}

func resourceDatadogWebhookCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
providerConf := meta.(*ProviderConfiguration)
datadogClientV1 := providerConf.DatadogClientV1
authV1 := providerConf.AuthV1

webhook, err := buildWebhookCreatePayload(d)
if err != nil {
return diag.FromErr(err)
}

resp, httpResponse, err := datadogClientV1.WebhooksIntegrationApi.CreateWebhooksIntegration(authV1, *webhook)
if err != nil {
return utils.TranslateClientErrorDiag(err, httpResponse, "error creating webhooks custom variable")
}

d.SetId(resp.GetName())

return updateWebhookState(d, &resp)
}

func resourceDatadogWebhookRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
providerConf := meta.(*ProviderConfiguration)
datadogClientV1 := providerConf.DatadogClientV1
authV1 := providerConf.AuthV1

resp, httpResponse, err := datadogClientV1.WebhooksIntegrationApi.GetWebhooksIntegration(authV1, d.Id())
if err != nil {
// Api returns 400 when the webhook does not exist
if httpResponse != nil && httpResponse.StatusCode == 400 {
bodyBytes, _ := ioutil.ReadAll(httpResponse.Body)
bodyString := string(bodyBytes)
if strings.Contains(bodyString, "Webhook does not exist") {
d.SetId("")
return nil
}
}
return utils.TranslateClientErrorDiag(err, httpResponse, "error getting webhook")
}
return updateWebhookState(d, &resp)
}

func resourceDatadogWebhookUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
providerConf := meta.(*ProviderConfiguration)
datadogClientV1 := providerConf.DatadogClientV1
authV1 := providerConf.AuthV1

webhook, err := buildWebhookUpdatePayload(d)
if err != nil {
return diag.FromErr(err)
}

resp, httpResponse, err := datadogClientV1.WebhooksIntegrationApi.UpdateWebhooksIntegration(authV1, d.Id(), *webhook)
if err != nil {
return utils.TranslateClientErrorDiag(err, httpResponse, "error updating webhook")
}

d.SetId(resp.GetName())

return updateWebhookState(d, &resp)
}

func resourceDatadogWebhookDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
providerConf := meta.(*ProviderConfiguration)
datadogClientV1 := providerConf.DatadogClientV1
authV1 := providerConf.AuthV1

if httpResponse, err := datadogClientV1.WebhooksIntegrationApi.DeleteWebhooksIntegration(authV1, d.Id()); err != nil {
return utils.TranslateClientErrorDiag(err, httpResponse, "error deleting webhook")
}

return nil
}

func buildWebhookCreatePayload(d *schema.ResourceData) (*datadogV1.WebhooksIntegration, error) {
payload := datadogV1.WebhooksIntegration{}

payload.SetName(d.Get("name").(string))
payload.SetUrl(d.Get("url").(string))
if v, ok := d.GetOk("payload"); ok {
payload.SetPayload(v.(string))
}
if v, ok := d.GetOk("custom_headers"); ok {
payload.SetCustomHeaders(v.(string))
}
if v, ok := d.GetOk("encode_as"); ok {
encoding, err := datadogV1.NewWebhooksIntegrationEncodingFromValue(v.(string))
if err != nil {
return nil, err
}
payload.SetEncodeAs(*encoding)
}

return &payload, nil
}

func buildWebhookUpdatePayload(d *schema.ResourceData) (*datadogV1.WebhooksIntegrationUpdateRequest, error) {
payload := datadogV1.WebhooksIntegrationUpdateRequest{}

payload.SetName(d.Get("name").(string))
payload.SetUrl(d.Get("url").(string))
if v, ok := d.GetOk("payload"); ok {
payload.SetPayload(v.(string))
}
if v, ok := d.GetOk("custom_headers"); ok {
payload.SetCustomHeaders(v.(string))
}
if v, ok := d.GetOk("encode_as"); ok {
encoding, err := datadogV1.NewWebhooksIntegrationEncodingFromValue(v.(string))
if err != nil {
return nil, err
}
payload.SetEncodeAs(*encoding)
}

return &payload, nil
}
@@ -0,0 +1 @@
2021-09-16T16:24:25.687739-04:00