134 lines
3.6 KiB
Go
134 lines
3.6 KiB
Go
package hcl2template
|
|
|
|
import (
|
|
"github.com/hashicorp/hcl/v2"
|
|
"github.com/hashicorp/hcl/v2/gohcl"
|
|
"github.com/hashicorp/hcl/v2/hclsyntax"
|
|
)
|
|
|
|
const (
|
|
buildFromLabel = "from"
|
|
|
|
buildSourceLabel = "source"
|
|
|
|
buildProvisionerLabel = "provisioner"
|
|
|
|
buildPostProcessorLabel = "post-processor"
|
|
)
|
|
|
|
var buildSchema = &hcl.BodySchema{
|
|
Blocks: []hcl.BlockHeaderSchema{
|
|
{Type: buildFromLabel, LabelNames: []string{"type"}},
|
|
{Type: sourceLabel, LabelNames: []string{"reference"}},
|
|
{Type: buildProvisionerLabel, LabelNames: []string{"type"}},
|
|
{Type: buildPostProcessorLabel, LabelNames: []string{"type"}},
|
|
},
|
|
}
|
|
|
|
// BuildBlock references an HCL 'build' block and it content, for example :
|
|
//
|
|
// build {
|
|
// sources = [
|
|
// ...
|
|
// ]
|
|
// provisioner "" { ... }
|
|
// post-processor "" { ... }
|
|
// }
|
|
type BuildBlock struct {
|
|
// Name is a string representing the named build to show in the logs
|
|
Name string
|
|
|
|
// A description of what this build does, it could be used in a inspect
|
|
// call for example.
|
|
Description string
|
|
|
|
// Sources is the list of sources that we want to start in this build block.
|
|
Sources []SourceRef
|
|
|
|
// ProvisionerBlocks references a list of HCL provisioner block that will
|
|
// will be ran against the sources.
|
|
ProvisionerBlocks []*ProvisionerBlock
|
|
|
|
// ProvisionerBlocks references a list of HCL post-processors block that
|
|
// will be ran against the artifacts from the provisioning steps.
|
|
PostProcessors []*PostProcessorBlock
|
|
|
|
HCL2Ref HCL2Ref
|
|
}
|
|
|
|
type Builds []*BuildBlock
|
|
|
|
// decodeBuildConfig is called when a 'build' block has been detected. It will
|
|
// load the references to the contents of the build block.
|
|
func (p *Parser) decodeBuildConfig(block *hcl.Block) (*BuildBlock, hcl.Diagnostics) {
|
|
build := &BuildBlock{}
|
|
|
|
var b struct {
|
|
Name string `hcl:"name,optional"`
|
|
Description string `hcl:"description,optional"`
|
|
FromSources []string `hcl:"sources,optional"`
|
|
Config hcl.Body `hcl:",remain"`
|
|
}
|
|
diags := gohcl.DecodeBody(block.Body, nil, &b)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
|
|
build.Name = b.Name
|
|
build.Description = b.Description
|
|
|
|
for _, buildFrom := range b.FromSources {
|
|
ref := sourceRefFromString(buildFrom)
|
|
|
|
if ref == NoSource ||
|
|
!hclsyntax.ValidIdentifier(ref.Type) ||
|
|
!hclsyntax.ValidIdentifier(ref.Name) {
|
|
diags = append(diags, &hcl.Diagnostic{
|
|
Severity: hcl.DiagError,
|
|
Summary: "Invalid " + sourceLabel + " reference",
|
|
Detail: "A " + sourceLabel + " type is made of three parts that are" +
|
|
"split by a dot `.`; each part must start with a letter and " +
|
|
"may contain only letters, digits, underscores, and dashes." +
|
|
"A valid source reference looks like: `source.type.name`",
|
|
Subject: block.DefRange.Ptr(),
|
|
})
|
|
continue
|
|
}
|
|
|
|
build.Sources = append(build.Sources, ref)
|
|
}
|
|
|
|
content, moreDiags := b.Config.Content(buildSchema)
|
|
diags = append(diags, moreDiags...)
|
|
if diags.HasErrors() {
|
|
return nil, diags
|
|
}
|
|
for _, block := range content.Blocks {
|
|
switch block.Type {
|
|
case sourceLabel:
|
|
ref, moreDiags := p.decodeBuildSource(block)
|
|
diags = append(diags, moreDiags...)
|
|
if moreDiags.HasErrors() {
|
|
continue
|
|
}
|
|
build.Sources = append(build.Sources, ref)
|
|
case buildProvisionerLabel:
|
|
p, moreDiags := p.decodeProvisioner(block)
|
|
diags = append(diags, moreDiags...)
|
|
if moreDiags.HasErrors() {
|
|
continue
|
|
}
|
|
build.ProvisionerBlocks = append(build.ProvisionerBlocks, p)
|
|
case buildPostProcessorLabel:
|
|
pp, moreDiags := p.decodePostProcessor(block)
|
|
diags = append(diags, moreDiags...)
|
|
if moreDiags.HasErrors() {
|
|
continue
|
|
}
|
|
build.PostProcessors = append(build.PostProcessors, pp)
|
|
}
|
|
}
|
|
|
|
return build, diags
|
|
}
|