Skip to content

Conversation

@bendrucker
Copy link
Member

@bendrucker bendrucker commented Dec 20, 2025

Extends the generator to produce validation rules for map-type attributes (tags, labels, environment variables) using key/value constraints from Smithy models. Adds 124 new tag validation rules across 48 services.

Changes

  • Extends generator to support listmap(ListShape, KeyShape, ValueShape) syntax in mapping files
  • Shapes in eval context are now rich objects carrying all constraint info
  • Transform functions (uppercase, replace) operate on shape enum values
  • Adds map_rule.go.tmpl template for map validation rules
  • Cleans up dead code and adds safe type assertions

Implementation

AWS services define tags using two different patterns in their Smithy models.

Smithy map Type

Some services use a map type with explicit key and value targets:

TagMap (map)
  ├── key → TagKey (string with constraints)
  └── value → TagValue (string with constraints)

The generator traverses this automatically via traverseToMapConstraints(). No mapping file changes needed—just reference the shape name.

List of Structures

Most services use a list containing a structure with named members:

TagList (list)
  └── member → Tag (structure)
                 ├── Key → TagKey (string with constraints)
                 └── Value → TagValue (string with constraints)

This pattern cannot be inferred automatically because member names vary across services (key/Key/TagKey, value/Value/TagValue). To avoid hardcoding member name lookups, I introduced the listmap() function:

tags = listmap(TagList, TagKey, TagValue)

This explicitly specifies which shapes provide list-level, key, and value constraints. The generator resolves each shape to a rich object containing pattern, length, and enum constraints, then combines them into a single map validation rule.

Shape Objects in Eval Context

The generator now represents each Smithy shape as a cty object:

shapeType = cty.Object({
    "name":    cty.String,
    "type":    cty.String,
    "pattern": cty.String,
    "min":     cty.Number,
    "max":     cty.Number,
    "enum":    cty.List(cty.String),
})

This allows HCL expressions to directly reference shapes by name. Transform functions like uppercase() and replace() operate on the shape's enum values and return a new shape with transformed values:

compression_type = uppercase(CompressionTypeValue)
encryption_mode  = uppercase(replace(EncryptionModeValue, "-", "_"))

Regex Pattern Compatibility

Tag key patterns often include negative lookahead like (?!aws:) to prevent reserved prefixes. Since Go's regexp doesn't support lookahead, these patterns are stripped. The character class validation still applies.

Testing

  • Table-driven tests for shape traversal functions
  • Tests verify listmap() function combines constraints correctly
  • Generator tests confirm transforms operate on shape objects
  • Full build and test suite passes

References

Extend the generator to traverse Smithy model structure types (Tags → Tag →
TagKey/TagValue) to extract pattern and length constraints for map attributes.

- Add shape traversal functions to follow list/map/structure types
- Add generateMapRuleFile for map[string]string validation rules
- Add map_rule.go.tmpl template for generated map rules
- Handle PCRE negative lookaheads by stripping (Go regexp incompatible)
- Skip malformed Unicode patterns with error message

Generates 149 new tag validation rules plus additional map rules for
environment_variables, attributes, labels, etc.

Closes #1019
- Extract tagStructureMembers config with godoc explaining case variations
- Add getMemberCaseInsensitive for case-insensitive member lookup
- Add getTarget helper to simplify shape reference extraction
- Extract resolveKeyValuePair to deduplicate map/structure handling
- Reduce traverseToTagConstraints from 80 to 30 lines
@bendrucker bendrucker changed the title Generate validation rules for tag keys and values Generate validation rules for map attributes Dec 20, 2025
- Add shapes_test.go with tests for extractShapeName, getTarget, and traverseToMapConstraints
- Cover map, list, and structure shape types
- Test case variations (Key/Value vs key/value vs Name/Value)
- Test edge cases (non-string members, mixed members, list values)
- Rename traverseToTagConstraints to traverseToMapConstraints
Adds `listmap()` function to HCL mapping syntax for explicitly specifying
list, key, and value constraint shapes. This enables tag validation rules
for services where Smithy models use list-of-structure patterns.

Changes:
- Extends generator to support `listmap(ListShape, KeyShape, ValueShape)`
  syntax in mapping files
- Shapes in eval context are now rich objects carrying all constraint info
- Transform functions (`uppercase`, `replace`) operate on shape enum values
- Adds 124 new tag validation rules across 48 services

Closes #1019
- Add safe type assertions in validMapping, findRawShape, fetchNumber,
  fetchString to prevent panics on unexpected types
- Add nil check for schema in generateRuleFile
- Remove dead code: validListMapping, resolveStructureMembers,
  parseListMapExpr, makeListTransformFunction
- Remove tests for deleted functions
- Fix variable shadowing: rename shapeType to typeStr in makeShapeValue
- Update HCL Transform System documentation comments
- Remove unused hclsyntax import
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants