mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
buildflags: handle unknown values from cty
Update the buildflags cty code to handle unknown values. When hcl decodes a value with an invalid variable name, it appends a diagnostic for the error and then returns an unknown value so it can continue processing the file and finding more errors. The iteration code has now been changed to use a rangefunc from go 1.23 and it skips empty or unknown values. Empty values are valid when they are skipped and unknown values will have a diagnostic for itself. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
@ -24,9 +24,7 @@ func (e *Attests) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
|
||||
func (e *Attests) fromCtyValue(in cty.Value, p cty.Path) error {
|
||||
*e = make([]*Attest, 0, in.LengthInt())
|
||||
for elem := in.ElementIterator(); elem.Next(); {
|
||||
_, value := elem.Element()
|
||||
|
||||
for value := range eachElement(in) {
|
||||
entry := &Attest{}
|
||||
if err := entry.FromCtyValue(value, p); err != nil {
|
||||
return err
|
||||
@ -64,6 +62,10 @@ func (e *Attest) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
e.Attrs = map[string]string{}
|
||||
for it := conv.ElementIterator(); it.Next(); {
|
||||
k, v := it.Element()
|
||||
if !v.IsKnown() {
|
||||
continue
|
||||
}
|
||||
|
||||
switch key := k.AsString(); key {
|
||||
case "type":
|
||||
e.Type = v.AsString()
|
||||
|
@ -23,13 +23,7 @@ func (o *CacheOptions) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
|
||||
func (o *CacheOptions) fromCtyValue(in cty.Value, p cty.Path) error {
|
||||
*o = make([]*CacheOptionsEntry, 0, in.LengthInt())
|
||||
for elem := in.ElementIterator(); elem.Next(); {
|
||||
_, value := elem.Element()
|
||||
|
||||
if isEmpty(value) {
|
||||
continue
|
||||
}
|
||||
|
||||
for value := range eachElement(in) {
|
||||
// Special handling for a string type to handle ref only format.
|
||||
if value.Type() == cty.String {
|
||||
entries, err := ParseCacheEntry([]string{value.AsString()})
|
||||
|
@ -23,13 +23,7 @@ func (e *Exports) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
|
||||
func (e *Exports) fromCtyValue(in cty.Value, p cty.Path) error {
|
||||
*e = make([]*ExportEntry, 0, in.LengthInt())
|
||||
for elem := in.ElementIterator(); elem.Next(); {
|
||||
_, value := elem.Element()
|
||||
|
||||
if isEmpty(value) {
|
||||
continue
|
||||
}
|
||||
|
||||
for value := range eachElement(in) {
|
||||
entry := &ExportEntry{}
|
||||
if err := entry.FromCtyValue(value, p); err != nil {
|
||||
return err
|
||||
|
@ -30,13 +30,7 @@ func (s *Secrets) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
|
||||
func (s *Secrets) fromCtyValue(in cty.Value, p cty.Path) error {
|
||||
*s = make([]*Secret, 0, in.LengthInt())
|
||||
for elem := in.ElementIterator(); elem.Next(); {
|
||||
_, value := elem.Element()
|
||||
|
||||
if isEmpty(value) {
|
||||
continue
|
||||
}
|
||||
|
||||
for value := range eachElement(in) {
|
||||
entry := &Secret{}
|
||||
if err := entry.FromCtyValue(value, p); err != nil {
|
||||
return err
|
||||
@ -71,13 +65,13 @@ func (e *Secret) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if id := conv.GetAttr("id"); !id.IsNull() {
|
||||
if id := conv.GetAttr("id"); !id.IsNull() && id.IsKnown() {
|
||||
e.ID = id.AsString()
|
||||
}
|
||||
if src := conv.GetAttr("src"); !src.IsNull() {
|
||||
if src := conv.GetAttr("src"); !src.IsNull() && src.IsKnown() {
|
||||
e.FilePath = src.AsString()
|
||||
}
|
||||
if env := conv.GetAttr("env"); !env.IsNull() {
|
||||
if env := conv.GetAttr("env"); !env.IsNull() && env.IsKnown() {
|
||||
e.Env = env.AsString()
|
||||
}
|
||||
return nil
|
||||
|
@ -30,13 +30,7 @@ func (s *SSHKeys) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
|
||||
func (s *SSHKeys) fromCtyValue(in cty.Value, p cty.Path) error {
|
||||
*s = make([]*SSH, 0, in.LengthInt())
|
||||
for elem := in.ElementIterator(); elem.Next(); {
|
||||
_, value := elem.Element()
|
||||
|
||||
if isEmpty(value) {
|
||||
continue
|
||||
}
|
||||
|
||||
for value := range eachElement(in) {
|
||||
entry := &SSH{}
|
||||
if err := entry.FromCtyValue(value, p); err != nil {
|
||||
return err
|
||||
@ -71,10 +65,10 @@ func (e *SSH) FromCtyValue(in cty.Value, p cty.Path) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if id := conv.GetAttr("id"); !id.IsNull() {
|
||||
if id := conv.GetAttr("id"); !id.IsNull() && id.IsKnown() {
|
||||
e.ID = id.AsString()
|
||||
}
|
||||
if paths := conv.GetAttr("paths"); !paths.IsNull() {
|
||||
if paths := conv.GetAttr("paths"); !paths.IsNull() && paths.IsKnown() {
|
||||
if err := gocty.FromCtyValue(paths, &e.Paths); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package buildflags
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/gocty"
|
||||
)
|
||||
@ -34,7 +36,7 @@ func removeDupes[E comparable[E]](s []E) []E {
|
||||
}
|
||||
|
||||
func getAndDelete(m map[string]cty.Value, attr string, gv interface{}) error {
|
||||
if v, ok := m[attr]; ok {
|
||||
if v, ok := m[attr]; ok && v.IsKnown() {
|
||||
delete(m, attr)
|
||||
return gocty.FromCtyValue(v, gv)
|
||||
}
|
||||
@ -44,11 +46,28 @@ func getAndDelete(m map[string]cty.Value, attr string, gv interface{}) error {
|
||||
func asMap(m map[string]cty.Value) map[string]string {
|
||||
out := make(map[string]string, len(m))
|
||||
for k, v := range m {
|
||||
out[k] = v.AsString()
|
||||
if v.IsKnown() {
|
||||
out[k] = v.AsString()
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func isEmpty(v cty.Value) bool {
|
||||
return v.Type() == cty.String && v.AsString() == ""
|
||||
func isEmptyOrUnknown(v cty.Value) bool {
|
||||
return !v.IsKnown() || (v.Type() == cty.String && v.AsString() == "")
|
||||
}
|
||||
|
||||
func eachElement(in cty.Value) iter.Seq[cty.Value] {
|
||||
return func(yield func(v cty.Value) bool) {
|
||||
for elem := in.ElementIterator(); elem.Next(); {
|
||||
_, value := elem.Element()
|
||||
if isEmptyOrUnknown(value) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !yield(value) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user