diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d160259c..38adc1229 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## [Unreleased] +- Add `global_data_tags` to fleet agent policies. ([#1044](https://github.com/elastic/terraform-provider-elasticstack/pull/1044)) + ## [0.11.14] - 2025-03-17 - Fix a provider crash when interacting with elasticstack_kibana_data_view resources created with 0.11.0. ([#979](https://github.com/elastic/terraform-provider-elasticstack/pull/979)) diff --git a/docs/resources/fleet_agent_policy.md b/docs/resources/fleet_agent_policy.md index 431593ceb..0420a8c33 100644 --- a/docs/resources/fleet_agent_policy.md +++ b/docs/resources/fleet_agent_policy.md @@ -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 + } + } } ``` @@ -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. @@ -52,6 +62,14 @@ resource "elasticstack_fleet_agent_policy" "test_policy" { - `id` (String) The ID of this resource. + +### 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: diff --git a/examples/resources/elasticstack_fleet_agent_policy/resource.tf b/examples/resources/elasticstack_fleet_agent_policy/resource.tf index 81625d7fc..a6b7befe9 100644 --- a/examples/resources/elasticstack_fleet_agent_policy/resource.tf +++ b/examples/resources/elasticstack_fleet_agent_policy/resource.tf @@ -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 + } + } } diff --git a/generated/kbapi/kibana.gen.go b/generated/kbapi/kibana.gen.go index 93472041d..400a66d4a 100644 --- a/generated/kbapi/kibana.gen.go +++ b/generated/kbapi/kibana.gen.go @@ -812,17 +812,14 @@ type AgentPolicy struct { FleetServerHostId *string `json:"fleet_server_host_id"` // GlobalDataTags User defined data tags that are added to all of the inputs. The values can be strings or numbers. - GlobalDataTags *[]struct { - Name string `json:"name"` - Value AgentPolicy_GlobalDataTags_Value `json:"value"` - } `json:"global_data_tags,omitempty"` - HasFleetServer *bool `json:"has_fleet_server,omitempty"` - Id string `json:"id"` - InactivityTimeout *float32 `json:"inactivity_timeout,omitempty"` - IsDefault *bool `json:"is_default,omitempty"` - IsDefaultFleetServer *bool `json:"is_default_fleet_server,omitempty"` - IsManaged bool `json:"is_managed"` - IsPreconfigured *bool `json:"is_preconfigured,omitempty"` + GlobalDataTags *[]AgentPolicyGlobalDataTagsItem `json:"global_data_tags,omitempty"` + HasFleetServer *bool `json:"has_fleet_server,omitempty"` + Id string `json:"id"` + InactivityTimeout *float32 `json:"inactivity_timeout,omitempty"` + IsDefault *bool `json:"is_default,omitempty"` + IsDefaultFleetServer *bool `json:"is_default_fleet_server,omitempty"` + IsManaged bool `json:"is_managed"` + IsPreconfigured *bool `json:"is_preconfigured,omitempty"` // IsProtected Indicates whether the agent policy has tamper protection enabled. Default false. IsProtected bool `json:"is_protected"` @@ -871,17 +868,6 @@ type AgentPolicy struct { Version *string `json:"version,omitempty"` } -// AgentPolicyGlobalDataTagsValue0 defines model for . -type AgentPolicyGlobalDataTagsValue0 = string - -// AgentPolicyGlobalDataTagsValue1 defines model for . -type AgentPolicyGlobalDataTagsValue1 = float32 - -// AgentPolicy_GlobalDataTags_Value defines model for AgentPolicy.GlobalDataTags.Value. -type AgentPolicy_GlobalDataTags_Value struct { - union json.RawMessage -} - // AgentPolicyMonitoringEnabled defines model for AgentPolicy.MonitoringEnabled. type AgentPolicyMonitoringEnabled string @@ -1028,6 +1014,23 @@ type AgentPolicy_PackagePolicies struct { // AgentPolicyStatus defines model for AgentPolicy.Status. type AgentPolicyStatus string +// AgentPolicyGlobalDataTagsItem defines model for agent_policy_global_data_tags_item. +type AgentPolicyGlobalDataTagsItem struct { + Name string `json:"name"` + Value AgentPolicyGlobalDataTagsItem_Value `json:"value"` +} + +// AgentPolicyGlobalDataTagsItemValue0 defines model for . +type AgentPolicyGlobalDataTagsItemValue0 = string + +// AgentPolicyGlobalDataTagsItemValue1 defines model for . +type AgentPolicyGlobalDataTagsItemValue1 = float32 + +// AgentPolicyGlobalDataTagsItem_Value defines model for AgentPolicyGlobalDataTagsItem.Value. +type AgentPolicyGlobalDataTagsItem_Value struct { + union json.RawMessage +} + // EnrollmentApiKey defines model for enrollment_api_key. type EnrollmentApiKey struct { // Active When false, the enrollment API key is revoked and cannot be used for enrolling Elastic Agents. @@ -2458,17 +2461,14 @@ type PostFleetAgentPoliciesJSONBody struct { Force *bool `json:"force,omitempty"` // GlobalDataTags User defined data tags that are added to all of the inputs. The values can be strings or numbers. - GlobalDataTags *[]struct { - Name string `json:"name"` - Value PostFleetAgentPoliciesJSONBody_GlobalDataTags_Value `json:"value"` - } `json:"global_data_tags,omitempty"` - HasFleetServer *bool `json:"has_fleet_server,omitempty"` - Id *string `json:"id,omitempty"` - InactivityTimeout *float32 `json:"inactivity_timeout,omitempty"` - IsDefault *bool `json:"is_default,omitempty"` - IsDefaultFleetServer *bool `json:"is_default_fleet_server,omitempty"` - IsManaged *bool `json:"is_managed,omitempty"` - IsProtected *bool `json:"is_protected,omitempty"` + GlobalDataTags *[]AgentPolicyGlobalDataTagsItem `json:"global_data_tags,omitempty"` + HasFleetServer *bool `json:"has_fleet_server,omitempty"` + Id *string `json:"id,omitempty"` + InactivityTimeout *float32 `json:"inactivity_timeout,omitempty"` + IsDefault *bool `json:"is_default,omitempty"` + IsDefaultFleetServer *bool `json:"is_default_fleet_server,omitempty"` + IsManaged *bool `json:"is_managed,omitempty"` + IsProtected *bool `json:"is_protected,omitempty"` // KeepMonitoringAlive When set to true, monitoring will be enabled but logs/metrics collection will be disabled KeepMonitoringAlive *bool `json:"keep_monitoring_alive,omitempty"` @@ -2512,17 +2512,6 @@ type PostFleetAgentPoliciesParams struct { SysMonitoring *bool `form:"sys_monitoring,omitempty" json:"sys_monitoring,omitempty"` } -// PostFleetAgentPoliciesJSONBodyGlobalDataTagsValue0 defines parameters for PostFleetAgentPolicies. -type PostFleetAgentPoliciesJSONBodyGlobalDataTagsValue0 = string - -// PostFleetAgentPoliciesJSONBodyGlobalDataTagsValue1 defines parameters for PostFleetAgentPolicies. -type PostFleetAgentPoliciesJSONBodyGlobalDataTagsValue1 = float32 - -// PostFleetAgentPoliciesJSONBody_GlobalDataTags_Value defines parameters for PostFleetAgentPolicies. -type PostFleetAgentPoliciesJSONBody_GlobalDataTags_Value struct { - union json.RawMessage -} - // PostFleetAgentPoliciesJSONBodyMonitoringEnabled defines parameters for PostFleetAgentPolicies. type PostFleetAgentPoliciesJSONBodyMonitoringEnabled string @@ -2562,17 +2551,14 @@ type PutFleetAgentPoliciesAgentpolicyidJSONBody struct { Force *bool `json:"force,omitempty"` // GlobalDataTags User defined data tags that are added to all of the inputs. The values can be strings or numbers. - GlobalDataTags *[]struct { - Name string `json:"name"` - Value PutFleetAgentPoliciesAgentpolicyidJSONBody_GlobalDataTags_Value `json:"value"` - } `json:"global_data_tags,omitempty"` - HasFleetServer *bool `json:"has_fleet_server,omitempty"` - Id *string `json:"id,omitempty"` - InactivityTimeout *float32 `json:"inactivity_timeout,omitempty"` - IsDefault *bool `json:"is_default,omitempty"` - IsDefaultFleetServer *bool `json:"is_default_fleet_server,omitempty"` - IsManaged *bool `json:"is_managed,omitempty"` - IsProtected *bool `json:"is_protected,omitempty"` + GlobalDataTags *[]AgentPolicyGlobalDataTagsItem `json:"global_data_tags,omitempty"` + HasFleetServer *bool `json:"has_fleet_server,omitempty"` + Id *string `json:"id,omitempty"` + InactivityTimeout *float32 `json:"inactivity_timeout,omitempty"` + IsDefault *bool `json:"is_default,omitempty"` + IsDefaultFleetServer *bool `json:"is_default_fleet_server,omitempty"` + IsManaged *bool `json:"is_managed,omitempty"` + IsProtected *bool `json:"is_protected,omitempty"` // KeepMonitoringAlive When set to true, monitoring will be enabled but logs/metrics collection will be disabled KeepMonitoringAlive *bool `json:"keep_monitoring_alive,omitempty"` @@ -2619,17 +2605,6 @@ type PutFleetAgentPoliciesAgentpolicyidParams struct { // PutFleetAgentPoliciesAgentpolicyidParamsFormat defines parameters for PutFleetAgentPoliciesAgentpolicyid. type PutFleetAgentPoliciesAgentpolicyidParamsFormat string -// PutFleetAgentPoliciesAgentpolicyidJSONBodyGlobalDataTagsValue0 defines parameters for PutFleetAgentPoliciesAgentpolicyid. -type PutFleetAgentPoliciesAgentpolicyidJSONBodyGlobalDataTagsValue0 = string - -// PutFleetAgentPoliciesAgentpolicyidJSONBodyGlobalDataTagsValue1 defines parameters for PutFleetAgentPoliciesAgentpolicyid. -type PutFleetAgentPoliciesAgentpolicyidJSONBodyGlobalDataTagsValue1 = float32 - -// PutFleetAgentPoliciesAgentpolicyidJSONBody_GlobalDataTags_Value defines parameters for PutFleetAgentPoliciesAgentpolicyid. -type PutFleetAgentPoliciesAgentpolicyidJSONBody_GlobalDataTags_Value struct { - union json.RawMessage -} - // PutFleetAgentPoliciesAgentpolicyidJSONBodyMonitoringEnabled defines parameters for PutFleetAgentPoliciesAgentpolicyid. type PutFleetAgentPoliciesAgentpolicyidJSONBodyMonitoringEnabled string @@ -10231,22 +10206,22 @@ func (a PackagePolicy_Elasticsearch) MarshalJSON() ([]byte, error) { return json.Marshal(object) } -// AsAgentPolicyGlobalDataTagsValue0 returns the union data inside the AgentPolicy_GlobalDataTags_Value as a AgentPolicyGlobalDataTagsValue0 -func (t AgentPolicy_GlobalDataTags_Value) AsAgentPolicyGlobalDataTagsValue0() (AgentPolicyGlobalDataTagsValue0, error) { - var body AgentPolicyGlobalDataTagsValue0 +// AsAgentPolicyPackagePolicies0 returns the union data inside the AgentPolicy_PackagePolicies as a AgentPolicyPackagePolicies0 +func (t AgentPolicy_PackagePolicies) AsAgentPolicyPackagePolicies0() (AgentPolicyPackagePolicies0, error) { + var body AgentPolicyPackagePolicies0 err := json.Unmarshal(t.union, &body) return body, err } -// FromAgentPolicyGlobalDataTagsValue0 overwrites any union data inside the AgentPolicy_GlobalDataTags_Value as the provided AgentPolicyGlobalDataTagsValue0 -func (t *AgentPolicy_GlobalDataTags_Value) FromAgentPolicyGlobalDataTagsValue0(v AgentPolicyGlobalDataTagsValue0) error { +// FromAgentPolicyPackagePolicies0 overwrites any union data inside the AgentPolicy_PackagePolicies as the provided AgentPolicyPackagePolicies0 +func (t *AgentPolicy_PackagePolicies) FromAgentPolicyPackagePolicies0(v AgentPolicyPackagePolicies0) error { b, err := json.Marshal(v) t.union = b return err } -// MergeAgentPolicyGlobalDataTagsValue0 performs a merge with any union data inside the AgentPolicy_GlobalDataTags_Value, using the provided AgentPolicyGlobalDataTagsValue0 -func (t *AgentPolicy_GlobalDataTags_Value) MergeAgentPolicyGlobalDataTagsValue0(v AgentPolicyGlobalDataTagsValue0) error { +// MergeAgentPolicyPackagePolicies0 performs a merge with any union data inside the AgentPolicy_PackagePolicies, using the provided AgentPolicyPackagePolicies0 +func (t *AgentPolicy_PackagePolicies) MergeAgentPolicyPackagePolicies0(v AgentPolicyPackagePolicies0) error { b, err := json.Marshal(v) if err != nil { return err @@ -10257,22 +10232,22 @@ func (t *AgentPolicy_GlobalDataTags_Value) MergeAgentPolicyGlobalDataTagsValue0( return err } -// AsAgentPolicyGlobalDataTagsValue1 returns the union data inside the AgentPolicy_GlobalDataTags_Value as a AgentPolicyGlobalDataTagsValue1 -func (t AgentPolicy_GlobalDataTags_Value) AsAgentPolicyGlobalDataTagsValue1() (AgentPolicyGlobalDataTagsValue1, error) { - var body AgentPolicyGlobalDataTagsValue1 +// AsAgentPolicyPackagePolicies1 returns the union data inside the AgentPolicy_PackagePolicies as a AgentPolicyPackagePolicies1 +func (t AgentPolicy_PackagePolicies) AsAgentPolicyPackagePolicies1() (AgentPolicyPackagePolicies1, error) { + var body AgentPolicyPackagePolicies1 err := json.Unmarshal(t.union, &body) return body, err } -// FromAgentPolicyGlobalDataTagsValue1 overwrites any union data inside the AgentPolicy_GlobalDataTags_Value as the provided AgentPolicyGlobalDataTagsValue1 -func (t *AgentPolicy_GlobalDataTags_Value) FromAgentPolicyGlobalDataTagsValue1(v AgentPolicyGlobalDataTagsValue1) error { +// FromAgentPolicyPackagePolicies1 overwrites any union data inside the AgentPolicy_PackagePolicies as the provided AgentPolicyPackagePolicies1 +func (t *AgentPolicy_PackagePolicies) FromAgentPolicyPackagePolicies1(v AgentPolicyPackagePolicies1) error { b, err := json.Marshal(v) t.union = b return err } -// MergeAgentPolicyGlobalDataTagsValue1 performs a merge with any union data inside the AgentPolicy_GlobalDataTags_Value, using the provided AgentPolicyGlobalDataTagsValue1 -func (t *AgentPolicy_GlobalDataTags_Value) MergeAgentPolicyGlobalDataTagsValue1(v AgentPolicyGlobalDataTagsValue1) error { +// MergeAgentPolicyPackagePolicies1 performs a merge with any union data inside the AgentPolicy_PackagePolicies, using the provided AgentPolicyPackagePolicies1 +func (t *AgentPolicy_PackagePolicies) MergeAgentPolicyPackagePolicies1(v AgentPolicyPackagePolicies1) error { b, err := json.Marshal(v) if err != nil { return err @@ -10283,32 +10258,32 @@ func (t *AgentPolicy_GlobalDataTags_Value) MergeAgentPolicyGlobalDataTagsValue1( return err } -func (t AgentPolicy_GlobalDataTags_Value) MarshalJSON() ([]byte, error) { +func (t AgentPolicy_PackagePolicies) MarshalJSON() ([]byte, error) { b, err := t.union.MarshalJSON() return b, err } -func (t *AgentPolicy_GlobalDataTags_Value) UnmarshalJSON(b []byte) error { +func (t *AgentPolicy_PackagePolicies) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } -// AsAgentPolicyPackagePolicies0 returns the union data inside the AgentPolicy_PackagePolicies as a AgentPolicyPackagePolicies0 -func (t AgentPolicy_PackagePolicies) AsAgentPolicyPackagePolicies0() (AgentPolicyPackagePolicies0, error) { - var body AgentPolicyPackagePolicies0 +// AsAgentPolicyGlobalDataTagsItemValue0 returns the union data inside the AgentPolicyGlobalDataTagsItem_Value as a AgentPolicyGlobalDataTagsItemValue0 +func (t AgentPolicyGlobalDataTagsItem_Value) AsAgentPolicyGlobalDataTagsItemValue0() (AgentPolicyGlobalDataTagsItemValue0, error) { + var body AgentPolicyGlobalDataTagsItemValue0 err := json.Unmarshal(t.union, &body) return body, err } -// FromAgentPolicyPackagePolicies0 overwrites any union data inside the AgentPolicy_PackagePolicies as the provided AgentPolicyPackagePolicies0 -func (t *AgentPolicy_PackagePolicies) FromAgentPolicyPackagePolicies0(v AgentPolicyPackagePolicies0) error { +// FromAgentPolicyGlobalDataTagsItemValue0 overwrites any union data inside the AgentPolicyGlobalDataTagsItem_Value as the provided AgentPolicyGlobalDataTagsItemValue0 +func (t *AgentPolicyGlobalDataTagsItem_Value) FromAgentPolicyGlobalDataTagsItemValue0(v AgentPolicyGlobalDataTagsItemValue0) error { b, err := json.Marshal(v) t.union = b return err } -// MergeAgentPolicyPackagePolicies0 performs a merge with any union data inside the AgentPolicy_PackagePolicies, using the provided AgentPolicyPackagePolicies0 -func (t *AgentPolicy_PackagePolicies) MergeAgentPolicyPackagePolicies0(v AgentPolicyPackagePolicies0) error { +// MergeAgentPolicyGlobalDataTagsItemValue0 performs a merge with any union data inside the AgentPolicyGlobalDataTagsItem_Value, using the provided AgentPolicyGlobalDataTagsItemValue0 +func (t *AgentPolicyGlobalDataTagsItem_Value) MergeAgentPolicyGlobalDataTagsItemValue0(v AgentPolicyGlobalDataTagsItemValue0) error { b, err := json.Marshal(v) if err != nil { return err @@ -10319,22 +10294,22 @@ func (t *AgentPolicy_PackagePolicies) MergeAgentPolicyPackagePolicies0(v AgentPo return err } -// AsAgentPolicyPackagePolicies1 returns the union data inside the AgentPolicy_PackagePolicies as a AgentPolicyPackagePolicies1 -func (t AgentPolicy_PackagePolicies) AsAgentPolicyPackagePolicies1() (AgentPolicyPackagePolicies1, error) { - var body AgentPolicyPackagePolicies1 +// AsAgentPolicyGlobalDataTagsItemValue1 returns the union data inside the AgentPolicyGlobalDataTagsItem_Value as a AgentPolicyGlobalDataTagsItemValue1 +func (t AgentPolicyGlobalDataTagsItem_Value) AsAgentPolicyGlobalDataTagsItemValue1() (AgentPolicyGlobalDataTagsItemValue1, error) { + var body AgentPolicyGlobalDataTagsItemValue1 err := json.Unmarshal(t.union, &body) return body, err } -// FromAgentPolicyPackagePolicies1 overwrites any union data inside the AgentPolicy_PackagePolicies as the provided AgentPolicyPackagePolicies1 -func (t *AgentPolicy_PackagePolicies) FromAgentPolicyPackagePolicies1(v AgentPolicyPackagePolicies1) error { +// FromAgentPolicyGlobalDataTagsItemValue1 overwrites any union data inside the AgentPolicyGlobalDataTagsItem_Value as the provided AgentPolicyGlobalDataTagsItemValue1 +func (t *AgentPolicyGlobalDataTagsItem_Value) FromAgentPolicyGlobalDataTagsItemValue1(v AgentPolicyGlobalDataTagsItemValue1) error { b, err := json.Marshal(v) t.union = b return err } -// MergeAgentPolicyPackagePolicies1 performs a merge with any union data inside the AgentPolicy_PackagePolicies, using the provided AgentPolicyPackagePolicies1 -func (t *AgentPolicy_PackagePolicies) MergeAgentPolicyPackagePolicies1(v AgentPolicyPackagePolicies1) error { +// MergeAgentPolicyGlobalDataTagsItemValue1 performs a merge with any union data inside the AgentPolicyGlobalDataTagsItem_Value, using the provided AgentPolicyGlobalDataTagsItemValue1 +func (t *AgentPolicyGlobalDataTagsItem_Value) MergeAgentPolicyGlobalDataTagsItemValue1(v AgentPolicyGlobalDataTagsItemValue1) error { b, err := json.Marshal(v) if err != nil { return err @@ -10345,12 +10320,12 @@ func (t *AgentPolicy_PackagePolicies) MergeAgentPolicyPackagePolicies1(v AgentPo return err } -func (t AgentPolicy_PackagePolicies) MarshalJSON() ([]byte, error) { +func (t AgentPolicyGlobalDataTagsItem_Value) MarshalJSON() ([]byte, error) { b, err := t.union.MarshalJSON() return b, err } -func (t *AgentPolicy_PackagePolicies) UnmarshalJSON(b []byte) error { +func (t *AgentPolicyGlobalDataTagsItem_Value) UnmarshalJSON(b []byte) error { err := t.union.UnmarshalJSON(b) return err } diff --git a/generated/kbapi/transform_schema.go b/generated/kbapi/transform_schema.go index 62a5cfd53..f1f0c4883 100644 --- a/generated/kbapi/transform_schema.go +++ b/generated/kbapi/transform_schema.go @@ -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 diff --git a/internal/fleet/agent_policy/create.go b/internal/fleet/agent_policy/create.go index 86e4a9d25..b07b6a607 100644 --- a/internal/fleet/agent_policy/create.go +++ b/internal/fleet/agent_policy/create.go @@ -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) @@ -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...) diff --git a/internal/fleet/agent_policy/models.go b/internal/fleet/agent_policy/models.go index 0f06dce37..6ff4b7b81 100644 --- a/internal/fleet/agent_policy/models.go +++ b/internal/fleet/agent_policy/models.go @@ -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"` @@ -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) @@ -47,17 +60,95 @@ func (model *agentPolicyModel) populateFromAPI(data *kbapi.AgentPolicy) { if !utils.IsKnown(model.MonitorLogs) { model.MonitorLogs = types.BoolValue(false) } - if !utils.IsKnown(model.MonitorLogs) { - model.MonitorLogs = types.BoolValue(false) + if !utils.IsKnown(model.MonitorMetrics) { + model.MonitorMetrics = types.BoolValue(false) } 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 { +// convertGlobalDataTags converts the global data tags from terraform model to API model +// and performs version validation +func (model *agentPolicyModel) convertGlobalDataTags(ctx context.Context, serverVersion *version.Version) (*[]kbapi.AgentPolicyGlobalDataTagsItem, diag.Diagnostics) { + var diags diag.Diagnostics + + if len(model.GlobalDataTags.Elements()) == 0 { + if serverVersion.GreaterThanOrEqual(MinVersionGlobalDataTags) { + emptyList := make([]kbapi.AgentPolicyGlobalDataTagsItem, 0) + return &emptyList, diags + } + return nil, diags + } + + 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 nil, 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 nil, diags + } + + itemsList := make([]kbapi.AgentPolicyGlobalDataTagsItem, 0, len(items)) + for _, v := range items { + itemsList = append(itemsList, v) + } + + return &itemsList, diags +} + +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) } @@ -77,10 +168,16 @@ func (model agentPolicyModel) toAPICreateModel() kbapi.PostFleetAgentPoliciesJSO Namespace: model.Namespace.ValueString(), } - return body + tags, diags := model.convertGlobalDataTags(ctx, serverVersion) + if diags.HasError() { + return kbapi.PostFleetAgentPoliciesJSONRequestBody{}, diags + } + body.GlobalDataTags = tags + + 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) @@ -100,5 +197,11 @@ func (model agentPolicyModel) toAPIUpdateModel() kbapi.PutFleetAgentPoliciesAgen Namespace: model.Namespace.ValueString(), } - return body + tags, diags := model.convertGlobalDataTags(ctx, serverVersion) + if diags.HasError() { + return kbapi.PutFleetAgentPoliciesAgentpolicyidJSONRequestBody{}, diags + } + body.GlobalDataTags = tags + + return body, nil } diff --git a/internal/fleet/agent_policy/read.go b/internal/fleet/agent_policy/read.go index 7d6714c13..5ad7f70df 100644 --- a/internal/fleet/agent_policy/read.go +++ b/internal/fleet/agent_policy/read.go @@ -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...) diff --git a/internal/fleet/agent_policy/resource.go b/internal/fleet/agent_policy/resource.go index 5d0628d33..917bec042 100644 --- a/internal/fleet/agent_policy/resource.go +++ b/internal/fleet/agent_policy/resource.go @@ -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" ) @@ -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{} diff --git a/internal/fleet/agent_policy/resource_test.go b/internal/fleet/agent_policy/resource_test.go index cd0d41d1f..a8b183123 100644 --- a/internal/fleet/agent_policy/resource_test.go +++ b/internal/fleet/agent_policy/resource_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "regexp" "testing" "github.com/elastic/terraform-provider-elasticstack/internal/acctest" @@ -18,6 +19,7 @@ import ( ) var minVersionAgentPolicy = version.Must(version.NewVersion("8.6.0")) +var minVersionGlobalDataTags = version.Must(version.NewVersion("8.15.0")) func TestAccResourceAgentPolicyFromSDK(t *testing.T) { policyName := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum) @@ -63,6 +65,8 @@ func TestAccResourceAgentPolicyFromSDK(t *testing.T) { func TestAccResourceAgentPolicy(t *testing.T) { policyName := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum) + policyNameGlobalDataTags := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum) + var originalPolicyId string resource.Test(t, resource.TestCase{ @@ -118,6 +122,47 @@ func TestAccResourceAgentPolicy(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"skip_destroy"}, }, + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionGlobalDataTags), + Config: testAccResourceAgentPolicyCreateWithGlobalDataTags(policyNameGlobalDataTags, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "name", fmt.Sprintf("Policy %s", policyNameGlobalDataTags)), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "namespace", "default"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "description", "Test Agent Policy"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_logs", "true"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_metrics", "false"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "skip_destroy", "false"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "global_data_tags.tag1.string_value", "value1"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "global_data_tags.tag2.number_value", "1.1"), + ), + }, + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionGlobalDataTags), + Config: testAccResourceAgentPolicyUpdateWithGlobalDataTags(policyNameGlobalDataTags, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "name", fmt.Sprintf("Updated Policy %s", policyNameGlobalDataTags)), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "namespace", "default"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "description", "This policy was updated"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_logs", "false"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_metrics", "true"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "skip_destroy", "false"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "global_data_tags.tag1.string_value", "value1a"), + resource.TestCheckNoResourceAttr("elasticstack_fleet_agent_policy.test_policy", "global_data_tags.tag2"), + ), + }, + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionGlobalDataTags), + Config: testAccResourceAgentPolicyUpdateWithNoGlobalDataTags(policyNameGlobalDataTags, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "name", fmt.Sprintf("Updated Policy %s", policyNameGlobalDataTags)), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "namespace", "default"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "description", "This policy was updated without global data tags"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_logs", "false"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "monitor_metrics", "true"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "skip_destroy", "false"), + resource.TestCheckResourceAttr("elasticstack_fleet_agent_policy.test_policy", "global_data_tags.#", "0"), + ), + }, }, }) } @@ -146,6 +191,22 @@ func TestAccResourceAgentPolicySkipDestroy(t *testing.T) { }) } +func TestAccResourceAgentPolicyWithBadGlobalDataTags(t *testing.T) { + policyName := sdkacctest.RandStringFromCharSet(22, sdkacctest.CharSetAlphaNum) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: acctest.Providers, + Steps: []resource.TestStep{ + { + SkipFunc: versionutils.CheckIfVersionIsUnsupported(minVersionGlobalDataTags), + Config: testAccResourceAgentPolicyCreateWithBadGlobalDataTags(policyName, true), + ExpectError: regexp.MustCompile(".*Error: Invalid Attribute Combination.*"), + }, + }, + }) +} + func testAccResourceAgentPolicyCreate(id string, skipDestroy bool) string { return fmt.Sprintf(` provider "elasticstack" { @@ -168,6 +229,113 @@ data "elasticstack_fleet_enrollment_tokens" "test_policy" { `, fmt.Sprintf("Policy %s", id), skipDestroy) } +func testAccResourceAgentPolicyCreateWithGlobalDataTags(id string, skipDestroy bool) string { + return fmt.Sprintf(` +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_fleet_agent_policy" "test_policy" { + name = "%s" + namespace = "default" + description = "Test Agent Policy" + monitor_logs = true + monitor_metrics = false + skip_destroy = %t + global_data_tags = { + tag1 = { + string_value = "value1" + }, + tag2 = { + number_value = 1.1 + } + } +} + +data "elasticstack_fleet_enrollment_tokens" "test_policy" { + policy_id = elasticstack_fleet_agent_policy.test_policy.policy_id +} + +`, fmt.Sprintf("Policy %s", id), skipDestroy) +} + +func testAccResourceAgentPolicyCreateWithBadGlobalDataTags(id string, skipDestroy bool) string { + return fmt.Sprintf(` +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_fleet_agent_policy" "test_policy" { + name = "%s" + namespace = "default" + description = "This policy was not created due to bad tags" + monitor_logs = false + monitor_metrics = true + skip_destroy = %t + global_data_tags = { + tag1 = { + string_value = "value1a" + number_value = 1.2 + } + } +} + +data "elasticstack_fleet_enrollment_tokens" "test_policy" { + policy_id = elasticstack_fleet_agent_policy.test_policy.policy_id +} +`, fmt.Sprintf("Updated Policy %s", id), skipDestroy) +} + +func testAccResourceAgentPolicyUpdateWithGlobalDataTags(id string, skipDestroy bool) string { + return fmt.Sprintf(` +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_fleet_agent_policy" "test_policy" { + name = "%s" + namespace = "default" + description = "This policy was updated" + monitor_logs = false + monitor_metrics = true + skip_destroy = %t + global_data_tags = { + tag1 = { + string_value = "value1a" + } + } +} + +data "elasticstack_fleet_enrollment_tokens" "test_policy" { + policy_id = elasticstack_fleet_agent_policy.test_policy.policy_id +} +`, fmt.Sprintf("Updated Policy %s", id), skipDestroy) +} + +func testAccResourceAgentPolicyUpdateWithNoGlobalDataTags(id string, skipDestroy bool) string { + return fmt.Sprintf(` +provider "elasticstack" { + elasticsearch {} + kibana {} +} + +resource "elasticstack_fleet_agent_policy" "test_policy" { + name = "%s" + namespace = "default" + description = "This policy was updated without global data tags" + monitor_logs = false + monitor_metrics = true + skip_destroy = %t +} + +data "elasticstack_fleet_enrollment_tokens" "test_policy" { + policy_id = elasticstack_fleet_agent_policy.test_policy.policy_id +} +`, fmt.Sprintf("Updated Policy %s", id), skipDestroy) +} func testAccResourceAgentPolicyUpdate(id string, skipDestroy bool) string { return fmt.Sprintf(` diff --git a/internal/fleet/agent_policy/schema.go b/internal/fleet/agent_policy/schema.go index 7b0e4507d..c6fc0b812 100644 --- a/internal/fleet/agent_policy/schema.go +++ b/internal/fleet/agent_policy/schema.go @@ -3,83 +3,127 @@ package agent_policy import ( "context" + "github.com/hashicorp/terraform-plugin-framework-validators/float32validator" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" ) func (r *agentPolicyResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema.Description = "Creates a new Fleet Agent Policy. See https://www.elastic.co/guide/en/fleet/current/agent-policy.html" - resp.Schema.Attributes = map[string]schema.Attribute{ - "id": schema.StringAttribute{ - Description: "The ID of this resource.", - Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), + resp.Schema = getSchema() +} + +func getSchema() schema.Schema { + return schema.Schema{ + Description: "Creates a new Fleet Agent Policy. See https://www.elastic.co/guide/en/fleet/current/agent-policy.html", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: "The ID of this resource.", + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + }, + }, + "policy_id": schema.StringAttribute{ + Description: "Unique identifier of the agent policy.", + Computed: true, + Optional: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.UseStateForUnknown(), + stringplanmodifier.RequiresReplace(), + }, + }, + "name": schema.StringAttribute{ + Description: "The name of the agent policy.", + Required: true, + }, + "namespace": schema.StringAttribute{ + Description: "The namespace of the agent policy.", + Required: true, + }, + "description": schema.StringAttribute{ + Description: "The description of the agent policy.", + Optional: true, + }, + "data_output_id": schema.StringAttribute{ + Description: "The identifier for the data output.", + Optional: true, }, - }, - "policy_id": schema.StringAttribute{ - Description: "Unique identifier of the agent policy.", - Computed: true, - Optional: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - stringplanmodifier.RequiresReplace(), + "monitoring_output_id": schema.StringAttribute{ + Description: "The identifier for monitoring output.", + Optional: true, }, - }, - "name": schema.StringAttribute{ - Description: "The name of the agent policy.", - Required: true, - }, - "namespace": schema.StringAttribute{ - Description: "The namespace of the agent policy.", - Required: true, - }, - "description": schema.StringAttribute{ - Description: "The description of the agent policy.", - Optional: true, - }, - "data_output_id": schema.StringAttribute{ - Description: "The identifier for the data output.", - Optional: true, - }, - "monitoring_output_id": schema.StringAttribute{ - Description: "The identifier for monitoring output.", - Optional: true, - }, - "fleet_server_host_id": schema.StringAttribute{ - Description: "The identifier for the Fleet server host.", - Optional: true, - }, - "download_source_id": schema.StringAttribute{ - Description: "The identifier for the Elastic Agent binary download server.", - Optional: true, - }, - "monitor_logs": schema.BoolAttribute{ - Description: "Enable collection of agent logs.", - Computed: true, - Optional: true, - Default: booldefault.StaticBool(false), - }, - "monitor_metrics": schema.BoolAttribute{ - Description: "Enable collection of agent metrics.", - Computed: true, - Optional: true, - Default: booldefault.StaticBool(false), - }, - "skip_destroy": schema.BoolAttribute{ - Description: "Set to true if you do not wish the agent policy to be deleted at destroy time, and instead just remove the agent policy from the Terraform state.", - Optional: true, - }, - "sys_monitoring": schema.BoolAttribute{ - Description: "Enable collection of system logs and metrics.", - Optional: true, - PlanModifiers: []planmodifier.Bool{ - boolplanmodifier.RequiresReplace(), + "fleet_server_host_id": schema.StringAttribute{ + Description: "The identifier for the Fleet server host.", + Optional: true, }, - }, - } + "download_source_id": schema.StringAttribute{ + Description: "The identifier for the Elastic Agent binary download server.", + Optional: true, + }, + "monitor_logs": schema.BoolAttribute{ + Description: "Enable collection of agent logs.", + Computed: true, + Optional: true, + Default: booldefault.StaticBool(false), + }, + "monitor_metrics": schema.BoolAttribute{ + Description: "Enable collection of agent metrics.", + Computed: true, + Optional: true, + Default: booldefault.StaticBool(false), + }, + "skip_destroy": schema.BoolAttribute{ + Description: "Set to true if you do not wish the agent policy to be deleted at destroy time, and instead just remove the agent policy from the Terraform state.", + Optional: true, + }, + "sys_monitoring": schema.BoolAttribute{ + Description: "Enable collection of system logs and metrics.", + Optional: true, + PlanModifiers: []planmodifier.Bool{ + boolplanmodifier.RequiresReplace(), + }, + }, + "global_data_tags": schema.MapNestedAttribute{ + Description: "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}", + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "string_value": schema.StringAttribute{ + Description: "String value for the field. If this is set, number_value must not be defined.", + Optional: true, + Validators: []validator.String{ + stringvalidator.ConflictsWith(path.MatchRelative().AtParent().AtName("number_value")), + }, + }, + "number_value": schema.Float32Attribute{ + Description: "Number value for the field. If this is set, string_value must not be defined.", + Optional: true, + Validators: []validator.Float32{ + float32validator.ConflictsWith(path.MatchRelative().AtParent().AtName("string_value")), + }, + }, + }, + }, + Computed: true, + Optional: true, + Default: mapdefault.StaticValue(types.MapValueMust(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "string_value": types.StringType, + "number_value": types.Float32Type, + }, + }, map[string]attr.Value{})), + }, + }} +} +func getGlobalDataTagsAttrTypes() attr.Type { + return getSchema().Attributes["global_data_tags"].GetType() } diff --git a/internal/fleet/agent_policy/update.go b/internal/fleet/agent_policy/update.go index 68313eeee..2bdac21e8 100644 --- a/internal/fleet/agent_policy/update.go +++ b/internal/fleet/agent_policy/update.go @@ -22,7 +22,17 @@ func (r *agentPolicyResource) Update(ctx context.Context, req resource.UpdateReq return } - body := planModel.toAPIUpdateModel() + sVersion, e := r.client.ServerVersion(ctx) + if e != nil { + return + } + + body, diags := planModel.toAPIUpdateModel(ctx, sVersion) + + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } policyID := planModel.PolicyID.ValueString() policy, diags := fleet.UpdateAgentPolicy(ctx, client, policyID, body) @@ -31,7 +41,7 @@ func (r *agentPolicyResource) Update(ctx context.Context, req resource.UpdateReq return } - planModel.populateFromAPI(policy) + planModel.populateFromAPI(ctx, policy) diags = resp.State.Set(ctx, planModel) resp.Diagnostics.Append(diags...)