-
Notifications
You must be signed in to change notification settings - Fork 11
/
context.go
158 lines (143 loc) · 4.55 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package main
import (
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"github.com/coveooss/gotemplate/v3/collections"
"github.com/coveooss/gotemplate/v3/template"
)
func createContext(varsFiles, varsFilesIfExist, namedVars []string, mode string, ignoreMissingFiles bool) (collections.IDictionary, error) {
var context collections.IDictionary
type fileDef struct {
name string
value interface{}
unnamed bool
required bool
}
if mode != "" {
// The type has been specified on the command line, so we initialize the context
// with the default type manager
context = collections.CreateDictionary()
}
nameValuePairs := make([]fileDef, 0, len(varsFiles)+len(namedVars))
for i := range varsFilesIfExist {
nameValuePairs = append(nameValuePairs, fileDef{value: varsFilesIfExist[i]})
}
for i := range varsFiles {
nameValuePairs = append(nameValuePairs, fileDef{value: varsFiles[i], required: true})
}
for i := range namedVars {
data := collections.CreateDictionary().AsMap()
if err := collections.ConvertData(namedVars[i], &data); err != nil {
var fd fileDef
fd.name, fd.value = collections.Split2(namedVars[i], "=")
if fd.value == "" {
fd = fileDef{value: fd.name, unnamed: true}
}
nameValuePairs = append(nameValuePairs, fd)
continue
}
if len(data) == 0 && strings.Contains(namedVars[i], "=") {
// The hcl converter consider "value=" as an empty map instead of empty value in a map
// we handle it
name, value := collections.Split2(namedVars[i], "=")
data[name] = value
}
for key, value := range data {
nameValuePairs = append(nameValuePairs, fileDef{name: key, value: value})
}
}
var unnamed []interface{}
for _, nv := range nameValuePairs {
var loader func(string) (collections.IDictionary, error)
filename, _ := reflect.ValueOf(nv.value).Interface().(string)
if filename != "" {
loader = func(filename string) (collections.IDictionary, error) {
var content interface{}
loadErr := collections.LoadData(filename, &content)
_, isFileErr := loadErr.(*os.PathError)
if loadErr == nil {
if nv.name == "" && !nv.unnamed {
if content, err := collections.TryAsDictionary(content); err == nil {
return content, nil
}
}
if nv.name == "" {
nv.name = strings.TrimSuffix(filepath.Base(filename), filepath.Ext(filename))
}
return collections.AsDictionary(map[string]interface{}{nv.name: content}), nil
} else if !isFileErr {
return nil, loadErr
}
// Finally, we just try to convert the data with the converted value
if err := collections.ConvertData(filename, &content); err != nil {
content = nv.value
}
if nv.name == "" && isFileErr {
if !nv.required {
loadErr = nil
}
return nil, loadErr
} else if nv.name == "" {
unnamed = append(unnamed, content)
return nil, nil
}
// If it does not work, we just set the value as is
return collections.AsDictionary(map[string]interface{}{nv.name: content}), nil
}
if filename == "-" {
loader = func(filename string) (result collections.IDictionary, err error) {
var content interface{}
if err = collections.ConvertData(readStdin(), &content); err != nil {
return nil, err
}
if nv.name == "" {
if content, err := collections.TryAsDictionary(content); err == nil {
return content, nil
}
}
if nv.name == "" {
nv.name = "STDIN"
}
return collections.AsDictionary(map[string]interface{}{nv.name: content}), nil
}
}
}
if loader == nil {
if context == nil {
// The context is not initialized yet, so we create it with the default collection type
context = collections.CreateDictionary()
}
context.Set(nv.name, nv.value)
continue
}
content, err := loader(filename)
if err != nil {
if _, isFileErr := err.(*os.PathError); isFileErr && ignoreMissingFiles {
template.InternalLog.Debugf("Import: %s not found. Skipping the import", filename)
continue
} else {
return nil, fmt.Errorf("error %w while loading variable file %v", err, nv.value)
}
}
if content != nil {
if context == nil {
// The context is not initialized yet, so we create it with the same type of the
// first file argument
context = content.Create()
dictHelper, listHelper := content.GetHelpers()
collections.SetDictionaryHelper(dictHelper)
collections.SetListHelper(listHelper)
}
for key, value := range content.AsMap() {
context.Set(key, value)
}
}
}
if len(unnamed) > 0 {
context.Set("ARGS", unnamed)
}
return context, nil
}