github.com/Yunsang-Jeong/terraforge@v0.0.0-20231003081416-fe4fad2c57e3/internal/configs/config.go (about)

     1  package configs
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"path/filepath"
     7  
     8  	"github.com/hashicorp/hcl/v2"
     9  	"github.com/hashicorp/hcl/v2/hclsyntax"
    10  	"github.com/hashicorp/hcl/v2/hclwrite"
    11  	"github.com/spf13/afero"
    12  	"github.com/zclconf/go-cty/cty"
    13  )
    14  
    15  type Config struct {
    16  	Metafile  *Metafile
    17  	Generates map[string][]*Generate
    18  	Ctx       *hcl.EvalContext
    19  }
    20  
    21  func (c *Config) GenerateTFConfig(workingDir string, fs afero.Afero) error {
    22  	for label0, generates := range c.Generates {
    23  		file := hclwrite.NewEmptyFile()
    24  		body := file.Body()
    25  
    26  		for index, generate := range generates {
    27  			if !generate.When {
    28  				continue
    29  			}
    30  
    31  			ctx := c.Ctx.NewChild()
    32  			ctx.Variables = map[string]cty.Value{}
    33  
    34  			if generate.ForEach != nil {
    35  				for key, value := range generate.ForEach {
    36  					ctx.Variables = map[string]cty.Value{
    37  						"each": cty.ObjectVal(map[string]cty.Value{
    38  							"key":   cty.StringVal(key),
    39  							"value": value,
    40  						}),
    41  					}
    42  
    43  					newBlock := body.AppendNewBlock(label0, generate.Labels[1:])
    44  					newBlockBody := newBlock.Body()
    45  
    46  					if err := appendBlockContent(newBlockBody, generate.Config, ctx); err != nil {
    47  						return err
    48  					}
    49  
    50  					if index < len(generate.Config.Blocks)-1 {
    51  						body.AppendNewline()
    52  					}
    53  				}
    54  			} else {
    55  				newBlock := body.AppendNewBlock(label0, generate.Labels[1:])
    56  				newBlockBody := newBlock.Body()
    57  
    58  				if err := appendBlockContent(newBlockBody, generate.Config, ctx); err != nil {
    59  					return err
    60  				}
    61  
    62  				if index < len(generate.Config.Blocks)-1 {
    63  					body.AppendNewline()
    64  				}
    65  			}
    66  		}
    67  
    68  		filename := filepath.Join(workingDir, fmt.Sprintf("%s.tf", label0))
    69  		if err := fs.WriteFile(filename, file.Bytes(), 0644); err != nil {
    70  			return err
    71  		}
    72  	}
    73  
    74  	return nil
    75  }
    76  
    77  func appendBlockContent(file *hclwrite.Body, config *hclsyntax.Body, ctx *hcl.EvalContext) error {
    78  	attributes := map[string]cty.Value{}
    79  	for name, attribute := range config.Attributes {
    80  		value, diags := attribute.Expr.Value(ctx)
    81  		if diags.HasErrors() {
    82  			return errors.Join(diags.Errs()...)
    83  		}
    84  
    85  		attributes[name] = value
    86  	}
    87  
    88  	for name, attribute := range attributes {
    89  		file.SetAttributeValue(name, attribute)
    90  	}
    91  
    92  	for _, block := range config.Blocks {
    93  		blockInBlock := file.AppendNewBlock(block.Type, []string{})
    94  		blockInBlockBody := blockInBlock.Body()
    95  
    96  		if err := appendBlockContent(blockInBlockBody, block.Body, ctx); err != nil {
    97  			return err
    98  		}
    99  	}
   100  
   101  	return nil
   102  }