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