internal/elasticsearch/watcher/watch.go (237 lines of code) (raw):
package watcher
import (
"context"
"encoding/json"
"fmt"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/elastic/terraform-provider-elasticstack/internal/clients/elasticsearch"
"github.com/elastic/terraform-provider-elasticstack/internal/models"
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)
func ResourceWatch() *schema.Resource {
watchSchema := map[string]*schema.Schema{
"id": {
Description: "Internal identifier of the resource.",
Type: schema.TypeString,
Computed: true,
},
"watch_id": {
Description: "Identifier for the watch.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"active": {
Description: "Defines whether the watch is active or inactive by default. The default value is true, which means the watch is active by default.",
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"trigger": {
Description: "The trigger that defines when the watch should run.",
Type: schema.TypeString,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: utils.DiffJsonSuppress,
Required: true,
},
"input": {
Description: "The input that defines the input that loads the data for the watch.",
Type: schema.TypeString,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: utils.DiffJsonSuppress,
Optional: true,
Default: "{\"none\":{}}",
},
"condition": {
Description: "The condition that defines if the actions should be run.",
Type: schema.TypeString,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: utils.DiffJsonSuppress,
Optional: true,
Default: "{\"always\":{}}",
},
"actions": {
Description: "The list of actions that will be run if the condition matches.",
Type: schema.TypeString,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: utils.DiffJsonSuppress,
Optional: true,
Default: "{}",
},
"metadata": {
Description: "Metadata json that will be copied into the history entries.",
Type: schema.TypeString,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: utils.DiffJsonSuppress,
Optional: true,
Default: "{}",
},
"transform": {
Description: "Processes the watch payload to prepare it for the watch actions.",
Type: schema.TypeString,
ValidateFunc: validation.StringIsJSON,
DiffSuppressFunc: utils.DiffJsonSuppress,
Optional: true,
},
"throttle_period_in_millis": {
Description: "Minimum time in milliseconds between actions being run. Defaults to 5000.",
Type: schema.TypeInt,
Optional: true,
Default: 5000,
},
}
return &schema.Resource{
Description: "Manage Watches. See, https://www.elastic.co/guide/en/elasticsearch/reference/current/watcher-api.html",
CreateContext: resourceWatchPut,
UpdateContext: resourceWatchPut,
ReadContext: resourceWatchRead,
DeleteContext: resourceWatchDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: watchSchema,
}
}
func resourceWatchPut(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
watchID := d.Get("watch_id").(string)
id, diags := client.ID(ctx, watchID)
if diags.HasError() {
return diags
}
var watch models.PutWatch
watch.WatchID = watchID
watch.Active = d.Get("active").(bool)
var trigger map[string]interface{}
if err := json.Unmarshal([]byte(d.Get("trigger").(string)), &trigger); err != nil {
return diag.FromErr(err)
}
watch.Body.Trigger = trigger
var input map[string]interface{}
if err := json.Unmarshal([]byte(d.Get("input").(string)), &input); err != nil {
return diag.FromErr(err)
}
watch.Body.Input = input
var condition map[string]interface{}
if err := json.Unmarshal([]byte(d.Get("condition").(string)), &condition); err != nil {
return diag.FromErr(err)
}
watch.Body.Condition = condition
var actions map[string]interface{}
if err := json.Unmarshal([]byte(d.Get("actions").(string)), &actions); err != nil {
return diag.FromErr(err)
}
watch.Body.Actions = actions
var metadata map[string]interface{}
if err := json.Unmarshal([]byte(d.Get("metadata").(string)), &metadata); err != nil {
return diag.FromErr(err)
}
watch.Body.Metadata = metadata
if transformJSON, ok := d.GetOk("transform"); ok {
var transform map[string]interface{}
if err := json.Unmarshal([]byte(transformJSON.(string)), &transform); err != nil {
return diag.FromErr(err)
}
watch.Body.Transform = transform
}
watch.Body.Throttle_period_in_millis = d.Get("throttle_period_in_millis").(int)
if diags := elasticsearch.PutWatch(ctx, client, &watch); diags.HasError() {
return diags
}
d.SetId(id.String())
return resourceWatchRead(ctx, d, meta)
}
func resourceWatchRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
resourceID, diags := clients.ResourceIDFromStr(d.Id())
if diags.HasError() {
return diags
}
watch, diags := elasticsearch.GetWatch(ctx, client, resourceID)
if watch == nil && diags == nil {
tflog.Warn(ctx, fmt.Sprintf(`Watch "%s" not found, removing from state`, resourceID))
d.SetId("")
return diags
}
if diags.HasError() {
return diags
}
if err := d.Set("watch_id", watch.WatchID); err != nil {
return diag.FromErr(err)
}
if err := d.Set("active", watch.Status.State.Active); err != nil {
return diag.FromErr(err)
}
trigger, err := json.Marshal(watch.Body.Trigger)
if err != nil {
return diag.FromErr(err)
}
if err := d.Set("trigger", string(trigger)); err != nil {
return diag.FromErr(err)
}
input, err := json.Marshal(watch.Body.Input)
if err != nil {
return diag.FromErr(err)
}
if err := d.Set("input", string(input)); err != nil {
return diag.FromErr(err)
}
condition, err := json.Marshal(watch.Body.Condition)
if err != nil {
return diag.FromErr(err)
}
if err := d.Set("condition", string(condition)); err != nil {
return diag.FromErr(err)
}
actions, err := json.Marshal(watch.Body.Actions)
if err != nil {
return diag.FromErr(err)
}
if err := d.Set("actions", string(actions)); err != nil {
return diag.FromErr(err)
}
metadata, err := json.Marshal(watch.Body.Metadata)
if err != nil {
return diag.FromErr(err)
}
if err := d.Set("metadata", string(metadata)); err != nil {
return diag.FromErr(err)
}
if watch.Body.Transform != nil {
transform, err := json.Marshal(watch.Body.Transform)
if err != nil {
return diag.FromErr(err)
}
if err := d.Set("transform", string(transform)); err != nil {
return diag.FromErr(err)
}
}
if err := d.Set("throttle_period_in_millis", watch.Body.Throttle_period_in_millis); err != nil {
return diag.FromErr(err)
}
return nil
}
func resourceWatchDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
resourceID, diags := clients.ResourceIDFromStr(d.Id())
if diags.HasError() {
return diags
}
if diags := elasticsearch.DeleteWatch(ctx, client, resourceID); diags.HasError() {
return diags
}
return nil
}