base_block.go (147 lines of code) (raw):

package golden import ( "context" "github.com/google/uuid" "github.com/hashicorp/go-multierror" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/zclconf/go-cty/cty" ) type BaseBlock struct { c Config hb *HclBlock name string id string blockAddress string forEach *ForEach hasExpanded bool readyForRead bool preConditions []PreCondition } func NewBaseBlock(c Config, hb *HclBlock) *BaseBlock { n := "" if hb != nil { n = hb.Labels[1] } bb := &BaseBlock{ c: c, hb: hb, blockAddress: blockAddress(hb), name: n, id: uuid.NewString(), } return bb } func (bb *BaseBlock) Id() string { if bb == nil { return "" } return bb.id } func (bb *BaseBlock) Name() string { if bb == nil { return "" } return bb.name } func (bb *BaseBlock) HclBlock() *HclBlock { if bb.hb == nil { return &HclBlock{ Block: new(hclsyntax.Block), } } return bb.hb } func (bb *BaseBlock) BaseValues() map[string]cty.Value { return map[string]cty.Value{ "id": cty.StringVal(bb.id), } } func (bb *BaseBlock) EvalContext() *hcl.EvalContext { var ctx *hcl.EvalContext if bb.c == nil { ctx = new(hcl.EvalContext) } else { ctx = bb.c.EvalContext() } if bb.forEach != nil { ctx = ctx.NewChild() ctx.Variables = map[string]cty.Value{ "each": cty.ObjectVal(map[string]cty.Value{ "key": cty.StringVal(CtyValueToString(bb.forEach.key)), "value": bb.forEach.value, }), } } return ctx } func (bb *BaseBlock) Address() string { if bb == nil { return "" } return bb.blockAddress } func (bb *BaseBlock) Context() context.Context { if bb == nil || bb.c == nil { return context.TODO() } return bb.c.Context() } func (bb *BaseBlock) PreConditionCheck(ctx *hcl.EvalContext) ([]PreCondition, error) { var failedChecks []PreCondition var err error for _, cond := range bb.preConditions { diag := gohcl.DecodeBody(cond.Body, ctx, &cond) if diag.HasErrors() { err = multierror.Append(err, diag.Errs()...) continue } if !cond.Condition { failedChecks = append(failedChecks, cond) } } return failedChecks, err } func (bb *BaseBlock) Config() Config { return bb.c } func (bb *BaseBlock) forEachDefined() bool { _, forEach := bb.HclBlock().Body.Attributes["for_each"] return forEach } func (bb *BaseBlock) getDownstreams() []Block { var blocks []Block children, _ := bb.c.GetChildren(bb.blockAddress) for _, c := range children { blocks = append(blocks, c.(Block)) } return blocks } func (bb *BaseBlock) setForEach(each *ForEach) { bb.forEach = each } func (bb *BaseBlock) getForEach() *ForEach { return bb.forEach } func (bb *BaseBlock) setMetaNestedBlock() { for _, nb := range bb.hb.Body.Blocks { if nb.Type == "precondition" { bb.preConditions = append(bb.preConditions, PreCondition{ Body: nb.Body, }) } } } func (bb *BaseBlock) markExpanded() { bb.hasExpanded = true } func (bb *BaseBlock) expandable() bool { return bb.forEachDefined() && !bb.hasExpanded } func (bb *BaseBlock) markReady() { bb.readyForRead = true } func (bb *BaseBlock) isReadyForRead() bool { return bb.readyForRead }