diff --git a/coralogix/data_source_coralogix_tco_policy.go b/coralogix/data_source_coralogix_tco_policy_logs.go similarity index 92% rename from coralogix/data_source_coralogix_tco_policy.go rename to coralogix/data_source_coralogix_tco_policy_logs.go index 841b9d05..1f916d17 100644 --- a/coralogix/data_source_coralogix_tco_policy.go +++ b/coralogix/data_source_coralogix_tco_policy_logs.go @@ -56,7 +56,7 @@ func (d *TCOPolicyDataSource) Schema(_ context.Context, _ datasource.SchemaReque } func (d *TCOPolicyDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { - var data TCOPolicyResourceModel + var data *TCOPolicyResourceModel resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return @@ -84,8 +84,11 @@ func (d *TCOPolicyDataSource) Read(ctx context.Context, req datasource.ReadReque } log.Printf("[INFO] Received tco-policy: %#v", getPolicyResp) - data = flattenTCOPolicy(getPolicyResp.GetPolicy()) - + data, diags := flattenTCOPolicy(ctx, getPolicyResp.GetPolicy()) + if diags.HasError() { + resp.Diagnostics = diags + return + } // Save data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) + resp.Diagnostics.Append(resp.State.Set(ctx, data)...) } diff --git a/coralogix/data_source_coralogix_tco_policy_test.go b/coralogix/data_source_coralogix_tco_policy_logs_test.go similarity index 100% rename from coralogix/data_source_coralogix_tco_policy_test.go rename to coralogix/data_source_coralogix_tco_policy_logs_test.go diff --git a/coralogix/data_source_coralogix_tco_policy_traces.go b/coralogix/data_source_coralogix_tco_policy_traces.go index c2643856..03ae1a86 100644 --- a/coralogix/data_source_coralogix_tco_policy_traces.go +++ b/coralogix/data_source_coralogix_tco_policy_traces.go @@ -56,7 +56,7 @@ func (d *TCOPolicyTracesDataSource) Schema(_ context.Context, _ datasource.Schem } func (d *TCOPolicyTracesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { - var data TCOPolicyTracesResourceModel + var data *TCOPolicyTracesResourceModel resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return @@ -84,8 +84,11 @@ func (d *TCOPolicyTracesDataSource) Read(ctx context.Context, req datasource.Rea } log.Printf("[INFO] Received tco-policy: %#v", getPolicyResp) - data = flattenTCOPolicyTraces(ctx, getPolicyResp.GetPolicy()) - + data, diags := flattenTCOPolicyTraces(ctx, getPolicyResp.GetPolicy()) + if diags.HasError() { + resp.Diagnostics = diags + return + } // Save data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } diff --git a/coralogix/resource_coralogix_tco_policy_logs.go b/coralogix/resource_coralogix_tco_policy_logs.go index 9331d8c6..4a627070 100644 --- a/coralogix/resource_coralogix_tco_policy_logs.go +++ b/coralogix/resource_coralogix_tco_policy_logs.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "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/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -70,16 +71,16 @@ type TCOPolicyResource struct { } type TCOPolicyResourceModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Description types.String `tfsdk:"description"` - Enabled types.Bool `tfsdk:"enabled"` - Order types.Int64 `tfsdk:"order"` - Priority types.String `tfsdk:"priority"` - Applications *TCORuleModel `tfsdk:"applications"` - Subsystems *TCORuleModel `tfsdk:"subsystems"` - Severities types.Set `tfsdk:"severities"` - ArchiveRetentionID types.String `tfsdk:"archive_retention_id"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + Enabled types.Bool `tfsdk:"enabled"` + Order types.Int64 `tfsdk:"order"` + Priority types.String `tfsdk:"priority"` + Applications types.Object `tfsdk:"applications"` + Subsystems types.Object `tfsdk:"subsystems"` + Severities types.Set `tfsdk:"severities"` + ArchiveRetentionID types.String `tfsdk:"archive_retention_id"` } type TCORuleModel struct { @@ -230,17 +231,26 @@ func (r *TCOPolicyResource) ValidateConfig(ctx context.Context, req resource.Val validateTCORuleModelModel(data.Applications, "applications", resp) } -func validateTCORuleModelModel(rule *TCORuleModel, root string, resp *resource.ValidateConfigResponse) { - if rule != nil { - ruleType := rule.RuleType.ValueString() - nameLength := len(rule.Names.Elements()) - if (ruleType == "starts_with" || ruleType == "includes") && nameLength > 1 { - resp.Diagnostics.AddAttributeWarning( - path.Root(root), - "Conflicting Attributes Values Configuration", - fmt.Sprintf("Currently, rule_type \"%s\" is supportred with only one value, but \"names\" includes %d elements.", ruleType, nameLength), - ) - } +func validateTCORuleModelModel(rule types.Object, root string, resp *resource.ValidateConfigResponse) { + if rule.IsNull() || rule.IsUnknown() { + return + } + + ruleModel := &TCORuleModel{} + diags := rule.As(context.Background(), ruleModel, basetypes.ObjectAsOptions{}) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + + ruleType := ruleModel.RuleType.ValueString() + nameLength := len(ruleModel.Names.Elements()) + if (ruleType == "starts_with" || ruleType == "includes") && nameLength > 1 { + resp.Diagnostics.AddAttributeWarning( + path.Root(root), + "Conflicting Attributes Values Configuration", + fmt.Sprintf("Currently, rule_type \"%s\" is supportred with only one value, but \"names\" includes %d elements.", ruleType, nameLength), + ) } } @@ -295,11 +305,11 @@ func upgradeTcoPolicyStateV0ToV1(ctx context.Context, req resource.UpgradeStateR resp.Diagnostics.Append(resp.State.Set(ctx, upgradedStateData)...) } -func upgradeTCOPolicyRuleV0ToV1(ctx context.Context, tCOPolicyRule types.List) *TCORuleModel { +func upgradeTCOPolicyRuleV0ToV1(ctx context.Context, tCOPolicyRule types.List) types.Object { var tCOPolicyRuleObjects []types.Object tCOPolicyRule.ElementsAs(ctx, &tCOPolicyRuleObjects, true) if len(tCOPolicyRuleObjects) == 0 { - return nil + return types.ObjectNull(tcoPolicyRuleAttributes()) } var tCORuleModelObjectV0 TCORuleModelV0 @@ -328,7 +338,16 @@ func upgradeTCOPolicyRuleV0ToV1(ctx context.Context, tCOPolicyRule types.List) * tCORuleModelObjectV1.Names = types.SetValueMust(types.StringType, elements) } - return tCORuleModelObjectV1 + obj, _ := types.ObjectValueFrom(ctx, tcoPolicyRuleAttributes(), tCORuleModelObjectV1) + + return obj +} + +func tcoPolicyRuleAttributes() map[string]attr.Type { + return map[string]attr.Type{ + "rule_type": types.StringType, + "names": types.SetType{ElemType: types.StringType}, + } } type TCORuleModelV0 struct { @@ -434,14 +453,18 @@ func tcoPolicySchemaV0() schema.Schema { } func (r *TCOPolicyResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - var plan TCOPolicyResourceModel + var plan *TCOPolicyResourceModel diags := req.Plan.Get(ctx, &plan) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { + if diags.HasError() { + resp.Diagnostics.Append(diags...) return } - createPolicyRequest := extractCreateTcoPolicy(ctx, plan) + createPolicyRequest, diags := extractCreateTcoPolicy(ctx, *plan) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } policyStr, _ := jsm.MarshalToString(createPolicyRequest) log.Printf("[INFO] Creating new tco-policy: %s", policyStr) createResp, err := r.client.CreateTCOPolicy(ctx, createPolicyRequest) @@ -460,15 +483,18 @@ func (r *TCOPolicyResource) Create(ctx context.Context, req resource.CreateReque updatePoliciesOrder(ctx, r.client, plan.ID.ValueString(), int(plan.Order.ValueInt64()), tcopolicies.SourceType_SOURCE_TYPE_LOGS) policy.Order = wrapperspb.Int32(int32(plan.Order.ValueInt64())) - plan = flattenTCOPolicy(policy) - + plan, diags = flattenTCOPolicy(ctx, policy) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } // Set state to fully populated data diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) } func (r *TCOPolicyResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var state TCOPolicyResourceModel + var state *TCOPolicyResourceModel diags := req.State.Get(ctx, &state) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -498,7 +524,11 @@ func (r *TCOPolicyResource) Read(ctx context.Context, req resource.ReadRequest, policy := getPolicyResp.GetPolicy() log.Printf("[INFO] Received tco-policy: %#v", policy) - state = flattenTCOPolicy(policy) + state, diags = flattenTCOPolicy(ctx, policy) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } // diags = resp.State.Set(ctx, &state) resp.Diagnostics.Append(diags...) @@ -506,14 +536,19 @@ func (r *TCOPolicyResource) Read(ctx context.Context, req resource.ReadRequest, func (r *TCOPolicyResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { // Retrieve values from plan - var plan TCOPolicyResourceModel + var plan *TCOPolicyResourceModel diags := req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - policyUpdateReq := extractUpdateTCOPolicy(ctx, plan) + policyUpdateReq, diags := extractUpdateTCOPolicy(ctx, *plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + log.Printf("[INFO] Updating tco-policy: %#v", policyUpdateReq) policyUpdateResp, err := r.client.UpdateTCOPolicy(ctx, policyUpdateReq) if err != nil { @@ -549,8 +584,11 @@ func (r *TCOPolicyResource) Update(ctx context.Context, req resource.UpdateReque } log.Printf("[INFO] Received tco-policy: %#v", getPolicyResp) - plan = flattenTCOPolicy(getPolicyResp.GetPolicy()) - + plan, diags = flattenTCOPolicy(ctx, getPolicyResp.GetPolicy()) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } // Set state to fully populated data diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) @@ -576,48 +614,66 @@ func (r TCOPolicyResource) Delete(ctx context.Context, req resource.DeleteReques log.Printf("[INFO] tco-policy %s deleted\n", id) } -func flattenTCOPolicy(policy *tcopolicies.Policy) TCOPolicyResourceModel { +func flattenTCOPolicy(ctx context.Context, policy *tcopolicies.Policy) (*TCOPolicyResourceModel, diag.Diagnostics) { logRules := policy.GetSourceTypeRules().(*tcopolicies.Policy_LogRules).LogRules - tcoPolicy := TCOPolicyResourceModel{ + applications, diags := flattenTCOPolicyRule(ctx, policy.GetApplicationRule()) + if diags.HasError() { + return nil, diags + } + subsystems, diags := flattenTCOPolicyRule(ctx, policy.GetSubsystemRule()) + if diags.HasError() { + return nil, diags + } + tcoPolicy := &TCOPolicyResourceModel{ ID: types.StringValue(policy.GetId().GetValue()), Name: types.StringValue(policy.GetName().GetValue()), Description: types.StringValue(policy.GetDescription().GetValue()), Enabled: types.BoolValue(policy.GetEnabled().GetValue()), Order: types.Int64Value(int64(policy.GetOrder().GetValue())), Priority: types.StringValue(tcoPoliciesPriorityProtoToSchema[policy.GetPriority()]), - Applications: flattenTCOPolicyRule(policy.GetApplicationRule()), - Subsystems: flattenTCOPolicyRule(policy.GetSubsystemRule()), + Applications: applications, + Subsystems: subsystems, ArchiveRetentionID: flattenArchiveRetention(policy.GetArchiveRetention()), Severities: flattenTCOPolicySeverities(logRules.GetSeverities()), } - return tcoPolicy + return tcoPolicy, nil } -func flattenTCOPolicyRule(rule *tcopolicies.Rule) *TCORuleModel { +func flattenTCOPolicyRule(ctx context.Context, rule *tcopolicies.Rule) (types.Object, diag.Diagnostics) { if rule == nil { - return nil + return types.ObjectNull(tcoPolicyRuleAttributes()), nil } ruleType := types.StringValue(tcoPoliciesRuleTypeProtoToSchema[rule.GetRuleTypeId()]) - names := strings.Split(rule.GetName().GetValue(), ",") namesSet := stringSliceToTypeStringSet(names) - - return &TCORuleModel{ + tcoModel := &TCORuleModel{ RuleType: ruleType, Names: namesSet, } + + return types.ObjectValueFrom(ctx, tcoPolicyRuleAttributes(), tcoModel) } -func extractUpdateTCOPolicy(ctx context.Context, plan TCOPolicyResourceModel) *tcopolicies.UpdatePolicyRequest { +func extractUpdateTCOPolicy(ctx context.Context, plan TCOPolicyResourceModel) (*tcopolicies.UpdatePolicyRequest, diag.Diagnostics) { id := typeStringToWrapperspbString(plan.ID) name := typeStringToWrapperspbString(plan.Name) description := typeStringToWrapperspbString(plan.Description) priority := tcoPoliciesPrioritySchemaToProto[plan.Priority.ValueString()] - applicationRule := expandTCOPolicyRule(ctx, plan.Applications) - subsystemRule := expandTCOPolicyRule(ctx, plan.Subsystems) + applicationRule, diags := expandTCOPolicyRule(ctx, plan.Applications) + if diags.HasError() { + return nil, diags + } + subsystemRule, diags := expandTCOPolicyRule(ctx, plan.Subsystems) + if diags.HasError() { + return nil, diags + } archiveRetention := expandActiveRetention(plan.ArchiveRetentionID) + sourceTypeRules, diags := expandLogsSourceTypeUpdate(ctx, plan) + if diags.HasError() { + return nil, diags + } updateRequest := &tcopolicies.UpdatePolicyRequest{ Id: id, @@ -627,66 +683,84 @@ func extractUpdateTCOPolicy(ctx context.Context, plan TCOPolicyResourceModel) *t ApplicationRule: applicationRule, SubsystemRule: subsystemRule, ArchiveRetention: archiveRetention, - SourceTypeRules: expandLogsSourceTypeUpdate(plan), + SourceTypeRules: sourceTypeRules, } - return updateRequest + return updateRequest, nil } -func extractCreateTcoPolicy(ctx context.Context, plan TCOPolicyResourceModel) *tcopolicies.CreatePolicyRequest { +func extractCreateTcoPolicy(ctx context.Context, plan TCOPolicyResourceModel) (*tcopolicies.CreatePolicyRequest, diag.Diagnostics) { name := typeStringToWrapperspbString(plan.Name) description := typeStringToWrapperspbString(plan.Description) priority := tcoPoliciesPrioritySchemaToProto[plan.Priority.ValueString()] - applicationRule := expandTCOPolicyRule(ctx, plan.Applications) - subsystemRule := expandTCOPolicyRule(ctx, plan.Subsystems) + applicationRule, diags := expandTCOPolicyRule(ctx, plan.Applications) + if diags.HasError() { + return nil, diags + } + subsystemRule, diags := expandTCOPolicyRule(ctx, plan.Subsystems) + if diags.HasError() { + return nil, diags + } archiveRetention := expandActiveRetention(plan.ArchiveRetentionID) + sourceTypeRules, diags := expandLogsSourceType(ctx, plan) + if diags.HasError() { + return nil, diags + } - createRequest := &tcopolicies.CreatePolicyRequest{ + return &tcopolicies.CreatePolicyRequest{ Name: name, Description: description, Priority: priority, ApplicationRule: applicationRule, SubsystemRule: subsystemRule, ArchiveRetention: archiveRetention, - SourceTypeRules: expandLogsSourceType(plan), - } - - return createRequest + SourceTypeRules: sourceTypeRules, + }, nil } -func expandLogsSourceType(plan TCOPolicyResourceModel) *tcopolicies.CreatePolicyRequest_LogRules { - severities := expandTCOPolicySeverities(plan.Severities.Elements()) - +func expandLogsSourceType(ctx context.Context, plan TCOPolicyResourceModel) (*tcopolicies.CreatePolicyRequest_LogRules, diag.Diagnostics) { + severities, diags := expandTCOPolicySeverities(ctx, plan.Severities.Elements()) + if diags.HasError() { + return nil, diags + } return &tcopolicies.CreatePolicyRequest_LogRules{ LogRules: &tcopolicies.LogRules{ Severities: severities, }, - } + }, nil } -func expandLogsSourceTypeUpdate(plan TCOPolicyResourceModel) *tcopolicies.UpdatePolicyRequest_LogRules { - severities := expandTCOPolicySeverities(plan.Severities.Elements()) - +func expandLogsSourceTypeUpdate(ctx context.Context, plan TCOPolicyResourceModel) (*tcopolicies.UpdatePolicyRequest_LogRules, diag.Diagnostics) { + severities, diags := expandTCOPolicySeverities(ctx, plan.Severities.Elements()) + if diags.HasError() { + return nil, diags + } return &tcopolicies.UpdatePolicyRequest_LogRules{ LogRules: &tcopolicies.LogRules{ Severities: severities, }, - } + }, nil } -func expandTCOPolicyRule(ctx context.Context, rule *TCORuleModel) *tcopolicies.Rule { - if rule == nil { - return nil +func expandTCOPolicyRule(ctx context.Context, rule types.Object) (*tcopolicies.Rule, diag.Diagnostics) { + if rule.IsNull() || rule.IsUnknown() { + return nil, nil } - ruleType := tcoPoliciesRuleTypeSchemaToProto[rule.RuleType.ValueString()] - names := typeStringSliceToStringSlice(ctx, rule.Names.Elements()) + tcoRuleModel := &TCORuleModel{} + diags := rule.As(ctx, tcoRuleModel, basetypes.ObjectAsOptions{}) + if diags.HasError() { + return nil, diags + } + + ruleType := tcoPoliciesRuleTypeSchemaToProto[tcoRuleModel.RuleType.ValueString()] + names := typeStringSliceToStringSlice(ctx, tcoRuleModel.Names.Elements()) nameStr := wrapperspb.String(strings.Join(names, ",")) return &tcopolicies.Rule{ RuleTypeId: ruleType, Name: nameStr, - } + }, nil } func updatePoliciesOrder(ctx context.Context, client *clientset.TCOPoliciesClient, policyID string, policyOrder int, sourceType tcopolicies.SourceType) error { @@ -769,16 +843,21 @@ func expandActiveRetention(archiveRetention types.String) *tcopolicies.ArchiveRe } } -func expandTCOPolicySeverities(severities []attr.Value) []tcopolicies.Severity { +func expandTCOPolicySeverities(ctx context.Context, severities []attr.Value) ([]tcopolicies.Severity, diag.Diagnostics) { result := make([]tcopolicies.Severity, 0, len(severities)) + var diags diag.Diagnostics for _, severity := range severities { - val, _ := severity.ToTerraformValue(context.Background()) + val, err := severity.ToTerraformValue(ctx) + if err != nil { + diags.AddError("Error expanding tco-policy severities", err.Error()) + continue + } var str string val.As(&str) s := tcoPolicySeveritySchemaToProto[str] result = append(result, s) } - return result + return result, diags } func flattenArchiveRetention(archiveRetention *tcopolicies.ArchiveRetention) types.String { diff --git a/coralogix/resource_coralogix_tco_policy_traces.go b/coralogix/resource_coralogix_tco_policy_traces.go index 77cc435b..45c762c5 100644 --- a/coralogix/resource_coralogix_tco_policy_traces.go +++ b/coralogix/resource_coralogix_tco_policy_traces.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "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/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -43,18 +44,18 @@ type TCOPolicyTracesResource struct { } type TCOPolicyTracesResourceModel struct { - ID types.String `tfsdk:"id"` - Name types.String `tfsdk:"name"` - Description types.String `tfsdk:"description"` - Enabled types.Bool `tfsdk:"enabled"` - Order types.Int64 `tfsdk:"order"` - Priority types.String `tfsdk:"priority"` - Applications *TCORuleModel `tfsdk:"applications"` - Subsystems *TCORuleModel `tfsdk:"subsystems"` - ArchiveRetentionID types.String `tfsdk:"archive_retention_id"` - Services *TCORuleModel `tfsdk:"services"` - Actions *TCORuleModel `tfsdk:"actions"` - Tags types.Map `tfsdk:"tags"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + Enabled types.Bool `tfsdk:"enabled"` + Order types.Int64 `tfsdk:"order"` + Priority types.String `tfsdk:"priority"` + Applications types.Object `tfsdk:"applications"` + Subsystems types.Object `tfsdk:"subsystems"` + ArchiveRetentionID types.String `tfsdk:"archive_retention_id"` + Services types.Object `tfsdk:"services"` + Actions types.Object `tfsdk:"actions"` + Tags types.Map `tfsdk:"tags"` } func (r *TCOPolicyTracesResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { @@ -261,14 +262,14 @@ func (r *TCOPolicyTracesResource) ValidateConfig(ctx context.Context, req resour validateTCORuleModelModel(data.Actions, "actions", resp) - var tagsMap map[string]TCORuleModel + var tagsMap map[string]types.Object diags := data.Tags.ElementsAs(ctx, &tagsMap, true) if diags != nil { resp.Diagnostics.Append(diags...) } else { for tagName, tagRule := range tagsMap { root := fmt.Sprintf("tags.%s", tagName) - validateTCORuleModelModel(&tagRule, root, resp) + validateTCORuleModelModel(tagRule, root, resp) } } @@ -280,14 +281,18 @@ func (r *TCOPolicyTracesResource) ImportState(ctx context.Context, req resource. } func (r *TCOPolicyTracesResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - var plan TCOPolicyTracesResourceModel + var plan *TCOPolicyTracesResourceModel diags := req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - createPolicyRequest := extractCreateTcoPolicyTraces(ctx, plan) + createPolicyRequest, diags := extractCreateTcoPolicyTraces(ctx, *plan) + if diags.HasError() { + resp.Diagnostics = diags + return + } policyStr, _ := jsm.MarshalToString(createPolicyRequest) log.Printf("[INFO] Creating new tco-policy: %s", policyStr) createResp, err := r.client.CreateTCOPolicy(ctx, createPolicyRequest) @@ -306,15 +311,18 @@ func (r *TCOPolicyTracesResource) Create(ctx context.Context, req resource.Creat updatePoliciesOrder(ctx, r.client, plan.ID.ValueString(), int(plan.Order.ValueInt64()), tcopolicies.SourceType_SOURCE_TYPE_SPANS) policy.Order = wrapperspb.Int32(int32(plan.Order.ValueInt64())) - plan = flattenTCOPolicyTraces(ctx, policy) - + plan, diags = flattenTCOPolicyTraces(ctx, policy) + if diags.HasError() { + resp.Diagnostics = diags + return + } // Set state to fully populated data diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) } func (r *TCOPolicyTracesResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var state TCOPolicyTracesResourceModel + var state *TCOPolicyTracesResourceModel diags := req.State.Get(ctx, &state) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { @@ -344,7 +352,11 @@ func (r *TCOPolicyTracesResource) Read(ctx context.Context, req resource.ReadReq policy := getPolicyResp.GetPolicy() log.Printf("[INFO] Received tco-policy: %#v", policy) - state = flattenTCOPolicyTraces(ctx, policy) + state, diags = flattenTCOPolicyTraces(ctx, policy) + if diags.HasError() { + resp.Diagnostics = diags + return + } // diags = resp.State.Set(ctx, &state) resp.Diagnostics.Append(diags...) @@ -352,14 +364,18 @@ func (r *TCOPolicyTracesResource) Read(ctx context.Context, req resource.ReadReq func (r TCOPolicyTracesResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { // Retrieve values from plan - var plan TCOPolicyTracesResourceModel + var plan *TCOPolicyTracesResourceModel diags := req.Plan.Get(ctx, &plan) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } - policyUpdateReq := extractUpdateTCOPolicyTraces(ctx, plan) + policyUpdateReq, diags := extractUpdateTCOPolicyTraces(ctx, *plan) + if diags.HasError() { + resp.Diagnostics = diags + return + } log.Printf("[INFO] Updating tco-policy: %#v", policyUpdateReq) policyUpdateResp, err := r.client.UpdateTCOPolicy(ctx, policyUpdateReq) if err != nil { @@ -395,8 +411,11 @@ func (r TCOPolicyTracesResource) Update(ctx context.Context, req resource.Update } log.Printf("[INFO] Received tco-policy: %#v", getPolicyResp) - plan = flattenTCOPolicyTraces(ctx, getPolicyResp.GetPolicy()) - + plan, diags = flattenTCOPolicyTraces(ctx, getPolicyResp.GetPolicy()) + if diags.HasError() { + resp.Diagnostics = diags + return + } // Set state to fully populated data diags = resp.State.Set(ctx, plan) resp.Diagnostics.Append(diags...) @@ -422,24 +441,39 @@ func (r TCOPolicyTracesResource) Delete(ctx context.Context, req resource.Delete log.Printf("[INFO] tco-policy %s deleted\n", id) } -func flattenTCOPolicyTraces(ctx context.Context, policy *tcopolicies.Policy) TCOPolicyTracesResourceModel { +func flattenTCOPolicyTraces(ctx context.Context, policy *tcopolicies.Policy) (*TCOPolicyTracesResourceModel, diag.Diagnostics) { traceRules := policy.GetSourceTypeRules().(*tcopolicies.Policy_SpanRules).SpanRules - tcoPolicy := TCOPolicyTracesResourceModel{ + applications, diags := flattenTCOPolicyRule(ctx, policy.GetApplicationRule()) + if diags.HasError() { + return nil, diags + } + subsystems, diags := flattenTCOPolicyRule(ctx, policy.GetSubsystemRule()) + if diags.HasError() { + return nil, diags + } + services, diags := flattenTCOPolicyRule(ctx, traceRules.GetServiceRule()) + if diags.HasError() { + return nil, diags + } + actions, diags := flattenTCOPolicyRule(ctx, traceRules.GetActionRule()) + if diags.HasError() { + return nil, diags + } + + return &TCOPolicyTracesResourceModel{ ID: types.StringValue(policy.GetId().GetValue()), Name: types.StringValue(policy.GetName().GetValue()), Description: types.StringValue(policy.GetDescription().GetValue()), Enabled: types.BoolValue(policy.GetEnabled().GetValue()), Order: types.Int64Value(int64(policy.GetOrder().GetValue())), Priority: types.StringValue(tcoPoliciesPriorityProtoToSchema[policy.GetPriority()]), - Applications: flattenTCOPolicyRule(policy.GetApplicationRule()), - Subsystems: flattenTCOPolicyRule(policy.GetSubsystemRule()), + Applications: applications, + Subsystems: subsystems, ArchiveRetentionID: flattenArchiveRetention(policy.GetArchiveRetention()), - Services: flattenTCOPolicyRule(traceRules.GetServiceRule()), - Actions: flattenTCOPolicyRule(traceRules.GetActionRule()), + Services: services, + Actions: actions, Tags: flattenTCOPolicyTags(ctx, traceRules.GetTagRules()), - } - - return tcoPolicy + }, nil } func flattenTCOPolicyTags(ctx context.Context, tags []*tcopolicies.TagRule) types.Map { @@ -474,16 +508,25 @@ func tcoRuleModelAttr() map[string]attr.Type { } } -func extractUpdateTCOPolicyTraces(ctx context.Context, plan TCOPolicyTracesResourceModel) *tcopolicies.UpdatePolicyRequest { +func extractUpdateTCOPolicyTraces(ctx context.Context, plan TCOPolicyTracesResourceModel) (*tcopolicies.UpdatePolicyRequest, diag.Diagnostics) { id := typeStringToWrapperspbString(plan.ID) name := typeStringToWrapperspbString(plan.Name) description := typeStringToWrapperspbString(plan.Description) priority := tcoPoliciesPrioritySchemaToProto[plan.Priority.ValueString()] - applicationRule := expandTCOPolicyRule(ctx, plan.Applications) - subsystemRule := expandTCOPolicyRule(ctx, plan.Subsystems) + applicationRule, diags := expandTCOPolicyRule(ctx, plan.Applications) + if diags.HasError() { + return nil, diags + } + subsystemRule, diags := expandTCOPolicyRule(ctx, plan.Subsystems) + if diags.HasError() { + return nil, diags + } archiveRetention := expandActiveRetention(plan.ArchiveRetentionID) - - updateRequest := &tcopolicies.UpdatePolicyRequest{ + sourceTypeRules, diags := expandTracesSourceTypeUpdate(ctx, plan) + if diags.HasError() { + return nil, diags + } + return &tcopolicies.UpdatePolicyRequest{ Id: id, Name: name, Description: description, @@ -491,37 +534,51 @@ func extractUpdateTCOPolicyTraces(ctx context.Context, plan TCOPolicyTracesResou ApplicationRule: applicationRule, SubsystemRule: subsystemRule, ArchiveRetention: archiveRetention, - SourceTypeRules: expandTracesSourceTypeUpdate(ctx, plan), - } - - return updateRequest + SourceTypeRules: sourceTypeRules, + }, nil } -func extractCreateTcoPolicyTraces(ctx context.Context, plan TCOPolicyTracesResourceModel) *tcopolicies.CreatePolicyRequest { +func extractCreateTcoPolicyTraces(ctx context.Context, plan TCOPolicyTracesResourceModel) (*tcopolicies.CreatePolicyRequest, diag.Diagnostics) { name := typeStringToWrapperspbString(plan.Name) description := typeStringToWrapperspbString(plan.Description) priority := tcoPoliciesPrioritySchemaToProto[plan.Priority.ValueString()] - applicationRule := expandTCOPolicyRule(ctx, plan.Applications) - subsystemRule := expandTCOPolicyRule(ctx, plan.Subsystems) + applicationRule, diags := expandTCOPolicyRule(ctx, plan.Applications) + if diags.HasError() { + return nil, diags + } + subsystemRule, diags := expandTCOPolicyRule(ctx, plan.Subsystems) + if diags.HasError() { + return nil, diags + } archiveRetention := expandActiveRetention(plan.ArchiveRetentionID) - - createRequest := &tcopolicies.CreatePolicyRequest{ + sourceTypeRules, diags := expandTracesSourceType(ctx, plan) + if diags.HasError() { + return nil, diags + } + return &tcopolicies.CreatePolicyRequest{ Name: name, Description: description, Priority: priority, ApplicationRule: applicationRule, SubsystemRule: subsystemRule, ArchiveRetention: archiveRetention, - SourceTypeRules: expandTracesSourceType(ctx, plan), - } - - return createRequest + SourceTypeRules: sourceTypeRules, + }, nil } -func expandTracesSourceType(ctx context.Context, plan TCOPolicyTracesResourceModel) *tcopolicies.CreatePolicyRequest_SpanRules { - serviceRule := expandTCOPolicyRule(ctx, plan.Services) - actionRule := expandTCOPolicyRule(ctx, plan.Actions) - tagRules := expandTagsRules(ctx, plan.Tags) +func expandTracesSourceType(ctx context.Context, plan TCOPolicyTracesResourceModel) (*tcopolicies.CreatePolicyRequest_SpanRules, diag.Diagnostics) { + serviceRule, diags := expandTCOPolicyRule(ctx, plan.Services) + if diags.HasError() { + return nil, diags + } + actionRule, diags := expandTCOPolicyRule(ctx, plan.Actions) + if diags.HasError() { + return nil, diags + } + tagRules, diags := expandTagsRules(ctx, plan.Tags) + if diags.HasError() { + return nil, diags + } return &tcopolicies.CreatePolicyRequest_SpanRules{ SpanRules: &tcopolicies.SpanRules{ @@ -529,44 +586,63 @@ func expandTracesSourceType(ctx context.Context, plan TCOPolicyTracesResourceMod ActionRule: actionRule, TagRules: tagRules, }, - } + }, nil } -func expandTracesSourceTypeUpdate(ctx context.Context, plan TCOPolicyTracesResourceModel) *tcopolicies.UpdatePolicyRequest_SpanRules { - serviceRule := expandTCOPolicyRule(ctx, plan.Services) - actionRule := expandTCOPolicyRule(ctx, plan.Actions) - tagRules := expandTagsRules(ctx, plan.Tags) - +func expandTracesSourceTypeUpdate(ctx context.Context, plan TCOPolicyTracesResourceModel) (*tcopolicies.UpdatePolicyRequest_SpanRules, diag.Diagnostics) { + serviceRule, diags := expandTCOPolicyRule(ctx, plan.Services) + if diags.HasError() { + return nil, diags + } + actionRule, diags := expandTCOPolicyRule(ctx, plan.Actions) + if diags.HasError() { + return nil, diags + } + tagRules, diags := expandTagsRules(ctx, plan.Tags) + if diags.HasError() { + return nil, diags + } return &tcopolicies.UpdatePolicyRequest_SpanRules{ SpanRules: &tcopolicies.SpanRules{ ServiceRule: serviceRule, ActionRule: actionRule, TagRules: tagRules, }, - } + }, nil } -func expandTagsRules(ctx context.Context, tags types.Map) []*tcopolicies.TagRule { - var tagsMap map[string]TCORuleModel +func expandTagsRules(ctx context.Context, tags types.Map) ([]*tcopolicies.TagRule, diag.Diagnostics) { + var tagsMap map[string]types.Object d := tags.ElementsAs(ctx, &tagsMap, true) if d != nil { panic(d) } + var diags diag.Diagnostics result := make([]*tcopolicies.TagRule, 0, len(tagsMap)) for tagName, tagElement := range tagsMap { - tagRule := expandTagRule(ctx, tagName, &tagElement) + tagRule, digs := expandTagRule(ctx, tagName, tagElement) + if digs.HasError() { + diags.Append(digs...) + continue + } result = append(result, tagRule) } - return result + if diags.HasError() { + return nil, diags + } + return result, nil } -func expandTagRule(ctx context.Context, name string, tag *TCORuleModel) *tcopolicies.TagRule { - rule := expandTCOPolicyRule(ctx, tag) +func expandTagRule(ctx context.Context, name string, tag types.Object) (*tcopolicies.TagRule, diag.Diagnostics) { + rule, diags := expandTCOPolicyRule(ctx, tag) + if diags.HasError() { + return nil, diags + } return &tcopolicies.TagRule{ TagName: wrapperspb.String(name), RuleTypeId: rule.GetRuleTypeId(), TagValue: rule.GetName(), - } + }, nil }