Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tioli: maybe this could fit nicely in processor_common.go since its pretty small, to keep all processor things together?

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package observability_pipeline

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)

// coreProcessorFields are the common processor attributes that are NOT processor types.
// Any other list attribute in the processor block is considered a processor type.
var coreProcessorFields = map[string]struct{}{
"id": {},
"enabled": {},
"include": {},
"display_name": {},
}

// ExactlyOneProcessorValidator validates that exactly one processor type block is specified
type ExactlyOneProcessorValidator struct{}

func (v ExactlyOneProcessorValidator) Description(ctx context.Context) string {
return "validates that exactly one processor type block is specified (e.g., filter, sample, quota)"
}

func (v ExactlyOneProcessorValidator) MarkdownDescription(ctx context.Context) string {
return v.Description(ctx)
}

func (v ExactlyOneProcessorValidator) ValidateObject(ctx context.Context, req validator.ObjectRequest, resp *validator.ObjectResponse) {
if req.ConfigValue.IsNull() || req.ConfigValue.IsUnknown() {
return
}

attrs := req.ConfigValue.Attributes()

var specifiedTypes []string
for attrName, attr := range attrs {
// Skip core processor fields
if _, isCoreField := coreProcessorFields[attrName]; isCoreField {
continue
}

if attr.IsNull() || attr.IsUnknown() {
continue
}

// Check if the list has any elements (processor type blocks are list nested blocks)
if list, ok := attr.(types.List); ok {
if len(list.Elements()) > 0 {
specifiedTypes = append(specifiedTypes, attrName)
}
}
}

if len(specifiedTypes) == 0 {
resp.Diagnostics.Append(diag.NewAttributeErrorDiagnostic(
req.Path,
"Missing Processor Type",
"A processor block must specify exactly one processor type (e.g., filter, sample, quota, parse_json, etc.).",
))
return
}

if len(specifiedTypes) > 1 {
resp.Diagnostics.Append(diag.NewAttributeErrorDiagnostic(
req.Path,
"Multiple Processor Types Specified",
fmt.Sprintf("A processor block must specify exactly one processor type, but found %d: %v. Each processor should only contain one type.", len(specifiedTypes), specifiedTypes),
))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,9 @@ func (r *observabilityPipelineResource) Schema(_ context.Context, _ resource.Sch
"processor": schema.ListNestedBlock{
Description: "The processor contained in this group.",
NestedObject: schema.NestedBlockObject{
Validators: []validator.Object{
observability_pipeline.ExactlyOneProcessorValidator{},
},
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Required: true,
Expand Down
Loading