Merge pull request #25216 from hashicorp/alisdair/upgrade-deps
Upgrade hcl and go-cty
This commit is contained in:
commit
9303b9f8fc
4
go.mod
4
go.mod
|
@ -66,7 +66,7 @@ require (
|
|||
github.com/hashicorp/go-uuid v1.0.1
|
||||
github.com/hashicorp/go-version v1.2.0
|
||||
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f
|
||||
github.com/hashicorp/hcl/v2 v2.5.1
|
||||
github.com/hashicorp/hcl/v2 v2.6.0
|
||||
github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590
|
||||
github.com/hashicorp/memberlist v0.1.0 // indirect
|
||||
github.com/hashicorp/serf v0.0.0-20160124182025-e4ec8cc423bb // indirect
|
||||
|
@ -119,7 +119,7 @@ require (
|
|||
github.com/xanzy/ssh-agent v0.2.1
|
||||
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 // indirect
|
||||
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
|
||||
github.com/zclconf/go-cty v1.4.2
|
||||
github.com/zclconf/go-cty v1.5.0
|
||||
github.com/zclconf/go-cty-yaml v1.0.1
|
||||
go.uber.org/atomic v1.3.2 // indirect
|
||||
go.uber.org/multierr v1.1.0 // indirect
|
||||
|
|
10
go.sum
10
go.sum
|
@ -136,8 +136,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
|||
github.com/dimchansky/utfbom v1.0.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4=
|
||||
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||
github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31 h1:Dzuw9GtbmllUqEcoHfScT9YpKFUssSiZ5PgZkIGf/YQ=
|
||||
github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/dylanmei/iso8601 v0.1.0 h1:812NGQDBcqquTfH5Yeo7lwR0nzx/cKdsmf3qMjPURUI=
|
||||
github.com/dylanmei/iso8601 v0.1.0/go.mod h1:w9KhXSgIyROl1DefbMYIE7UVSIvELTbMrCfx+QkYnoQ=
|
||||
|
@ -283,8 +281,8 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
|||
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f h1:UdxlrJz4JOnY8W+DbLISwf2B8WXEolNRA8BGCwI9jws=
|
||||
github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hashicorp/hcl/v2 v2.0.0/go.mod h1:oVVDG71tEinNGYCxinCYadcmKU9bglqW9pV3txagJ90=
|
||||
github.com/hashicorp/hcl/v2 v2.5.1 h1:5ytFZykUu2/4U59ogd2f+XZdi9+6oC/Tv5WzsH6fIDA=
|
||||
github.com/hashicorp/hcl/v2 v2.5.1/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
|
||||
github.com/hashicorp/hcl/v2 v2.6.0 h1:3krZOfGY6SziUXa6H9PJU6TyohHn7I+ARYnhbeNBz+o=
|
||||
github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
|
||||
github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590 h1:2yzhWGdgQUWZUCNK+AoO35V+HTsgEmcM4J9IkArh7PI=
|
||||
github.com/hashicorp/hil v0.0.0-20190212112733-ab17b08d6590/go.mod h1:n2TSygSNwsLJ76m8qFXTSc7beTb+auJxYdqrnoqwZWE=
|
||||
github.com/hashicorp/memberlist v0.1.0 h1:qSsCiC0WYD39lbSitKNt40e30uorm2Ss/d4JGU1hzH8=
|
||||
|
@ -508,8 +506,8 @@ github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557/go.mod h1:ce1O1j6Ut
|
|||
github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
|
||||
github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
|
||||
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
|
||||
github.com/zclconf/go-cty v1.4.2 h1:GKcsRGjxZnRRlyVk2Y6PyG3fdcn3Pv0D7KT4xyYTLlE=
|
||||
github.com/zclconf/go-cty v1.4.2/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
|
||||
github.com/zclconf/go-cty v1.5.0 h1:U0USwJxGTnUd+dT565f92paYOlRtd201pI7+ZGW36XY=
|
||||
github.com/zclconf/go-cty v1.5.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
|
||||
github.com/zclconf/go-cty-yaml v1.0.1 h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8=
|
||||
github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
|
|
|
@ -1,5 +1,16 @@
|
|||
# HCL Changelog
|
||||
|
||||
## v2.6.0 (June 4, 2020)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* hcldec: Add a new `Spec`, `ValidateSpec`, which allows custom validation of values at decode-time. ([#387](https://github.com/hashicorp/hcl/pull/387))
|
||||
|
||||
### Bugs Fixed
|
||||
|
||||
* hclsyntax: Fix panic with combination of sequences and null arguments ([#386](https://github.com/hashicorp/hcl/pull/386))
|
||||
* hclsyntax: Fix handling of unknown values and sequences ([#386](https://github.com/hashicorp/hcl/pull/386))
|
||||
|
||||
## v2.5.1 (May 14, 2020)
|
||||
|
||||
### Bugs Fixed
|
||||
|
|
|
@ -22,14 +22,14 @@ const (
|
|||
)
|
||||
|
||||
// Diagnostic represents information to be presented to a user about an
|
||||
// error or anomoly in parsing or evaluating configuration.
|
||||
// error or anomaly in parsing or evaluating configuration.
|
||||
type Diagnostic struct {
|
||||
Severity DiagnosticSeverity
|
||||
|
||||
// Summary and Detail contain the English-language description of the
|
||||
// problem. Summary is a terse description of the general problem and
|
||||
// detail is a more elaborate, often-multi-sentence description of
|
||||
// the probem and what might be done to solve it.
|
||||
// the problem and what might be done to solve it.
|
||||
Summary string
|
||||
Detail string
|
||||
|
||||
|
|
|
@ -1565,6 +1565,52 @@ func (s *TransformFuncSpec) sourceRange(content *hcl.BodyContent, blockLabels []
|
|||
return s.Wrapped.sourceRange(content, blockLabels)
|
||||
}
|
||||
|
||||
// ValidateFuncSpec is a spec that allows for extended
|
||||
// developer-defined validation. The validation function receives the
|
||||
// result of the wrapped spec.
|
||||
//
|
||||
// The Subject field of the returned Diagnostic is optional. If not
|
||||
// specified, it is automatically populated with the range covered by
|
||||
// the wrapped spec.
|
||||
//
|
||||
type ValidateSpec struct {
|
||||
Wrapped Spec
|
||||
Func func(value cty.Value) hcl.Diagnostics
|
||||
}
|
||||
|
||||
func (s *ValidateSpec) visitSameBodyChildren(cb visitFunc) {
|
||||
cb(s.Wrapped)
|
||||
}
|
||||
|
||||
func (s *ValidateSpec) decode(content *hcl.BodyContent, blockLabels []blockLabel, ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
|
||||
wrappedVal, diags := s.Wrapped.decode(content, blockLabels, ctx)
|
||||
if diags.HasErrors() {
|
||||
// We won't try to run our function in this case, because it'll probably
|
||||
// generate confusing additional errors that will distract from the
|
||||
// root cause.
|
||||
return cty.UnknownVal(s.impliedType()), diags
|
||||
}
|
||||
|
||||
validateDiags := s.Func(wrappedVal)
|
||||
// Auto-populate the Subject fields if they weren't set.
|
||||
for i := range validateDiags {
|
||||
if validateDiags[i].Subject == nil {
|
||||
validateDiags[i].Subject = s.sourceRange(content, blockLabels).Ptr()
|
||||
}
|
||||
}
|
||||
|
||||
diags = append(diags, validateDiags...)
|
||||
return wrappedVal, diags
|
||||
}
|
||||
|
||||
func (s *ValidateSpec) impliedType() cty.Type {
|
||||
return s.Wrapped.impliedType()
|
||||
}
|
||||
|
||||
func (s *ValidateSpec) sourceRange(content *hcl.BodyContent, blockLabels []blockLabel) hcl.Range {
|
||||
return s.Wrapped.sourceRange(content, blockLabels)
|
||||
}
|
||||
|
||||
// noopSpec is a placeholder spec that does nothing, used in situations where
|
||||
// a non-nil placeholder spec is required. It is not exported because there is
|
||||
// no reason to use it directly; it is always an implementation detail only.
|
||||
|
|
|
@ -260,6 +260,20 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
|
|||
}
|
||||
|
||||
switch {
|
||||
case expandVal.Type().Equals(cty.DynamicPseudoType):
|
||||
if expandVal.IsNull() {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid expanding argument value",
|
||||
Detail: "The expanding argument (indicated by ...) must not be null.",
|
||||
Subject: expandExpr.Range().Ptr(),
|
||||
Context: e.Range().Ptr(),
|
||||
Expression: expandExpr,
|
||||
EvalContext: ctx,
|
||||
})
|
||||
return cty.DynamicVal, diags
|
||||
}
|
||||
return cty.DynamicVal, diags
|
||||
case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType():
|
||||
if expandVal.IsNull() {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
|
@ -406,22 +420,39 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
|
|||
} else {
|
||||
param = varParam
|
||||
}
|
||||
argExpr := e.Args[i]
|
||||
|
||||
// TODO: we should also unpick a PathError here and show the
|
||||
// path to the deep value where the error was detected.
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid function argument",
|
||||
Detail: fmt.Sprintf(
|
||||
"Invalid value for %q parameter: %s.",
|
||||
param.Name, err,
|
||||
),
|
||||
Subject: argExpr.StartRange().Ptr(),
|
||||
Context: e.Range().Ptr(),
|
||||
Expression: argExpr,
|
||||
EvalContext: ctx,
|
||||
})
|
||||
// this can happen if an argument is (incorrectly) null.
|
||||
if i > len(e.Args)-1 {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid function argument",
|
||||
Detail: fmt.Sprintf(
|
||||
"Invalid value for %q parameter: %s.",
|
||||
param.Name, err,
|
||||
),
|
||||
Subject: args[len(params)].StartRange().Ptr(),
|
||||
Context: e.Range().Ptr(),
|
||||
Expression: e,
|
||||
EvalContext: ctx,
|
||||
})
|
||||
} else {
|
||||
argExpr := e.Args[i]
|
||||
|
||||
// TODO: we should also unpick a PathError here and show the
|
||||
// path to the deep value where the error was detected.
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Invalid function argument",
|
||||
Detail: fmt.Sprintf(
|
||||
"Invalid value for %q parameter: %s.",
|
||||
param.Name, err,
|
||||
),
|
||||
Subject: argExpr.StartRange().Ptr(),
|
||||
Context: e.Range().Ptr(),
|
||||
Expression: argExpr,
|
||||
EvalContext: ctx,
|
||||
})
|
||||
}
|
||||
|
||||
default:
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
|
|
|
@ -521,8 +521,8 @@ func writerTokens(nativeTokens hclsyntax.Tokens) Tokens {
|
|||
// The tokens are assumed to be in source order and non-overlapping, which
|
||||
// will be true if the token sequence from the scanner is used directly.
|
||||
func partitionTokens(toks hclsyntax.Tokens, rng hcl.Range) (start, end int) {
|
||||
// We us a linear search here because we assume tha in most cases our
|
||||
// target range is close to the beginning of the sequence, and the seqences
|
||||
// We use a linear search here because we assume that in most cases our
|
||||
// target range is close to the beginning of the sequence, and the sequences
|
||||
// are generally small for most reasonable files anyway.
|
||||
for i := 0; ; i++ {
|
||||
if i >= len(toks) {
|
||||
|
|
|
@ -156,34 +156,45 @@ func conversionCollectionToMap(ety cty.Type, conv conversion) conversion {
|
|||
// given tuple type and return a set of the given element type.
|
||||
//
|
||||
// Will panic if the given tupleType isn't actually a tuple type.
|
||||
func conversionTupleToSet(tupleType cty.Type, listEty cty.Type, unsafe bool) conversion {
|
||||
func conversionTupleToSet(tupleType cty.Type, setEty cty.Type, unsafe bool) conversion {
|
||||
tupleEtys := tupleType.TupleElementTypes()
|
||||
|
||||
if len(tupleEtys) == 0 {
|
||||
// Empty tuple short-circuit
|
||||
return func(val cty.Value, path cty.Path) (cty.Value, error) {
|
||||
return cty.SetValEmpty(listEty), nil
|
||||
return cty.SetValEmpty(setEty), nil
|
||||
}
|
||||
}
|
||||
|
||||
if listEty == cty.DynamicPseudoType {
|
||||
if setEty == cty.DynamicPseudoType {
|
||||
// This is a special case where the caller wants us to find
|
||||
// a suitable single type that all elements can convert to, if
|
||||
// possible.
|
||||
listEty, _ = unify(tupleEtys, unsafe)
|
||||
if listEty == cty.NilType {
|
||||
setEty, _ = unify(tupleEtys, unsafe)
|
||||
if setEty == cty.NilType {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the set element type after unification is still the dynamic
|
||||
// type, the only way this can result in a valid set is if all values
|
||||
// are of dynamic type
|
||||
if setEty == cty.DynamicPseudoType {
|
||||
for _, tupleEty := range tupleEtys {
|
||||
if !tupleEty.Equals(cty.DynamicPseudoType) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elemConvs := make([]conversion, len(tupleEtys))
|
||||
for i, tupleEty := range tupleEtys {
|
||||
if tupleEty.Equals(listEty) {
|
||||
if tupleEty.Equals(setEty) {
|
||||
// no conversion required
|
||||
continue
|
||||
}
|
||||
|
||||
elemConvs[i] = getConversion(tupleEty, listEty, unsafe)
|
||||
elemConvs[i] = getConversion(tupleEty, setEty, unsafe)
|
||||
if elemConvs[i] == nil {
|
||||
// If any of our element conversions are impossible, then the our
|
||||
// whole conversion is impossible.
|
||||
|
@ -244,6 +255,17 @@ func conversionTupleToList(tupleType cty.Type, listEty cty.Type, unsafe bool) co
|
|||
if listEty == cty.NilType {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the list element type after unification is still the dynamic
|
||||
// type, the only way this can result in a valid list is if all values
|
||||
// are of dynamic type
|
||||
if listEty == cty.DynamicPseudoType {
|
||||
for _, tupleEty := range tupleEtys {
|
||||
if !tupleEty.Equals(cty.DynamicPseudoType) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elemConvs := make([]conversion, len(tupleEtys))
|
||||
|
|
|
@ -87,7 +87,7 @@ func (t Type) HasDynamicTypes() bool {
|
|||
case t.IsPrimitiveType():
|
||||
return false
|
||||
case t.IsCollectionType():
|
||||
return false
|
||||
return t.ElementType().HasDynamicTypes()
|
||||
case t.IsObjectType():
|
||||
attrTypes := t.AttributeTypes()
|
||||
for _, at := range attrTypes {
|
||||
|
|
|
@ -106,3 +106,37 @@ func (val Value) IsWhollyKnown() bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// HasWhollyKnownType checks if the value is dynamic, or contains any nested
|
||||
// DynamicVal. This implies that both the value is not known, and the final
|
||||
// type may change.
|
||||
func (val Value) HasWhollyKnownType() bool {
|
||||
// a null dynamic type is known
|
||||
if val.IsNull() {
|
||||
return true
|
||||
}
|
||||
|
||||
// an unknown DynamicPseudoType is a DynamicVal, but we don't want to
|
||||
// check that value for equality here, since this method is used within the
|
||||
// equality check.
|
||||
if !val.IsKnown() && val.ty == DynamicPseudoType {
|
||||
return false
|
||||
}
|
||||
|
||||
if val.CanIterateElements() {
|
||||
// if the value is not known, then we can look directly at the internal
|
||||
// types
|
||||
if !val.IsKnown() {
|
||||
return !val.ty.HasDynamicTypes()
|
||||
}
|
||||
|
||||
for it := val.ElementIterator(); it.Next(); {
|
||||
_, ev := it.Element()
|
||||
if !ev.HasWhollyKnownType() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -133,9 +133,9 @@ func (val Value) Equals(other Value) Value {
|
|||
case val.IsKnown() && !other.IsKnown():
|
||||
switch {
|
||||
case val.IsNull(), other.ty.HasDynamicTypes():
|
||||
// If known is Null, we need to wait for the unkown value since
|
||||
// If known is Null, we need to wait for the unknown value since
|
||||
// nulls of any type are equal.
|
||||
// An unkown with a dynamic type compares as unknown, which we need
|
||||
// An unknown with a dynamic type compares as unknown, which we need
|
||||
// to check before the type comparison below.
|
||||
return UnknownVal(Bool)
|
||||
case !val.ty.Equals(other.ty):
|
||||
|
@ -148,9 +148,9 @@ func (val Value) Equals(other Value) Value {
|
|||
case other.IsKnown() && !val.IsKnown():
|
||||
switch {
|
||||
case other.IsNull(), val.ty.HasDynamicTypes():
|
||||
// If known is Null, we need to wait for the unkown value since
|
||||
// If known is Null, we need to wait for the unknown value since
|
||||
// nulls of any type are equal.
|
||||
// An unkown with a dynamic type compares as unknown, which we need
|
||||
// An unknown with a dynamic type compares as unknown, which we need
|
||||
// to check before the type comparison below.
|
||||
return UnknownVal(Bool)
|
||||
case !other.ty.Equals(val.ty):
|
||||
|
@ -171,7 +171,15 @@ func (val Value) Equals(other Value) Value {
|
|||
return BoolVal(false)
|
||||
}
|
||||
|
||||
if val.ty.HasDynamicTypes() || other.ty.HasDynamicTypes() {
|
||||
// Check if there are any nested dynamic values making this comparison
|
||||
// unknown.
|
||||
if !val.HasWhollyKnownType() || !other.HasWhollyKnownType() {
|
||||
// Even if we have dynamic values, we can still determine inequality if
|
||||
// there is no way the types could later conform.
|
||||
if val.ty.TestConformance(other.ty) != nil && other.ty.TestConformance(val.ty) != nil {
|
||||
return BoolVal(false)
|
||||
}
|
||||
|
||||
return UnknownVal(Bool)
|
||||
}
|
||||
|
||||
|
|
|
@ -375,7 +375,7 @@ github.com/hashicorp/hcl/hcl/token
|
|||
github.com/hashicorp/hcl/json/parser
|
||||
github.com/hashicorp/hcl/json/scanner
|
||||
github.com/hashicorp/hcl/json/token
|
||||
# github.com/hashicorp/hcl/v2 v2.5.1
|
||||
# github.com/hashicorp/hcl/v2 v2.6.0
|
||||
## explicit
|
||||
github.com/hashicorp/hcl/v2
|
||||
github.com/hashicorp/hcl/v2/ext/customdecode
|
||||
|
@ -597,7 +597,7 @@ github.com/xanzy/ssh-agent
|
|||
# github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
|
||||
## explicit
|
||||
github.com/xlab/treeprint
|
||||
# github.com/zclconf/go-cty v1.4.2
|
||||
# github.com/zclconf/go-cty v1.5.0
|
||||
## explicit
|
||||
github.com/zclconf/go-cty/cty
|
||||
github.com/zclconf/go-cty/cty/convert
|
||||
|
|
Loading…
Reference in New Issue