Skip to content

Investigate a proper way to declare mutually exclusive config fields #25945

Description

@pront

The remap transform has three mutually exclusive source fields:

transforms:
  my_remap:
    type: remap
    # Exactly one of the following must be provided:
    source: |
      .foo = "bar"
    file: path/to/program_1.vrl
    files:
      - path/to/program_1.vrl
      - path/to/program_2.vrl

The sample transform has the same issue with rate and ratio.

These fields are mutually exclusive — exactly one may be present in a valid config — but nothing in the config schema or generated docs expressed that constraint. Fields showed up as optional individually, and auto-generated example configs had to rely on docs::examples/docs::required heuristics to surface one representative.


Implemented in #25948 via a new #[configurable(required_one_of = "group")] field attribute.

Annotating a set of fields with the same group name wires up three layers automatically:

  1. JSON Schema — the macro generates a oneOf constraint in the parent struct's allOf expressing that exactly one field from the group must be present.
  2. Component docs — the CUE doc builder propagates the group metadata and auto-generates the description note ("Exactly one of rate or ratio must be set.") on each field. No hand-written prose needed.
  3. Website badge — fields render an orange required (one of: <group>) badge instead of the generic "optional" badge.

Example usage in sample:

#[configurable(required_one_of = "sampling_strategy")]
pub rate: Option<u64>,

#[configurable(required_one_of = "sampling_strategy", metadata(docs::examples = 0.13))]
pub ratio: Option<f64>,

No config format changes. No deprecations. No new user-facing fields.

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain: configAnything related to configuring Vector

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions