github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/legacy/helper/schema/field_reader_multi.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package schema 5 6 import ( 7 "fmt" 8 ) 9 10 // MultiLevelFieldReader reads from other field readers, 11 // merging their results along the way in a specific order. You can specify 12 // "levels" and name them in order to read only an exact level or up to 13 // a specific level. 14 // 15 // This is useful for saying things such as "read the field from the state 16 // and config and merge them" or "read the latest value of the field". 17 type MultiLevelFieldReader struct { 18 Readers map[string]FieldReader 19 Levels []string 20 } 21 22 func (r *MultiLevelFieldReader) ReadField(address []string) (FieldReadResult, error) { 23 return r.ReadFieldMerge(address, r.Levels[len(r.Levels)-1]) 24 } 25 26 func (r *MultiLevelFieldReader) ReadFieldExact( 27 address []string, level string) (FieldReadResult, error) { 28 reader, ok := r.Readers[level] 29 if !ok { 30 return FieldReadResult{}, fmt.Errorf( 31 "Unknown reader level: %s", level) 32 } 33 34 result, err := reader.ReadField(address) 35 if err != nil { 36 return FieldReadResult{}, fmt.Errorf( 37 "Error reading level %s: %s", level, err) 38 } 39 40 return result, nil 41 } 42 43 func (r *MultiLevelFieldReader) ReadFieldMerge( 44 address []string, level string) (FieldReadResult, error) { 45 var result FieldReadResult 46 for _, l := range r.Levels { 47 if r, ok := r.Readers[l]; ok { 48 out, err := r.ReadField(address) 49 if err != nil { 50 return FieldReadResult{}, fmt.Errorf( 51 "Error reading level %s: %s", l, err) 52 } 53 54 // TODO: computed 55 if out.Exists { 56 result = out 57 } 58 } 59 60 if l == level { 61 break 62 } 63 } 64 65 return result, nil 66 }