Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## [Unreleased]

- Add `ignore_missing_component_templates` to `elasticstack_elasticsearch_index_template` ([#1206](https://github.com/elastic/terraform-provider-elasticstack/pull/1206))
- Migrate `elasticstack_elasticsearch_enrich_policy` resource and data source to Terraform Plugin Framework ([#1220](https://github.com/elastic/terraform-provider-elasticstack/pull/1220))

## [0.11.17] - 2025-07-21

Expand Down
32 changes: 28 additions & 4 deletions docs/data-sources/elasticsearch_enrich_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,35 @@ output "query" {

- `name` (String) The name of the policy.

### Optional

- `elasticsearch_connection` (Block List, Deprecated) Elasticsearch connection configuration block. (see [below for nested schema](#nestedblock--elasticsearch_connection))

### Read-Only

- `enrich_fields` (Set of String) Fields to add to matching incoming documents. These fields must be present in the source indices.
- `enrich_fields` (List of String) Fields to add to matching incoming documents. These fields must be present in the source indices.
- `id` (String) Internal identifier of the resource
- `indices` (Set of String) Array of one or more source indices used to create the enrich index.
- `match_field` (String) Field in source indices used to match incoming documents.
- `indices` (List of String) Array of one or more source indices used to create the enrich index.
- `match_field` (String) Field from the source indices used to match incoming documents.
- `policy_type` (String) The type of enrich policy, can be one of geo_match, match, range.
- `query` (String) Query used to filter documents in the enrich index. The policy only uses documents matching this query to enrich incoming documents. Defaults to a match_all query.
- `query` (String) Query used to filter documents in the enrich index for matching.

<a id="nestedblock--elasticsearch_connection"></a>
### Nested Schema for `elasticsearch_connection`

Optional:

- `api_key` (String, Sensitive) API Key to use for authentication to Elasticsearch
- `bearer_token` (String, Sensitive) Bearer Token to use for authentication to Elasticsearch
- `ca_data` (String) PEM-encoded custom Certificate Authority certificate
- `ca_file` (String) Path to a custom Certificate Authority certificate
- `cert_data` (String) PEM encoded certificate for client auth
- `cert_file` (String) Path to a file containing the PEM encoded certificate for client auth
- `endpoints` (List of String, Sensitive) A list of endpoints where the terraform provider will point to, this must include the http(s) schema and port number.
- `es_client_authentication` (String, Sensitive) ES Client Authentication field to be used with the JWT token
- `headers` (Map of String, Sensitive) A list of headers to be sent with each request to Elasticsearch.
- `insecure` (Boolean) Disable TLS certificate validation
- `key_data` (String, Sensitive) PEM encoded private key for client auth
- `key_file` (String) Path to a file containing the PEM encoded private key for client auth
- `password` (String, Sensitive) Password to use for API authentication to Elasticsearch.
- `username` (String) Username to use for API authentication to Elasticsearch.
8 changes: 4 additions & 4 deletions docs/resources/elasticsearch_enrich_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,21 @@ resource "elasticstack_elasticsearch_enrich_policy" "policy1" {

### Required

- `enrich_fields` (Set of String) Fields to add to matching incoming documents. These fields must be present in the source indices.
- `indices` (Set of String) Array of one or more source indices used to create the enrich index.
- `enrich_fields` (List of String) Fields to add to matching incoming documents. These fields must be present in the source indices.
- `indices` (List of String) Array of one or more source indices used to create the enrich index.
- `match_field` (String) Field in source indices used to match incoming documents.
- `name` (String) Name of the enrich policy to manage.
- `policy_type` (String) The type of enrich policy, can be one of geo_match, match, range.

### Optional

- `elasticsearch_connection` (Block List, Max: 1, Deprecated) Elasticsearch connection configuration block. This property will be removed in a future provider version. Configure the Elasticsearch connection via the provider configuration instead. (see [below for nested schema](#nestedblock--elasticsearch_connection))
- `elasticsearch_connection` (Block List, Deprecated) Elasticsearch connection configuration block. (see [below for nested schema](#nestedblock--elasticsearch_connection))
- `execute` (Boolean) Whether to call the execute API function in order to create the enrich index.
- `query` (String) Query used to filter documents in the enrich index. The policy only uses documents matching this query to enrich incoming documents. Defaults to a match_all query.

### Read-Only

- `id` (String) The ID of this resource.
- `id` (String) Internal identifier of the resource

<a id="nestedblock--elasticsearch_connection"></a>
### Nested Schema for `elasticsearch_connection`
Expand Down
200 changes: 200 additions & 0 deletions internal/elasticsearch/enrich/acc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
package enrich_test

import (
"encoding/json"
"fmt"
"net/http"
"testing"

"github.com/elastic/terraform-provider-elasticstack/internal/acctest"
"github.com/elastic/terraform-provider-elasticstack/internal/clients"
sdkacctest "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccResourceEnrichPolicyFW(t *testing.T) {
name := sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
CheckDestroy: checkEnrichPolicyDestroyFW(name),
ProtoV6ProviderFactories: acctest.Providers,
Steps: []resource.TestStep{
{
Config: testAccEnrichPolicyFW(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "name", name),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "policy_type", "match"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "match_field", `email`),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "indices.0", name),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "enrich_fields.0", "first_name"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "enrich_fields.1", "last_name"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "query", "{\"match_all\":{}}"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "execute", "true"),
),
},
},
})
}

func TestAccDataSourceEnrichPolicyFW(t *testing.T) {
name := sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProtoV6ProviderFactories: acctest.Providers,
Steps: []resource.TestStep{
{
Config: testAccEnrichPolicyDataSourceFW(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_enrich_policy.test", "name", name),
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_enrich_policy.test", "policy_type", "match"),
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_enrich_policy.test", "match_field", "email"),
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_enrich_policy.test", "indices.0", name),
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_enrich_policy.test", "enrich_fields.0", "first_name"),
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_enrich_policy.test", "enrich_fields.1", "last_name"),
resource.TestCheckResourceAttr("data.elasticstack_elasticsearch_enrich_policy.test", "query", "{\"match_all\":{}}"),
),
},
},
})
}

func TestAccResourceEnrichPolicyFromSDK(t *testing.T) {
name := sdkacctest.RandStringFromCharSet(10, sdkacctest.CharSetAlphaNum)
resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Steps: []resource.TestStep{
{
// Create the enrich policy with the last provider version where the enrich policy resource was built on the SDK
ExternalProviders: map[string]resource.ExternalProvider{
"elasticstack": {
Source: "elastic/elasticstack",
VersionConstraint: "0.11.17",
},
},
Config: testAccEnrichPolicyFW(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "name", name),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "policy_type", "match"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "execute", "true"),
),
},
{
ProtoV6ProviderFactories: acctest.Providers,
Config: testAccEnrichPolicyFW(name),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "name", name),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "policy_type", "match"),
resource.TestCheckResourceAttr("elasticstack_elasticsearch_enrich_policy.policy", "execute", "true"),
),
},
},
})
}

func testAccEnrichPolicyFW(name string) string {
return fmt.Sprintf(`
provider "elasticstack" {
elasticsearch {}
}

resource "elasticstack_elasticsearch_index" "my_index" {
name = "%s"

mappings = jsonencode({
properties = {
email = { type = "text" }
first_name = { type = "text" }
last_name = { type = "text" }
}
})
deletion_protection = false
}

resource "elasticstack_elasticsearch_enrich_policy" "policy" {
name = "%s"
policy_type = "match"
indices = [elasticstack_elasticsearch_index.my_index.name]
match_field = "email"
enrich_fields = ["first_name", "last_name"]
query = <<-EOD
{"match_all": {}}
EOD
}
`, name, name)
}

func testAccEnrichPolicyDataSourceFW(name string) string {
return fmt.Sprintf(`
provider "elasticstack" {
elasticsearch {}
}

resource "elasticstack_elasticsearch_index" "my_index" {
name = "%s"

mappings = jsonencode({
properties = {
email = { type = "text" }
first_name = { type = "text" }
last_name = { type = "text" }
}
})
deletion_protection = false
}

resource "elasticstack_elasticsearch_enrich_policy" "policy" {
name = "%s"
policy_type = "match"
indices = [elasticstack_elasticsearch_index.my_index.name]
match_field = "email"
enrich_fields = ["first_name", "last_name"]
query = <<-EOD
{"match_all": {}}
EOD
}

data "elasticstack_elasticsearch_enrich_policy" "test" {
name = elasticstack_elasticsearch_enrich_policy.policy.name
}
`, name, name)
}

func checkEnrichPolicyDestroyFW(name string) func(s *terraform.State) error {
return func(s *terraform.State) error {
client, err := clients.NewAcceptanceTestingClient()
if err != nil {
return err
}

for _, rs := range s.RootModule().Resources {
if rs.Type != "elasticstack_elasticsearch_enrich_policy" {
continue
}
compId, _ := clients.CompositeIdFromStr(rs.Primary.ID)
if compId.ResourceId != name {
return fmt.Errorf("Found unexpectedly enrich policy: %s", compId.ResourceId)
}
esClient, err := client.GetESClient()
if err != nil {
return err
}
req := esClient.EnrichGetPolicy.WithName(compId.ResourceId)
res, err := esClient.EnrichGetPolicy(req)
if err != nil {
return err
}
defer res.Body.Close()
if res.StatusCode == http.StatusFound {
var policiesResponse map[string]any
if err := json.NewDecoder(res.Body).Decode(&policiesResponse); err != nil {
return err
}
if len(policiesResponse["policies"].([]any)) != 0 {
return fmt.Errorf("Enrich policy (%s) still exists", compId.ResourceId)
}
}
}
return nil
}
}
94 changes: 94 additions & 0 deletions internal/elasticsearch/enrich/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package enrich

import (
"context"

"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-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
)

func (r *enrichPolicyResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
diags := r.upsert(ctx, req.Plan, &resp.State)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

func (r *enrichPolicyResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
diags := r.upsert(ctx, req.Plan, &resp.State)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
}

func (r *enrichPolicyResource) upsert(ctx context.Context, plan tfsdk.Plan, state *tfsdk.State) diag.Diagnostics {
var data EnrichPolicyData
var diags diag.Diagnostics
diags.Append(plan.Get(ctx, &data)...)
if diags.HasError() {
return diags
}

policyName := data.Name.ValueString()
id, sdkDiags := r.client.ID(ctx, policyName)
diags.Append(utils.FrameworkDiagsFromSDK(sdkDiags)...)
if diags.HasError() {
return diags
}

client, diags := clients.MaybeNewApiClientFromFrameworkResource(ctx, data.ElasticsearchConnection, r.client)
diags.Append(diags...)
if diags.HasError() {
return diags
}

// Convert framework types to model
indices := utils.ListTypeToSlice_String(ctx, data.Indices, path.Empty(), &diags)
if diags.HasError() {
return diags
}

enrichFields := utils.ListTypeToSlice_String(ctx, data.EnrichFields, path.Empty(), &diags)
if diags.HasError() {
return diags
}

policy := &models.EnrichPolicy{
Type: data.PolicyType.ValueString(),
Name: policyName,
Indices: indices,
MatchField: data.MatchField.ValueString(),
EnrichFields: enrichFields,
}

if !data.Query.IsNull() && !data.Query.IsUnknown() {
policy.Query = data.Query.ValueString()
}

if sdkDiags := elasticsearch.PutEnrichPolicy(ctx, client, policy); sdkDiags.HasError() {
diags.Append(utils.FrameworkDiagsFromSDK(sdkDiags)...)
return diags
}

data.Id = types.StringValue(id.String())

// Execute policy if requested
if !data.Execute.IsNull() && !data.Execute.IsUnknown() && data.Execute.ValueBool() {
if sdkDiags := elasticsearch.ExecuteEnrichPolicy(ctx, client, policyName); sdkDiags.HasError() {
diags.Append(utils.FrameworkDiagsFromSDK(sdkDiags)...)
return diags
}
}

diags.Append(state.Set(ctx, &data)...)
return diags
}
Loading
Loading