github.com/hashicorp/packer@v1.14.3/hcl2template/version.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package hcl2template
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/hashicorp/go-version"
    10  	"github.com/hashicorp/hcl/v2"
    11  	"github.com/zclconf/go-cty/cty"
    12  	"github.com/zclconf/go-cty/cty/convert"
    13  )
    14  
    15  // VersionConstraint represents a version constraint on some resource that
    16  // carries with it a source range so that a helpful diagnostic can be printed
    17  // in the event that a particular constraint does not match.
    18  type VersionConstraint struct {
    19  	Required  version.Constraints
    20  	DeclRange hcl.Range
    21  }
    22  
    23  func decodeVersionConstraint(attr *hcl.Attribute) (VersionConstraint, hcl.Diagnostics) {
    24  	ret := VersionConstraint{
    25  		DeclRange: attr.Range,
    26  	}
    27  
    28  	val, diags := attr.Expr.Value(nil)
    29  	if diags.HasErrors() {
    30  		return ret, diags
    31  	}
    32  	var err error
    33  	val, err = convert.Convert(val, cty.String)
    34  	if err != nil {
    35  		diags = append(diags, &hcl.Diagnostic{
    36  			Severity: hcl.DiagError,
    37  			Summary:  "Invalid version constraint",
    38  			Detail:   fmt.Sprintf("A string value is required for %s.", attr.Name),
    39  			Subject:  attr.Expr.Range().Ptr(),
    40  		})
    41  		return ret, diags
    42  	}
    43  
    44  	if val.IsNull() {
    45  		// A null version constraint is strange, but we'll just treat it
    46  		// like an empty constraint set.
    47  		return ret, diags
    48  	}
    49  
    50  	if !val.IsWhollyKnown() {
    51  		// If there is a syntax error, HCL sets the value of the given attribute
    52  		// to cty.DynamicVal. A diagnostic for the syntax error will already
    53  		// bubble up, so we will move forward gracefully here.
    54  		return ret, diags
    55  	}
    56  
    57  	constraintStr := val.AsString()
    58  	constraints, err := version.NewConstraint(constraintStr)
    59  	if err != nil {
    60  		// NewConstraint doesn't return user-friendly errors, so we'll just
    61  		// ignore the provided error and produce our own generic one.
    62  		diags = append(diags, &hcl.Diagnostic{
    63  			Severity: hcl.DiagError,
    64  			Summary:  "Invalid version constraint",
    65  			Detail:   "This string does not use correct version constraint syntax. Check out the docs: https://packer.io/docs/templates/hcl_templates/blocks/packer#version-constraints",
    66  			Subject:  attr.Expr.Range().Ptr(),
    67  		})
    68  		return ret, diags
    69  	}
    70  
    71  	ret.Required = constraints
    72  	return ret, diags
    73  }