github.com/hairyhenderson/templater@v3.5.0+incompatible/data/datasource_merge.go (about) 1 package data 2 3 import ( 4 "strings" 5 6 "github.com/hairyhenderson/gomplate/coll" 7 8 "github.com/pkg/errors" 9 ) 10 11 // readMerge demultiplexes a `merge:` datasource. The 'args' parameter currently 12 // has no meaning for this source. 13 // 14 // URI format is 'merge:<source 1>|<source 2>[|<source n>...]' where `<source #>` 15 // is a supported URI or a pre-defined alias name. 16 // 17 // Query strings and fragments are interpreted relative to the merged data, not 18 // the source data. To merge datasources with query strings or fragments, define 19 // separate sources first and specify the alias names. HTTP headers are also not 20 // supported directly. 21 func (d *Data) readMerge(source *Source, args ...string) ([]byte, error) { 22 opaque := source.URL.Opaque 23 parts := strings.Split(opaque, "|") 24 if len(parts) < 2 { 25 return nil, errors.New("need at least 2 datasources to merge") 26 } 27 data := make([]map[string]interface{}, len(parts)) 28 for i, part := range parts { 29 // supports either URIs or aliases 30 subSource, err := d.lookupSource(part) 31 if err != nil { 32 // maybe it's a relative filename? 33 subSource, err = parseSource(part + "=" + part) 34 if err != nil { 35 return nil, err 36 } 37 } 38 subSource.inherit(source) 39 40 b, err := d.readSource(subSource) 41 if err != nil { 42 return nil, errors.Wrapf(err, "Couldn't read datasource '%s'", part) 43 } 44 45 mimeType, err := subSource.mimeType() 46 if err != nil { 47 return nil, errors.Wrapf(err, "failed to read datasource %s", subSource.URL) 48 } 49 50 data[i], err = parseMap(mimeType, string(b)) 51 if err != nil { 52 return nil, err 53 } 54 } 55 56 // Merge the data together 57 b, err := mergeData(data) 58 if err != nil { 59 return nil, err 60 } 61 62 source.mediaType = yamlMimetype 63 return b, nil 64 } 65 66 func mergeData(data []map[string]interface{}) (out []byte, err error) { 67 dst := data[0] 68 data = data[1:] 69 70 dst, err = coll.Merge(dst, data...) 71 if err != nil { 72 return nil, err 73 } 74 75 s, err := ToYAML(dst) 76 if err != nil { 77 return nil, err 78 } 79 return []byte(s), nil 80 } 81 82 func parseMap(mimeType, data string) (map[string]interface{}, error) { 83 datum, err := parseData(mimeType, data) 84 if err != nil { 85 return nil, err 86 } 87 var m map[string]interface{} 88 switch datum := datum.(type) { 89 case map[string]interface{}: 90 m = datum 91 default: 92 return nil, errors.Errorf("unexpected data type '%T' for datasource (type %s); merge: can only merge maps", datum, mimeType) 93 } 94 return m, nil 95 }