internal/fleet/integration_policy/models.go (122 lines of code) (raw):

package integration_policy import ( "context" "sort" "github.com/elastic/terraform-provider-elasticstack/generated/kbapi" "github.com/elastic/terraform-provider-elasticstack/internal/utils" "github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/types" ) type integrationPolicyModel struct { ID types.String `tfsdk:"id"` PolicyID types.String `tfsdk:"policy_id"` Name types.String `tfsdk:"name"` Namespace types.String `tfsdk:"namespace"` AgentPolicyID types.String `tfsdk:"agent_policy_id"` Description types.String `tfsdk:"description"` Enabled types.Bool `tfsdk:"enabled"` Force types.Bool `tfsdk:"force"` IntegrationName types.String `tfsdk:"integration_name"` IntegrationVersion types.String `tfsdk:"integration_version"` Input types.List `tfsdk:"input"` //> integrationPolicyInputModel VarsJson jsontypes.Normalized `tfsdk:"vars_json"` } type integrationPolicyInputModel struct { InputID types.String `tfsdk:"input_id"` Enabled types.Bool `tfsdk:"enabled"` StreamsJson jsontypes.Normalized `tfsdk:"streams_json"` VarsJson jsontypes.Normalized `tfsdk:"vars_json"` } func (model *integrationPolicyModel) populateFromAPI(ctx context.Context, data *kbapi.PackagePolicy) diag.Diagnostics { if data == nil { return nil } var diags diag.Diagnostics model.ID = types.StringValue(data.Id) model.PolicyID = types.StringValue(data.Id) model.Name = types.StringValue(data.Name) model.Namespace = types.StringPointerValue(data.Namespace) model.AgentPolicyID = types.StringPointerValue(data.PolicyId) model.Description = types.StringPointerValue(data.Description) model.Enabled = types.BoolValue(data.Enabled) model.IntegrationName = types.StringValue(data.Package.Name) model.IntegrationVersion = types.StringValue(data.Package.Version) model.VarsJson = utils.MapToNormalizedType(utils.Deref(data.Vars), path.Root("vars_json"), &diags) model.populateInputFromAPI(ctx, data.Inputs, &diags) return diags } func (model *integrationPolicyModel) populateInputFromAPI(ctx context.Context, inputs map[string]kbapi.PackagePolicyInput, diags *diag.Diagnostics) { newInputs := utils.TransformMapToSlice(ctx, inputs, path.Root("input"), diags, func(inputData kbapi.PackagePolicyInput, meta utils.MapMeta) integrationPolicyInputModel { return integrationPolicyInputModel{ InputID: types.StringValue(meta.Key), Enabled: types.BoolPointerValue(inputData.Enabled), StreamsJson: utils.MapToNormalizedType(utils.Deref(inputData.Streams), meta.Path.AtName("streams_json"), diags), VarsJson: utils.MapToNormalizedType(utils.Deref(inputData.Vars), meta.Path.AtName("vars_json"), diags), } }) if newInputs == nil { model.Input = types.ListNull(getInputTypeV1()) } else { oldInputs := utils.ListTypeAs[integrationPolicyInputModel](ctx, model.Input, path.Root("input"), diags) sortInputs(newInputs, oldInputs) inputList, d := types.ListValueFrom(ctx, getInputTypeV1(), newInputs) diags.Append(d...) model.Input = inputList } } func (model integrationPolicyModel) toAPIModel(ctx context.Context, isUpdate bool) (kbapi.PackagePolicyRequest, diag.Diagnostics) { var diags diag.Diagnostics body := kbapi.PackagePolicyRequest{ Description: model.Description.ValueStringPointer(), Force: model.Force.ValueBoolPointer(), Name: model.Name.ValueString(), Namespace: model.Namespace.ValueStringPointer(), Package: kbapi.PackagePolicyRequestPackage{ Name: model.IntegrationName.ValueString(), Version: model.IntegrationVersion.ValueString(), }, PolicyId: model.AgentPolicyID.ValueStringPointer(), Vars: utils.MapRef(utils.NormalizedTypeToMap[any](model.VarsJson, path.Root("vars_json"), &diags)), } if isUpdate { body.Id = model.ID.ValueStringPointer() } body.Inputs = utils.MapRef(utils.ListTypeToMap(ctx, model.Input, path.Root("input"), &diags, func(inputModel integrationPolicyInputModel, meta utils.ListMeta) (string, kbapi.PackagePolicyRequestInput) { return inputModel.InputID.ValueString(), kbapi.PackagePolicyRequestInput{ Enabled: inputModel.Enabled.ValueBoolPointer(), Streams: utils.MapRef(utils.NormalizedTypeToMap[kbapi.PackagePolicyRequestInputStream](inputModel.StreamsJson, meta.Path.AtName("streams_json"), &diags)), Vars: utils.MapRef(utils.NormalizedTypeToMap[any](inputModel.VarsJson, meta.Path.AtName("vars_json"), &diags)), } })) return body, diags } // sortInputs will sort the 'incoming' list of input definitions based on // the order of inputs defined in the 'existing' list. Inputs not present in // 'existing' will be placed at the end of the list. Inputs are identified by // their ID ('input_id'). The 'incoming' slice will be sorted in-place. func sortInputs(incoming []integrationPolicyInputModel, existing []integrationPolicyInputModel) { if len(existing) == 0 { sort.Slice(incoming, func(i, j int) bool { return incoming[i].InputID.ValueString() < incoming[j].InputID.ValueString() }) return } idToIndex := make(map[string]int, len(existing)) for index, inputData := range existing { inputID := inputData.InputID.ValueString() idToIndex[inputID] = index } sort.Slice(incoming, func(i, j int) bool { iID := incoming[i].InputID.ValueString() iIdx, ok := idToIndex[iID] if !ok { return false } jID := incoming[j].InputID.ValueString() jIdx, ok := idToIndex[jID] if !ok { return true } return iIdx < jIdx }) }