Skip to content

feat: a datasource filters on the fields of the objects it lists - #105

Merged
ShocOne merged 1 commit into
mainfrom
feat/datasource-field-filters
Aug 15, 2026
Merged

feat: a datasource filters on the fields of the objects it lists#105
ShocOne merged 1 commit into
mainfrom
feat/datasource-field-filters

Conversation

@ShocOne

@ShocOne ShocOne commented Aug 15, 2026

Copy link
Copy Markdown
Member

Stacked on #103. Based on docs/entity-operation-sets so the doc
changes stay coherent — #103 describes the datasource shape, and this
changes that shape. Review after #103; the base retargets to main on merge.

What was wrong

A companion datasource declared filter_type and filter_value, and the
OneOf validator allowed exactly two values: all and id. Only id did
anything — it fetched one object through the item GET. Every other case
returned the collection whole, and filter_value narrowed nothing at all.

So a caller who wanted one object had to know its position in the list and
index to it — items[2] — which no API promises to keep stable. The filter
was the part that was never built.

What changes

Every scalar field at the root of a listed object becomes an optional argument
of that field's own type, and items carries the objects that matched every
argument the configuration set.

data "example_computer" "mine" {
  name    = "abcd"
  managed = true
}
  • Which fields. Strings, numbers and booleans at the root of the item.
    Nested objects and collections are not offered: HCL would have to describe a
    whole object to match one leaf of it, and a collection has no single value to
    compare. They are read off the items the filters selected.
  • Typed, not stringly. Because each filter is its own attribute it carries
    the field's own type, so managed = true, not "true". The generated match
    compares terraform values with .Equal, which needs no conversion and cannot
    disagree with the item model.
  • Exact and case-sensitive. A filter the configuration leaves out narrows
    nothing, which is what lets several combine and none be mandatory.
  • id still short-circuits. Where the API has a by-id read, setting id
    calls it rather than listing a collection to discard all but one of it.
  • No wire side. A filter binds to no SDK field — the match runs over the
    objects the list already answered with — so sdkbind leaves them alone, as
    it already did for filter_type.

Carried on the intermediate representation as Attribute.Filter, which is what
tells addressing attributes and filters apart at the root of a companion; that
distinction used to be a hardcoded name check.

Generated output

func matches(config *HTTPServerDatasourceModel, item *HTTPServerItemModel) bool {
	if !config.ID.IsNull() && !config.ID.Equal(item.ID) {
		return false
	}
	if !config.Name.IsNull() && !config.Name.Equal(item.Name) {
		return false
	}
	if !config.Enabled.IsNull() && !config.Enabled.Equal(item.Enabled) {
		return false
	}
	return true
}

Two imports stop being emitted for datasources — stringvalidator and
validator were there only for filter_type's hardcoded OneOf, and fmt
only for the filter_value error. The schema builder still adds them where a
filter actually needs one.

Verification

make check passes: fmt, build, vet, coverage gate at 91.3% total, hygiene.
The generated-tree tests are the load-bearing ones here — RenderServices_TheRenderedTreeCompiles
builds the emitted provider for both backends, and CuratedTreeCompiles does
the same for the curated tree, so the new matches function and the reshaped
model are compiled, not just string-matched. Added a test asserting each root
scalar is offered at its own type, that the model carries a field for it, that
the match consults every filter, and that id reaches the by-id read.

Test fixtures in internal/emit and internal/sdkbind that hand-built the old
filter_type/filter_value root were updated to the new shape.

🤖 Generated with Claude Code

A companion datasource declared filter_type and filter_value, and only
ever acted on one value of them: filter_type "id" fetched one object, and
everything else returned the collection whole. filter_value narrowed
nothing. A caller who wanted one object had to know its position in the
list and index to it, which no API promises to keep stable.

Every scalar field at the root of a listed object is now an optional
argument of that field's own type, and items carries the objects that
matched every argument the configuration set. Nested fields and
collections are not offered: HCL would have to describe a whole object to
match one leaf of it, and a collection has no single value to compare.

Matching is exact and runs over the objects the list already answered
with, so a filter carries no wire value and binds to no SDK field.
Setting id is still answered by the by-id read where the API has one,
rather than listing a collection to discard all but one of it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Base automatically changed from docs/entity-operation-sets to main August 15, 2026 13:12
@ShocOne
ShocOne merged commit 371d50a into main Aug 15, 2026
2 checks passed
@ShocOne
ShocOne deleted the feat/datasource-field-filters branch August 15, 2026 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant