-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move pf write and add resource writing
- Loading branch information
1 parent
0a8ebb4
commit de1e97c
Showing
3 changed files
with
170 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
package crosstests | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"sort" | ||
|
||
"github.com/hashicorp/hcl/v2/hclwrite" | ||
pschema "github.com/hashicorp/terraform-plugin-framework/provider/schema" | ||
rschema "github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" | ||
"github.com/zclconf/go-cty/cty" | ||
) | ||
|
||
type PFWriter struct{ out io.Writer } | ||
|
||
func WritePF(out io.Writer) PFWriter { return PFWriter{out} } | ||
|
||
func (w PFWriter) Provider(sch pschema.Schema, providerName string, config map[string]cty.Value) error { | ||
if !cty.ObjectVal(config).IsWhollyKnown() { | ||
return fmt.Errorf("WriteHCL cannot yet write unknowns") | ||
} | ||
f := hclwrite.NewEmptyFile() | ||
block := f.Body().AppendNewBlock("provider", []string{providerName}) | ||
writePfProvider(block.Body(), sch, config) | ||
_, err := f.WriteTo(w.out) | ||
return err | ||
} | ||
|
||
func (w PFWriter) Resource(sch rschema.Schema, resourceType, resourceName string, config map[string]cty.Value) error { | ||
if !cty.ObjectVal(config).IsWhollyKnown() { | ||
return fmt.Errorf("WriteHCL cannot yet write unknowns") | ||
} | ||
f := hclwrite.NewEmptyFile() | ||
block := f.Body().AppendNewBlock("resource", []string{resourceType, resourceName}) | ||
writePfResource(block.Body(), sch, config) | ||
_, err := f.WriteTo(w.out) | ||
return err | ||
} | ||
|
||
func writePfProvider(body *hclwrite.Body, schemas pschema.Schema, values map[string]cty.Value) { | ||
writePfObjectProvider(body, pschema.NestedBlockObject{ | ||
Attributes: schemas.Attributes, | ||
Blocks: schemas.Blocks, | ||
}, values) | ||
} | ||
|
||
func writePfResource(body *hclwrite.Body, schemas rschema.Schema, values map[string]cty.Value) { | ||
writePfObjectResource(body, rschema.NestedBlockObject{ | ||
Attributes: schemas.Attributes, | ||
Blocks: schemas.Blocks, | ||
}, values) | ||
} | ||
|
||
// writePfBlockProvider writes the values for a single schema block to parentBody. | ||
// | ||
// Because blocks can be repeated (ListNestedBlock and SetNestedBlock), writePfBlockProvider | ||
// can write an arbitrary number of blocks. | ||
// | ||
// For example, writing a list would add two blocks to parentBody: | ||
// | ||
// writePfBlockProvider("key", parentBody, ListNestedBlock{count: int}, cty.Value([{count: 1}, {count: 2}])) | ||
// | ||
// key { | ||
// count = 1 | ||
// } | ||
// key { | ||
// count = 2 | ||
// } | ||
// | ||
// This is why writePfBlockProvider is called with parentBody, instead of with the block body | ||
// already created (as with [writeBlock]). | ||
func writePfBlockProvider(key string, parentBody *hclwrite.Body, schemas pschema.Block, value cty.Value) { | ||
switch schemas := schemas.(type) { | ||
case pschema.ListNestedBlock: | ||
for _, v := range value.AsValueSlice() { | ||
b := parentBody.AppendNewBlock(key, nil).Body() | ||
writePfObjectProvider(b, schemas.NestedObject, v.AsValueMap()) | ||
} | ||
case pschema.SetNestedBlock: | ||
values := value.AsValueSet().Values() | ||
for _, v := range values { | ||
b := parentBody.AppendNewBlock(key, nil).Body() | ||
writePfObjectProvider(b, schemas.NestedObject, v.AsValueMap()) | ||
} | ||
case pschema.SingleNestedBlock: | ||
body := parentBody.AppendNewBlock(key, nil).Body() | ||
|
||
if value.IsNull() { | ||
return | ||
} | ||
|
||
writePfObjectProvider(body, pschema.NestedBlockObject{ | ||
Attributes: schemas.Attributes, | ||
Blocks: schemas.Blocks, | ||
}, value.AsValueMap()) | ||
default: | ||
contract.Failf("Unknown block type: %T", schemas) | ||
} | ||
} | ||
|
||
func writePfBlockResource(key string, parentBody *hclwrite.Body, schemas rschema.Block, value cty.Value) { | ||
switch schemas := schemas.(type) { | ||
case rschema.ListNestedBlock: | ||
for _, v := range value.AsValueSlice() { | ||
b := parentBody.AppendNewBlock(key, nil).Body() | ||
writePfObjectResource(b, schemas.NestedObject, v.AsValueMap()) | ||
} | ||
case rschema.SetNestedBlock: | ||
values := value.AsValueSet().Values() | ||
for _, v := range values { | ||
b := parentBody.AppendNewBlock(key, nil).Body() | ||
writePfObjectResource(b, schemas.NestedObject, v.AsValueMap()) | ||
} | ||
case rschema.SingleNestedBlock: | ||
body := parentBody.AppendNewBlock(key, nil).Body() | ||
|
||
if value.IsNull() { | ||
return | ||
} | ||
|
||
writePfObjectResource(body, rschema.NestedBlockObject{ | ||
Attributes: schemas.Attributes, | ||
Blocks: schemas.Blocks, | ||
}, value.AsValueMap()) | ||
default: | ||
contract.Failf("Unknown block type: %T", schemas) | ||
} | ||
} | ||
|
||
func writePfObjectProvider(body *hclwrite.Body, schemas pschema.NestedBlockObject, values map[string]cty.Value) { | ||
keys := make([]string, 0, len(values)) | ||
for k := range values { | ||
keys = append(keys, k) | ||
} | ||
sort.Strings(keys) | ||
|
||
for _, key := range keys { | ||
if _, ok := schemas.Attributes[key]; ok { | ||
body.SetAttributeValue(key, values[key]) | ||
continue | ||
} | ||
if block, ok := schemas.Blocks[key]; ok { | ||
writePfBlockProvider(key, body, block, values[key]) | ||
continue | ||
} | ||
contract.Failf("Could not find a attr or block for value key %q", key) | ||
} | ||
} | ||
|
||
func writePfObjectResource(body *hclwrite.Body, schemas rschema.NestedBlockObject, values map[string]cty.Value) { | ||
keys := make([]string, 0, len(values)) | ||
for k := range values { | ||
keys = append(keys, k) | ||
} | ||
sort.Strings(keys) | ||
|
||
for _, key := range keys { | ||
if _, ok := schemas.Attributes[key]; ok { | ||
body.SetAttributeValue(key, values[key]) | ||
continue | ||
} | ||
if block, ok := schemas.Blocks[key]; ok { | ||
writePfBlockResource(key, body, block, values[key]) | ||
continue | ||
} | ||
contract.Failf("Could not find a attr or block for value key %q", key) | ||
} | ||
} |