156 lines
4 KiB
Go
156 lines
4 KiB
Go
package hcl
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/zclconf/go-cty/cty"
|
|
"github.com/zclconf/go-cty/cty/gocty"
|
|
|
|
"code.icb4dc0.de/buildr/buildr/modules"
|
|
)
|
|
|
|
type RepositoryOption func(evalCtx *hcl.EvalContext) error
|
|
|
|
func WithGlobalVariable(key string, value any) RepositoryOption {
|
|
return func(evalCtx *hcl.EvalContext) error {
|
|
ctyType, err := gocty.ImpliedType(value)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
mapped, err := gocty.ToCtyValue(value, ctyType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
evalCtx.Variables[key] = mapped
|
|
return nil
|
|
}
|
|
}
|
|
|
|
type ModulesSpec struct {
|
|
diagsWriter hcl.DiagnosticWriter
|
|
Locals []LocalsBlock `hcl:"locals,block"`
|
|
Tools GenericBlocks `hcl:"tool,block"`
|
|
Tasks GenericBlocks `hcl:"task,block"`
|
|
Builds GenericBlocks `hcl:"build,block"`
|
|
Packages GenericBlocks `hcl:"package,block"`
|
|
}
|
|
|
|
func (s ModulesSpec) Repository(
|
|
evalCtx *hcl.EvalContext,
|
|
diagsWriter hcl.DiagnosticWriter,
|
|
registry *modules.TypeRegistry,
|
|
outDir string,
|
|
opts ...RepositoryOption,
|
|
) (*modules.Repository, error) {
|
|
repo := new(modules.Repository)
|
|
s.diagsWriter = diagsWriter
|
|
|
|
for _, opt := range opts {
|
|
if err := opt(evalCtx); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if err := s.parseLocals(s.Locals, evalCtx); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
parsingSpecs := make([]blockParsingSpec, 0, len(s.Tools)+len(s.Tasks)+len(s.Builds))
|
|
|
|
if specs, err := s.buildParsingInventory(modules.CategoryTool, s.Tools, evalCtx, outDir); err != nil {
|
|
return nil, err
|
|
} else {
|
|
parsingSpecs = append(parsingSpecs, specs...)
|
|
}
|
|
|
|
if specs, err := s.buildParsingInventory(modules.CategoryTask, s.Tasks, evalCtx, outDir); err != nil {
|
|
return nil, err
|
|
} else {
|
|
parsingSpecs = append(parsingSpecs, specs...)
|
|
}
|
|
|
|
if specs, err := s.buildParsingInventory(modules.CategoryBuild, s.Builds, evalCtx, outDir); err != nil {
|
|
return nil, err
|
|
} else {
|
|
parsingSpecs = append(parsingSpecs, specs...)
|
|
}
|
|
|
|
if specs, err := s.buildParsingInventory(modules.CategoryPackage, s.Packages, evalCtx, outDir); err != nil {
|
|
return nil, err
|
|
} else {
|
|
parsingSpecs = append(parsingSpecs, specs...)
|
|
}
|
|
|
|
if parsedModules, err := s.parseBlocksToModules(parsingSpecs, registry, evalCtx, diagsWriter); err != nil {
|
|
return nil, err
|
|
} else {
|
|
repo.RegisterModules(parsedModules...)
|
|
}
|
|
|
|
return repo, nil
|
|
}
|
|
|
|
func (s ModulesSpec) buildParsingInventory(
|
|
modCategory modules.Category,
|
|
blocks []GenericBlock,
|
|
evalCtx *hcl.EvalContext,
|
|
outDir string,
|
|
) ([]blockParsingSpec, error) {
|
|
if len(blocks) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
groupNameByCategory := func(c modules.Category) string {
|
|
return fmt.Sprintf("%ss", strings.Replace(strings.ToLower(c.String()), "category", "", -1))
|
|
}
|
|
|
|
groupName := groupNameByCategory(modCategory)
|
|
|
|
blockGroupRepresentation := make(map[string]cty.Value, len(blocks))
|
|
blockGroupParsingSpecs := make([]blockParsingSpec, 0)
|
|
|
|
for i := range blocks {
|
|
result, err := s.prepareBlockForParsing(blocks[i], modCategory, evalCtx, outDir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
blockGroupRepresentation[blocks[i].BlockName] = result.ParsingRepresentation
|
|
blockGroupParsingSpecs = append(blockGroupParsingSpecs, result.Specs...)
|
|
}
|
|
|
|
evalCtx.Variables[groupName] = cty.ObjectVal(blockGroupRepresentation)
|
|
|
|
return blockGroupParsingSpecs, nil
|
|
}
|
|
|
|
func (s ModulesSpec) parseBlocksToModules(
|
|
specs []blockParsingSpec,
|
|
registry *modules.TypeRegistry,
|
|
evalCtx *hcl.EvalContext,
|
|
diagsWriter hcl.DiagnosticWriter,
|
|
) ([]modules.ModuleWithMeta, error) {
|
|
parsedModules := make([]modules.ModuleWithMeta, 0, len(specs))
|
|
|
|
for i := range specs {
|
|
spec := specs[i]
|
|
|
|
blockParseCtx := evalCtx
|
|
if len(spec.AdditionalParsingVariables) > 0 {
|
|
blockParseCtx = evalCtx.NewChild()
|
|
blockParseCtx.Variables = spec.AdditionalParsingVariables
|
|
}
|
|
|
|
if m, err := registry.CreateFromHCL(spec.Type, spec.Block.ModuleName, spec.Block.BlockBody, blockParseCtx, diagsWriter); err != nil {
|
|
return nil, err
|
|
} else {
|
|
parsedModules = append(parsedModules, m)
|
|
}
|
|
}
|
|
|
|
return parsedModules, nil
|
|
}
|