Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update complex constraints to allow interpolation #216

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
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
21 changes: 15 additions & 6 deletions internal/schema/0.12/provisioners.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,11 @@ var LocalExecProvisioner = &schema.BodySchema{
},
"interpreter": {
IsOptional: true,
Constraint: schema.List{
Elem: schema.AnyExpression{OfType: cty.String},
Constraint: schema.OneOf{
schema.AnyExpression{OfType: cty.List(cty.String), SkipLiteralComplexTypes: true},
schema.List{
Elem: schema.AnyExpression{OfType: cty.String},
},
},
Description: lang.Markdown("If provided, this is a list of interpreter arguments used to execute " +
"the command. The first argument is the interpreter itself. It can be provided as a relative " +
Expand Down Expand Up @@ -117,8 +120,11 @@ var RemoteExecProvisioner = &schema.BodySchema{
Attributes: map[string]*schema.AttributeSchema{
"inline": {
IsOptional: true,
Constraint: schema.List{
Elem: schema.AnyExpression{OfType: cty.String},
Constraint: schema.OneOf{
schema.AnyExpression{OfType: cty.List(cty.String), SkipLiteralComplexTypes: true},
schema.List{
Elem: schema.AnyExpression{OfType: cty.String},
},
},
Description: lang.Markdown("A list of command strings. They are executed in the order they are provided." +
" This cannot be provided with `script` or `scripts`."),
Expand All @@ -131,8 +137,11 @@ var RemoteExecProvisioner = &schema.BodySchema{
},
"scripts": {
IsOptional: true,
Constraint: schema.List{
Elem: schema.AnyExpression{OfType: cty.String},
Constraint: schema.OneOf{
schema.AnyExpression{OfType: cty.List(cty.String), SkipLiteralComplexTypes: true},
schema.List{
Elem: schema.AnyExpression{OfType: cty.String},
},
},
Description: lang.Markdown("A list of paths (relative or absolute) to local scripts that will be copied " +
"to the remote resource and then executed. They are executed in the order they are provided." +
Expand Down
69 changes: 62 additions & 7 deletions schema/convert_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,27 +195,47 @@ func exprConstraintFromSchemaAttribute(attr *tfjson.SchemaAttribute) schema.Cons
return convertAttributeTypeToConstraint(attr.AttributeType)
}
if attr.AttributeNestedType != nil {
var attrType cty.Type
var cons schema.Constraint

objType := convertJsonAttributesToCtyObject(attr.AttributeNestedType.Attributes)
objectCons := convertJsonAttributesToObjectConstraint(attr.AttributeNestedType.Attributes)

switch attr.AttributeNestedType.NestingMode {
case tfjson.SchemaNestingModeSingle:
return convertJsonAttributesToObjectConstraint(attr.AttributeNestedType.Attributes)
attrType = objType
cons = objectCons
case tfjson.SchemaNestingModeList:
return schema.List{
Elem: convertJsonAttributesToObjectConstraint(attr.AttributeNestedType.Attributes),
attrType = cty.List(objType)
cons = schema.List{
Elem: objectCons,
MinItems: attr.AttributeNestedType.MinItems,
MaxItems: attr.AttributeNestedType.MaxItems,
}
case tfjson.SchemaNestingModeSet:
return schema.Set{
Elem: convertJsonAttributesToObjectConstraint(attr.AttributeNestedType.Attributes),
attrType = cty.Set(objType)
cons = schema.Set{
Elem: objectCons,
MinItems: attr.AttributeNestedType.MinItems,
MaxItems: attr.AttributeNestedType.MaxItems,
}
case tfjson.SchemaNestingModeMap:
return schema.Map{
Elem: convertJsonAttributesToObjectConstraint(attr.AttributeNestedType.Attributes),
attrType = cty.Map(objType)
cons = schema.Map{
Elem: objectCons,
MinItems: attr.AttributeNestedType.MinItems,
MaxItems: attr.AttributeNestedType.MaxItems,
}
default:
return nil
}

return schema.OneOf{
schema.AnyExpression{
OfType: attrType,
SkipLiteralComplexTypes: true,
},
cons,
}
}
return nil
Expand Down Expand Up @@ -300,6 +320,41 @@ func convertJsonAttributesToObjectConstraint(attrs map[string]*tfjson.SchemaAttr
}
}

func convertJsonAttributesToCtyObject(attrs map[string]*tfjson.SchemaAttribute) cty.Type {
optional := make([]string, 0)
attributes := make(map[string]cty.Type, 0)

for name, attr := range attrs {
attributes[name] = convertJsonAttributeToCtyType(attr)
if attr.Optional {
optional = append(optional, name)
}
}

return cty.ObjectWithOptionalAttrs(attributes, optional)
}

func convertJsonAttributeToCtyType(attr *tfjson.SchemaAttribute) cty.Type {
if attr.AttributeType != cty.NilType {
return attr.AttributeType
}
if attr.AttributeNestedType != nil {
objType := convertJsonAttributesToCtyObject(attr.AttributeNestedType.Attributes)

switch attr.AttributeNestedType.NestingMode {
case tfjson.SchemaNestingModeSingle:
return objType
case tfjson.SchemaNestingModeList:
return cty.List(objType)
case tfjson.SchemaNestingModeSet:
return cty.Set(objType)
case tfjson.SchemaNestingModeMap:
return cty.Map(objType)
}
}
return cty.NilType
}

func markupContent(value string, kind tfjson.SchemaDescriptionKind) lang.MarkupContent {
if value == "" {
return lang.MarkupContent{}
Expand Down