internal/kibana/connector.go (225 lines of code) (raw):
package kibana
import (
"context"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/elastic/terraform-provider-elasticstack/internal/clients/kibana"
"github.com/elastic/terraform-provider-elasticstack/internal/models"
"github.com/elastic/terraform-provider-elasticstack/internal/utils"
"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 ResourceActionConnector() *schema.Resource {
var connectorSchema = map[string]*schema.Schema{
"connector_id": {
Description: "A UUID v1 or v4 to use instead of a randomly generated ID.",
Type: schema.TypeString,
Computed: true,
Optional: true,
ForceNew: true,
},
"space_id": {
Description: "An identifier for the space. If space_id is not provided, the default space is used.",
Type: schema.TypeString,
Optional: true,
Default: "default",
ForceNew: true,
},
"name": {
Description: "The name of the connector. While this name does not have to be unique, a distinctive name can help you identify a connector.",
Type: schema.TypeString,
Required: true,
},
"connector_type_id": {
Description: "The ID of the connector type, e.g. `.index`.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"config": {
Description: "The configuration for the connector. Configuration properties vary depending on the connector type.",
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringIsJSON,
},
"secrets": {
Description: "The secrets configuration for the connector. Secrets configuration properties vary depending on the connector type.",
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: utils.DiffJsonSuppress,
ValidateFunc: validation.StringIsJSON,
Sensitive: true,
},
"is_deprecated": {
Description: "Indicates whether the connector type is deprecated.",
Type: schema.TypeBool,
Computed: true,
},
"is_missing_secrets": {
Description: "Indicates whether secrets are missing for the connector.",
Type: schema.TypeBool,
Computed: true,
},
"is_preconfigured": {
Description: "Indicates whether it is a preconfigured connector.",
Type: schema.TypeBool,
Computed: true,
},
}
return &schema.Resource{
Description: "Creates a Kibana action connector. See https://www.elastic.co/guide/en/kibana/current/action-types.html",
CreateContext: resourceConnectorCreate,
UpdateContext: resourceConnectorUpdate,
ReadContext: resourceConnectorRead,
DeleteContext: resourceConnectorDelete,
CustomizeDiff: connectorCustomizeDiff,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: connectorSchema,
}
}
func connectorCustomizeDiff(ctx context.Context, rd *schema.ResourceDiff, in interface{}) error {
if !rd.HasChange("config") {
return nil
}
oldVal, newVal := rd.GetChange("config")
oldJSON := oldVal.(string)
newJSON := newVal.(string)
if oldJSON == newJSON {
return nil
}
oldVal, newVal = rd.GetChange("connector_type_id")
oldTypeID := oldVal.(string)
newTypeID := newVal.(string)
if oldTypeID != newTypeID {
return nil
}
rawState := rd.GetRawState()
if !rawState.IsKnown() || rawState.IsNull() {
return nil
}
state := rawState.GetAttr("config")
if !state.IsKnown() || state.IsNull() {
return nil
}
stateJSON := state.AsString()
customJSON, err := kibana.ConnectorConfigWithDefaults(oldTypeID, newJSON, oldJSON, stateJSON)
if err != nil {
return err
}
return rd.SetNew("config", string(customJSON))
}
func resourceConnectorCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
connectorOld, diags := expandActionConnector(d)
if diags.HasError() {
return diags
}
connectorID, diags := kibana.CreateConnector(ctx, client, connectorOld)
if diags.HasError() {
return diags
}
compositeID := &clients.CompositeId{ClusterId: connectorOld.SpaceID, ResourceId: connectorID}
d.SetId(compositeID.String())
return resourceConnectorRead(ctx, d, meta)
}
func resourceConnectorUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
connectorOld, diags := expandActionConnector(d)
if diags.HasError() {
return diags
}
compositeIDold, diags := clients.CompositeIdFromStr(d.Id())
if diags.HasError() {
return diags
}
connectorOld.ConnectorID = compositeIDold.ResourceId
connectorID, diags := kibana.UpdateConnector(ctx, client, connectorOld)
if diags.HasError() {
return diags
}
compositeIDnew := &clients.CompositeId{ClusterId: connectorOld.SpaceID, ResourceId: connectorID}
d.SetId(compositeIDnew.String())
return resourceConnectorRead(ctx, d, meta)
}
func resourceConnectorRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
compositeID, diags := clients.CompositeIdFromStr(d.Id())
if diags.HasError() {
return diags
}
connector, diags := kibana.GetConnector(ctx, client, compositeID.ResourceId, compositeID.ClusterId)
if connector == nil && diags == nil {
d.SetId("")
return diags
}
if diags.HasError() {
return diags
}
return flattenActionConnector(connector, d)
}
func resourceConnectorDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, diags := clients.NewApiClientFromSDKResource(d, meta)
if diags.HasError() {
return diags
}
compositeID, diags := clients.CompositeIdFromStr(d.Id())
if diags.HasError() {
return diags
}
spaceId := d.Get("space_id").(string)
if diags := kibana.DeleteConnector(ctx, client, compositeID.ResourceId, spaceId); diags.HasError() {
return diags
}
d.SetId("")
return nil
}
func expandActionConnector(d *schema.ResourceData) (models.KibanaActionConnector, diag.Diagnostics) {
var diags diag.Diagnostics
connector := models.KibanaActionConnector{
SpaceID: d.Get("space_id").(string),
Name: d.Get("name").(string),
ConnectorTypeID: d.Get("connector_type_id").(string),
}
connector.ConfigJSON = d.Get("config").(string)
connector.SecretsJSON = d.Get("secrets").(string)
return connector, diags
}
func flattenActionConnector(connector *models.KibanaActionConnector, d *schema.ResourceData) diag.Diagnostics {
if err := d.Set("connector_id", connector.ConnectorID); err != nil {
return diag.FromErr(err)
}
if err := d.Set("space_id", connector.SpaceID); err != nil {
return diag.FromErr(err)
}
if err := d.Set("name", connector.Name); err != nil {
return diag.FromErr(err)
}
if err := d.Set("connector_type_id", connector.ConnectorTypeID); err != nil {
return diag.FromErr(err)
}
if err := d.Set("config", connector.ConfigJSON); err != nil {
return diag.FromErr(err)
}
if err := d.Set("is_deprecated", connector.IsDeprecated); err != nil {
return diag.FromErr(err)
}
if err := d.Set("is_missing_secrets", connector.IsMissingSecrets); err != nil {
return diag.FromErr(err)
}
if err := d.Set("is_preconfigured", connector.IsPreconfigured); err != nil {
return diag.FromErr(err)
}
return nil
}