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

Issue667 - Add global_data_tags to fleet agent policies #1044

Open
wants to merge 83 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
bcc548e
devcontainer
Zyther Feb 13, 2025
8764537
schema and model to support global data tags
Zyther Feb 18, 2025
7f3aed7
minimum version
Zyther Feb 18, 2025
7306278
tests
Zyther Feb 18, 2025
fbe50f1
Merge branch 'elastic:main' into main
Zyther Feb 18, 2025
7327d0a
test cleanup
Zyther Feb 18, 2025
5cef248
Merge remote-tracking branch 'origin/main'
Zyther Feb 19, 2025
8c0e117
lint
Zyther Feb 19, 2025
0073c53
schema description
Zyther Feb 19, 2025
1ae728f
docs
Zyther Feb 19, 2025
741b3f2
if datatags is nil
Zyther Feb 19, 2025
80e5831
len not nil
Zyther Feb 19, 2025
0f10127
reflect instead
Zyther Feb 19, 2025
edb3613
ehh
Zyther Feb 19, 2025
a84e867
deref
Zyther Feb 19, 2025
4559698
test mod
Zyther Feb 19, 2025
443d9e3
temp dev
Zyther Feb 19, 2025
221bceb
temp dev2
Zyther Feb 19, 2025
d33762f
temp dev 3
Zyther Feb 19, 2025
5934e78
to jsonencode
Zyther Mar 3, 2025
1629527
docs
Zyther Mar 3, 2025
82a0348
pointers
Zyther Mar 3, 2025
945f95e
maybe json
Zyther Mar 4, 2025
75977b1
8.17.3 generate with new transform to combine global_data_tags schemas
Zyther Mar 4, 2025
a01a80c
amazing, types arent screaming and tests pass
Zyther Mar 4, 2025
10a33d6
Merge branch 'elastic:main' into main
Zyther Mar 5, 2025
faa7d25
changelog
Zyther Mar 5, 2025
e722758
seems like this breaks other things
Zyther Mar 5, 2025
b2c7842
using elastic/kibana 4f38cf96d24a66c98ac6dbaede2a9b92fa460b75 to gene…
Zyther Mar 5, 2025
d55a1b6
gen kbapi from github_ref=3757e641278a5186919e35a0f980ac3cda7e8ccd
Zyther Mar 5, 2025
fb2a436
fmt
Zyther Mar 6, 2025
4d8ec62
schema
Zyther Mar 6, 2025
a9c8dce
new docs
Zyther Mar 6, 2025
fcf226b
test mod
Zyther Mar 6, 2025
8422d22
novalidate
Zyther Mar 6, 2025
f9e995e
its alive
Zyther Mar 7, 2025
e07ece8
passing tests
Zyther Mar 7, 2025
f2bec33
docs
Zyther Mar 7, 2025
dfaa416
devcontainer
Zyther Feb 13, 2025
8fd542c
schema and model to support global data tags
Zyther Feb 18, 2025
7f8790f
minimum version
Zyther Feb 18, 2025
d75bfd8
tests
Zyther Feb 18, 2025
506c284
test cleanup
Zyther Feb 18, 2025
c0b8f7b
lint
Zyther Feb 19, 2025
7b5a8c8
schema description
Zyther Feb 19, 2025
6116783
docs
Zyther Feb 19, 2025
4822826
if datatags is nil
Zyther Feb 19, 2025
aea89ce
len not nil
Zyther Feb 19, 2025
008ce70
reflect instead
Zyther Feb 19, 2025
a2a3674
ehh
Zyther Feb 19, 2025
fa76d5b
deref
Zyther Feb 19, 2025
3e79fa0
test mod
Zyther Feb 19, 2025
178416a
temp dev
Zyther Feb 19, 2025
c487f13
temp dev2
Zyther Feb 19, 2025
35b3f61
temp dev 3
Zyther Feb 19, 2025
4289452
to jsonencode
Zyther Mar 3, 2025
fe4320a
docs
Zyther Mar 3, 2025
3348ea6
pointers
Zyther Mar 3, 2025
3a8c668
maybe json
Zyther Mar 4, 2025
b6697b3
8.17.3 generate with new transform to combine global_data_tags schemas
Zyther Mar 4, 2025
2658557
amazing, types arent screaming and tests pass
Zyther Mar 4, 2025
16f7951
changelog
Zyther Mar 5, 2025
4503604
seems like this breaks other things
Zyther Mar 5, 2025
704998a
using elastic/kibana 4f38cf96d24a66c98ac6dbaede2a9b92fa460b75 to gene…
Zyther Mar 5, 2025
c0b300e
gen kbapi from github_ref=3757e641278a5186919e35a0f980ac3cda7e8ccd
Zyther Mar 5, 2025
65463b5
fmt
Zyther Mar 6, 2025
457e024
schema
Zyther Mar 6, 2025
d9da725
new docs
Zyther Mar 6, 2025
e4b02a9
test mod
Zyther Mar 6, 2025
7527ddc
novalidate
Zyther Mar 6, 2025
dc0360c
its alive
Zyther Mar 7, 2025
1cf7a62
passing tests
Zyther Mar 7, 2025
39998b0
docs
Zyther Mar 7, 2025
d7332bb
Merge branch 'main' into elastic-main
Zyther Mar 12, 2025
b32eeed
Merge pull request #2 from Zyther/elastic-main
Zyther Mar 12, 2025
85d0793
requested changes
Zyther Mar 21, 2025
da8b107
prep sync
Zyther Mar 21, 2025
90dd36b
Merge branch 'main' into main
Zyther Mar 21, 2025
044b04e
changelog
Zyther Mar 21, 2025
8404167
separate test, passes
Zyther Mar 21, 2025
42874ed
remove comment in test
Zyther Mar 22, 2025
5254b77
fmt
Zyther Mar 22, 2025
542d491
test name change to create
Zyther Mar 22, 2025
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
Expand Up @@ -8,6 +8,7 @@
- Fix namespaces inconsistency when creating elasticstack_kibana_data_view resources ([#1011](https://github.com/elastic/terraform-provider-elasticstack/pull/1011))
- Update rule ID documentation. ([#1047](https://github.com/elastic/terraform-provider-elasticstack/pull/1047))
- Mark `elasticstack_kibana_action_connector.secrets` as sensitive. ([#1045](https://github.com/elastic/terraform-provider-elasticstack/pull/1045))
- Add `global_data_tags` to fleet agent policies. ([#1044](https://github.com/elastic/terraform-provider-elasticstack/pull/1044))

## [0.11.13] - 2025-01-09

Expand Down
18 changes: 18 additions & 0 deletions docs/resources/fleet_agent_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ resource "elasticstack_fleet_agent_policy" "test_policy" {
sys_monitoring = true
monitor_logs = true
monitor_metrics = true

global_data_tags = {
first_tag = {
string_value = "tag_value"
},
second_tag = {
number_value = 1.2
}
}
}
```

Expand All @@ -41,6 +50,7 @@ resource "elasticstack_fleet_agent_policy" "test_policy" {
- `description` (String) The description of the agent policy.
- `download_source_id` (String) The identifier for the Elastic Agent binary download server.
- `fleet_server_host_id` (String) The identifier for the Fleet server host.
- `global_data_tags` (Attributes Map) User-defined data tags to apply to all inputs. Values can be strings (string_value) or numbers (number_value) but not both. Example -- key1 = {string_value = value1}, key2 = {number_value = 42} (see [below for nested schema](#nestedatt--global_data_tags))
- `monitor_logs` (Boolean) Enable collection of agent logs.
- `monitor_metrics` (Boolean) Enable collection of agent metrics.
- `monitoring_output_id` (String) The identifier for monitoring output.
Expand All @@ -52,6 +62,14 @@ resource "elasticstack_fleet_agent_policy" "test_policy" {

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

<a id="nestedatt--global_data_tags"></a>
### Nested Schema for `global_data_tags`

Optional:

- `number_value` (Number) Number value for the field. If this is set, string_value must not be defined.
- `string_value` (String) String value for the field. If this is set, number_value must not be defined.

## Import

Import is supported using the following syntax:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ resource "elasticstack_fleet_agent_policy" "test_policy" {
sys_monitoring = true
monitor_logs = true
monitor_metrics = true

global_data_tags = {
first_tag = {
string_value = "tag_value"
},
second_tag = {
number_value = 1.2
}
}
}
171 changes: 73 additions & 98 deletions generated/kbapi/kibana.gen.go

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions generated/kbapi/transform_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,12 @@ func transformFleetPaths(schema *Schema) {
agentPolicyPath.Put.Set(fmt.Sprintf("requestBody.content.application/json.schema.properties.%s.x-omitempty", key), true)
}

schema.Components.CreateRef(schema, "agent_policy_global_data_tags_item", "schemas.agent_policy.properties.global_data_tags.items")

// Define the value types for the GlobalDataTags
agentPoliciesPath.Post.Set("requestBody.content.application/json.schema.properties.global_data_tags.items.$ref", "#/components/schemas/agent_policy_global_data_tags_item")
agentPolicyPath.Put.Set("requestBody.content.application/json.schema.properties.global_data_tags.items.$ref", "#/components/schemas/agent_policy_global_data_tags_item")

// Enrollment api keys
// https://github.com/elastic/kibana/blob/main/x-pack/plugins/fleet/common/types/models/enrollment_api_key.ts
// https://github.com/elastic/kibana/blob/main/x-pack/plugins/fleet/common/types/rest_spec/enrollment_api_key.ts
Expand Down
17 changes: 15 additions & 2 deletions internal/fleet/agent_policy/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ func (r *agentPolicyResource) Create(ctx context.Context, req resource.CreateReq
return
}

body := planModel.toAPICreateModel()
sVersion, e := r.client.ServerVersion(ctx)
if e != nil {
return
}

body, diags := planModel.toAPICreateModel(ctx, sVersion)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

sysMonitoring := planModel.SysMonitoring.ValueBool()
policy, diags := fleet.CreateAgentPolicy(ctx, client, body, sysMonitoring)
Expand All @@ -31,7 +40,11 @@ func (r *agentPolicyResource) Create(ctx context.Context, req resource.CreateReq
return
}

planModel.populateFromAPI(policy)
diags = planModel.populateFromAPI(ctx, policy)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

resp.State.Set(ctx, planModel)
resp.Diagnostics.Append(diags...)
Expand Down
128 changes: 122 additions & 6 deletions internal/fleet/agent_policy/models.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
package agent_policy

import (
"context"
"fmt"
"slices"

"github.com/elastic/terraform-provider-elasticstack/generated/kbapi"
"github.com/elastic/terraform-provider-elasticstack/internal/utils"

"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
)

type globalDataTagsItemModel struct {
StringValue types.String `tfsdk:"string_value"`
NumberValue types.Float32 `tfsdk:"number_value"`
}

type agentPolicyModel struct {
ID types.String `tfsdk:"id"`
PolicyID types.String `tfsdk:"policy_id"`
Expand All @@ -22,11 +34,12 @@ type agentPolicyModel struct {
MonitorMetrics types.Bool `tfsdk:"monitor_metrics"`
SysMonitoring types.Bool `tfsdk:"sys_monitoring"`
SkipDestroy types.Bool `tfsdk:"skip_destroy"`
GlobalDataTags types.Map `tfsdk:"global_data_tags"` //> globalDataTagsModel
}

func (model *agentPolicyModel) populateFromAPI(data *kbapi.AgentPolicy) {
func (model *agentPolicyModel) populateFromAPI(ctx context.Context, data *kbapi.AgentPolicy) diag.Diagnostics {
if data == nil {
return
return nil
}

model.ID = types.StringValue(data.Id)
Expand Down Expand Up @@ -54,10 +67,39 @@ func (model *agentPolicyModel) populateFromAPI(data *kbapi.AgentPolicy) {
model.MonitoringOutputId = types.StringPointerValue(data.MonitoringOutputId)
model.Name = types.StringValue(data.Name)
model.Namespace = types.StringValue(data.Namespace)
if utils.Deref(data.GlobalDataTags) != nil {
diags := diag.Diagnostics{}
var map0 = make(map[string]globalDataTagsItemModel)
for _, v := range utils.Deref(data.GlobalDataTags) {
maybeFloat, error := v.Value.AsAgentPolicyGlobalDataTagsItemValue1()
if error != nil {
maybeString, error := v.Value.AsAgentPolicyGlobalDataTagsItemValue0()
if error != nil {
diags.AddError("Failed to unmarshal global data tags", error.Error())
}
map0[v.Name] = globalDataTagsItemModel{
StringValue: types.StringValue(maybeString),
}
} else {
map0[v.Name] = globalDataTagsItemModel{
NumberValue: types.Float32Value(float32(maybeFloat)),
}
}
}

model.GlobalDataTags = utils.MapValueFrom(ctx, map0, getGlobalDataTagsAttrTypes().(attr.TypeWithElementType).ElementType(), path.Root("global_data_tags"), &diags)
if diags.HasError() {
return diags
}

}

return nil
}

func (model agentPolicyModel) toAPICreateModel() kbapi.PostFleetAgentPoliciesJSONRequestBody {
func (model *agentPolicyModel) toAPICreateModel(ctx context.Context, serverVersion *version.Version) (kbapi.PostFleetAgentPoliciesJSONRequestBody, diag.Diagnostics) {
monitoring := make([]kbapi.PostFleetAgentPoliciesJSONBodyMonitoringEnabled, 0, 2)

if model.MonitorLogs.ValueBool() {
monitoring = append(monitoring, kbapi.PostFleetAgentPoliciesJSONBodyMonitoringEnabledLogs)
}
Expand All @@ -77,10 +119,47 @@ func (model agentPolicyModel) toAPICreateModel() kbapi.PostFleetAgentPoliciesJSO
Namespace: model.Namespace.ValueString(),
}

return body
if len(model.GlobalDataTags.Elements()) > 0 {
var diags diag.Diagnostics
if serverVersion.LessThan(MinVersionGlobalDataTags) {
diags.AddError("global_data_tags ES version error", fmt.Sprintf("Global data tags are only supported in Elastic Stack %s and above", MinVersionGlobalDataTags))
return kbapi.PostFleetAgentPoliciesJSONRequestBody{}, diags
}

items := utils.MapTypeToMap(ctx, model.GlobalDataTags, path.Root("global_data_tags"), &diags,
func(item globalDataTagsItemModel, meta utils.MapMeta) kbapi.AgentPolicyGlobalDataTagsItem {
var value kbapi.AgentPolicyGlobalDataTagsItem_Value
var err error
if item.StringValue.ValueStringPointer() != nil {
err = value.FromAgentPolicyGlobalDataTagsItemValue0(*item.StringValue.ValueStringPointer())
} else {
err = value.FromAgentPolicyGlobalDataTagsItemValue1(*item.NumberValue.ValueFloat32Pointer())
}
if err != nil {
diags.AddError("global_data_tags validation_error_converting_values", err.Error())
return kbapi.AgentPolicyGlobalDataTagsItem{}
}
return kbapi.AgentPolicyGlobalDataTagsItem{
Name: meta.Key,
Value: value,
}
})

if diags.HasError() {
return kbapi.PostFleetAgentPoliciesJSONRequestBody{}, diags
}

itemsList := make([]kbapi.AgentPolicyGlobalDataTagsItem, 0, len(items))
for _, v := range items {
itemsList = append(itemsList, v)
}
body.GlobalDataTags = &itemsList
}

return body, nil
}

func (model agentPolicyModel) toAPIUpdateModel() kbapi.PutFleetAgentPoliciesAgentpolicyidJSONRequestBody {
func (model *agentPolicyModel) toAPIUpdateModel(ctx context.Context, serverVersion *version.Version) (kbapi.PutFleetAgentPoliciesAgentpolicyidJSONRequestBody, diag.Diagnostics) {
monitoring := make([]kbapi.PutFleetAgentPoliciesAgentpolicyidJSONBodyMonitoringEnabled, 0, 2)
if model.MonitorLogs.ValueBool() {
monitoring = append(monitoring, kbapi.Logs)
Expand All @@ -100,5 +179,42 @@ func (model agentPolicyModel) toAPIUpdateModel() kbapi.PutFleetAgentPoliciesAgen
Namespace: model.Namespace.ValueString(),
}

return body
if len(model.GlobalDataTags.Elements()) > 0 {
var diags diag.Diagnostics
if serverVersion.LessThan(MinVersionGlobalDataTags) {
diags.AddError("global_data_tags ES version error", fmt.Sprintf("Global data tags are only supported in Elastic Stack %s and above", MinVersionGlobalDataTags))
return kbapi.PutFleetAgentPoliciesAgentpolicyidJSONRequestBody{}, diags
}

items := utils.MapTypeToMap(ctx, model.GlobalDataTags, path.Root("global_data_tags"), &diags,
func(item globalDataTagsItemModel, meta utils.MapMeta) kbapi.AgentPolicyGlobalDataTagsItem {

var value kbapi.AgentPolicyGlobalDataTagsItem_Value
var err error
if item.StringValue.ValueStringPointer() != nil {
err = value.FromAgentPolicyGlobalDataTagsItemValue0(*item.StringValue.ValueStringPointer())
} else {
err = value.FromAgentPolicyGlobalDataTagsItemValue1(*item.NumberValue.ValueFloat32Pointer())
}
if err != nil {
diags.AddError("global_data_tags validation_error_converting_values", err.Error())
return kbapi.AgentPolicyGlobalDataTagsItem{}
}
return kbapi.AgentPolicyGlobalDataTagsItem{
Name: meta.Key,
Value: value,
}
})
if diags.HasError() {
return kbapi.PutFleetAgentPoliciesAgentpolicyidJSONRequestBody{}, diags
}

itemsList := make([]kbapi.AgentPolicyGlobalDataTagsItem, 0, len(items))
for _, v := range items {
itemsList = append(itemsList, v)
}
body.GlobalDataTags = &itemsList
}

return body, nil
}
6 changes: 5 additions & 1 deletion internal/fleet/agent_policy/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ func (r *agentPolicyResource) Read(ctx context.Context, req resource.ReadRequest
return
}

stateModel.populateFromAPI(policy)
diags = stateModel.populateFromAPI(ctx, policy)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

resp.State.Set(ctx, stateModel)
resp.Diagnostics.Append(diags...)
Expand Down
3 changes: 3 additions & 0 deletions internal/fleet/agent_policy/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

"github.com/elastic/terraform-provider-elasticstack/internal/clients"
"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
)
Expand All @@ -15,6 +16,8 @@ var (
_ resource.ResourceWithImportState = &agentPolicyResource{}
)

var MinVersionGlobalDataTags = version.Must(version.NewVersion("8.15.0"))

// NewResource is a helper function to simplify the provider implementation.
func NewResource() resource.Resource {
return &agentPolicyResource{}
Expand Down
Loading