Skip to content

Commit

Permalink
feat: create targets for store blocks to allow references to dynamic …
Browse files Browse the repository at this point in the history
…values within
  • Loading branch information
ansgarm committed Aug 16, 2024
1 parent f939e3a commit f7e9793
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 0 deletions.
1 change: 1 addition & 0 deletions internal/schema/refscope/scopes.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ var (

ComponentScope = lang.ScopeId("component")
IdentityTokenScope = lang.ScopeId("identity_token")
StoreScope = lang.ScopeId("store")
)
5 changes: 5 additions & 0 deletions internal/schema/stacks/1.9/store_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func storeBlockSchema() *schema.BlockSchema {
Name: "name",
SemanticTokenModifiers: lang.SemanticTokenModifiers{tokmod.Name},
Description: lang.PlainText("Store name"),
IsDepKey: true,
},
},
DependentBody: map[schema.SchemaKey]*schema.BodySchema{
Expand Down Expand Up @@ -53,6 +54,10 @@ func storeBlockSchema() *schema.BlockSchema {
Description: lang.Markdown("The id of the varset. In the form of 'varset-nnnnnnnnnnnnnnnn'."),
},
},
AnyAttribute: &schema.AttributeSchema{
IsComputed: true,
Constraint: schema.AnyExpression{OfType: cty.DynamicPseudoType},
},
},
},
}
Expand Down
42 changes: 42 additions & 0 deletions schema/stacks/deploy_schema_merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,48 @@ func (m *DeploySchemaMerger) SchemaForDeployment(meta *stack.Meta) (*schema.Body
// TODO: isOptional should be set to true if at least one input is required
mergedSchema.Blocks["deployment"].Body.Attributes["inputs"].Constraint = constr

// We add specific Targetables with a dynamic type for each store as the AnyAttribute defined in the store schema
// is not picked up when reference targets are collected because we don't know all the available attributes that
// are eventually available in the varset and reference targets need a specific name to match against
// However, it is also possible to target the parent if its type is dynamic. This is why we add this target.
// We can't set the body to dynamic in the schema as that would remove the completions for the "id" attribute of the
// varset store block.
// If there's a better way to do this, we should consider it as this feels like a bit of a hack.
// TODO: once we parse tfvars files, do this differently for the tfvars type store block
for name, store := range meta.Stores {
key := schema.NewSchemaKey(schema.DependencyKeys{
Labels: []schema.LabelDependent{
{Index: 0, Value: store.Type},
{Index: 1, Value: name},
}})

// Copy the body of the store block for the specific store type to keep attributes and constraints
// as dependent bodies replace the original ones
newBody := mergedSchema.Blocks["store"].DependentBody[schema.NewSchemaKey(schema.DependencyKeys{
Labels: []schema.LabelDependent{
{Index: 0, Value: store.Type},
}})].Copy()

if newBody == nil {
newBody = mergedSchema.Blocks["store"].Body
}

newBody.TargetableAs = schema.Targetables{
&schema.Targetable{
Address: lang.Address{
lang.RootStep{Name: "store"},
lang.AttrStep{Name: store.Type},
lang.AttrStep{Name: name},
},
AsType: cty.DynamicPseudoType, // we need this type for the target for this store block as it matches every nested value
ScopeId: refscope.StoreScope,
FriendlyName: "store",
},
}

mergedSchema.Blocks["store"].DependentBody[key] = newBody
}

return mergedSchema, nil
}

Expand Down

0 comments on commit f7e9793

Please sign in to comment.