Files
Packer-Cn/hcl2template/types.datasource.go
T
hashicorp-copywrite[bot] 19055df3ec [COMPLIANCE] License changes (#12568)
* Updating the license from MPL to Business Source License

Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at https://hashi.co/bsl-blog, FAQ at https://hashi.co/license-faq, and details of the license at www.hashicorp.com/bsl.

* Update copyright file headers to BUSL-1.1

---------

Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2023-08-10 15:53:29 -07:00

161 lines
4.2 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hcl2template
import (
"fmt"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
)
// DatasourceBlock references an HCL 'data' block.
type DatasourceBlock struct {
Type string
Name string
value cty.Value
block *hcl.Block
}
type DatasourceRef struct {
Type string
Name string
}
type Datasources map[DatasourceRef]DatasourceBlock
func (data *DatasourceBlock) Ref() DatasourceRef {
return DatasourceRef{
Type: data.Type,
Name: data.Name,
}
}
func (ds *Datasources) Values() (map[string]cty.Value, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := map[string]cty.Value{}
valuesMap := map[string]map[string]cty.Value{}
for ref, datasource := range *ds {
if datasource.value == (cty.Value{}) {
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("empty value"),
Subject: &datasource.block.DefRange,
Severity: hcl.DiagError,
})
continue
}
inner := valuesMap[ref.Type]
if inner == nil {
inner = map[string]cty.Value{}
}
inner[ref.Name] = datasource.value
res[ref.Type] = cty.MapVal(inner)
// Keeps values of different datasources from same type
valuesMap[ref.Type] = inner
}
return res, diags
}
func (cfg *PackerConfig) startDatasource(dataSourceStore packer.DatasourceStore, ref DatasourceRef, secondaryEvaluation bool) (packersdk.Datasource, hcl.Diagnostics) {
var diags hcl.Diagnostics
block := cfg.Datasources[ref].block
if dataSourceStore == nil {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + dataSourceLabel + " type " + ref.Type,
Subject: block.LabelRanges[0].Ptr(),
Detail: fmt.Sprintf("packer does not currently know any data source."),
Severity: hcl.DiagError,
})
return nil, diags
}
if !dataSourceStore.Has(ref.Type) {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + dataSourceLabel + " type " + ref.Type,
Subject: block.LabelRanges[0].Ptr(),
Detail: fmt.Sprintf("known data sources: %v", dataSourceStore.List()),
Severity: hcl.DiagError,
})
return nil, diags
}
datasource, err := dataSourceStore.Start(ref.Type)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: err.Error(),
Subject: &block.DefRange,
Severity: hcl.DiagError,
})
}
if datasource == nil {
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("failed to start datasource plugin %q.%q", ref.Type, ref.Name),
Subject: &block.DefRange,
Severity: hcl.DiagError,
})
}
var decoded cty.Value
var moreDiags hcl.Diagnostics
body := block.Body
decoded, moreDiags = decodeHCL2Spec(body, cfg.EvalContext(DatasourceContext, nil), datasource)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
return nil, diags
}
// In case of cty.Unknown values, this will write a equivalent placeholder
// of the same type. Unknown types are not recognized by the json marshal
// during the RPC call and we have to do this here to avoid json parsing
// failures when running the validate command. We don't do this before so
// we can validate if variable type matches correctly on decodeHCL2Spec.
decoded = hcl2shim.WriteUnknownPlaceholderValues(decoded)
if err := datasource.Configure(decoded); err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: err.Error(),
Subject: &block.DefRange,
Severity: hcl.DiagError,
})
}
return datasource, diags
}
func (p *Parser) decodeDataBlock(block *hcl.Block) (*DatasourceBlock, hcl.Diagnostics) {
var diags hcl.Diagnostics
r := &DatasourceBlock{
Type: block.Labels[0],
Name: block.Labels[1],
block: block,
}
if !hclsyntax.ValidIdentifier(r.Type) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid data source name",
Detail: badIdentifierDetail,
Subject: &block.LabelRanges[0],
})
}
if !hclsyntax.ValidIdentifier(r.Name) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid data resource name",
Detail: badIdentifierDetail,
Subject: &block.LabelRanges[1],
})
}
return r, diags
}