-
Notifications
You must be signed in to change notification settings - Fork 208
/
parameter_sources.go
236 lines (199 loc) · 7.67 KB
/
parameter_sources.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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package cnab
import (
"encoding/json"
"github.com/pkg/errors"
)
const (
// ParameterSourcesExtensionShortHand is the short suffix of the ParameterSourcesExtensionKey.
ParameterSourcesExtensionShortHand = "parameter-sources"
// ParameterSourcesExtensionKey represents the full key for the Parameter Sources Extension.
ParameterSourcesExtensionKey = OfficialExtensionsPrefix + ParameterSourcesExtensionShortHand
// ParameterSourcesExtensionSchema represents the schema for the Docker Extension.
ParameterSourcesSchema = "https://cnab.io/v1/parameter-sources.schema.json"
// ParameterSourceTypeOutput defines a type of parameter source that is provided by a bundle output.
ParameterSourceTypeOutput = "output"
// ParameterSourceTypeDependencyOutput defines a type of parameter source that is provided by a bundle's dependency
// output.
ParameterSourceTypeDependencyOutput = "dependencies.output"
)
// ParameterSourcesExtension represents a required extension that specifies how
// to default parameter values.
var ParameterSourcesExtension = RequiredExtension{
Shorthand: ParameterSourcesExtensionShortHand,
Key: ParameterSourcesExtensionKey,
Schema: ParameterSourcesSchema,
Reader: ParameterSourcesReader,
}
// ParameterSources describes the set of custom extension metadata associated
// with the Parameter Sources extension
type ParameterSources map[string]ParameterSource
// SetParameterFromOutput creates an entry in the parameter sources section setting
// the parameter's value using the specified output's value.
func (ps *ParameterSources) SetParameterFromOutput(parameter string, output string) {
if *ps == nil {
*ps = ParameterSources{}
}
(*ps)[parameter] = ParameterSource{
Priority: []string{ParameterSourceTypeOutput},
Sources: ParameterSourceMap{
ParameterSourceTypeOutput: OutputParameterSource{OutputName: output},
},
}
}
// SetParameterFromDependencyOutput creates an entry in the parameter sources section setting
// the parameter's value using the specified dependency's output value.
func (ps *ParameterSources) SetParameterFromDependencyOutput(parameter string, dep string, output string) {
if *ps == nil {
*ps = ParameterSources{}
}
(*ps)[parameter] = ParameterSource{
Priority: []string{ParameterSourceTypeDependencyOutput},
Sources: ParameterSourceMap{
ParameterSourceTypeDependencyOutput: DependencyOutputParameterSource{
Dependency: dep,
OutputName: output},
},
}
}
type ParameterSource struct {
// Priority is an array of source types in the priority order that they should be used to
// populated the parameter.
Priority []string `json:"priority" mapstructure:"priority"`
// Sources is a map of key/value pairs of a source type and definition for
// the parameter value.
Sources ParameterSourceMap `json:"sources" mapstructure:"sources"`
}
// ListSourcesByPriority returns the parameter sources by the requested priority,
// if none is specified, they are unsorted.
func (s ParameterSource) ListSourcesByPriority() []ParameterSourceDefinition {
sources := make([]ParameterSourceDefinition, 0, len(s.Sources))
if len(s.Priority) == 0 {
for _, source := range s.Sources {
sources = append(sources, source)
}
} else {
for _, sourceType := range s.Priority {
sources = append(sources, s.Sources[sourceType])
}
}
return sources
}
type ParameterSourceMap map[string]ParameterSourceDefinition
func (m *ParameterSourceMap) UnmarshalJSON(data []byte) error {
if *m == nil {
*m = ParameterSourceMap{}
}
var rawMap map[string]interface{}
err := json.Unmarshal(data, &rawMap)
if err != nil {
return err
}
for sourceKey, sourceDef := range rawMap {
rawDef, err := json.Marshal(sourceDef)
if err != nil {
return errors.Wrapf(err, "error re-marshaling parameter source definition")
}
switch sourceKey {
case ParameterSourceTypeOutput:
var output OutputParameterSource
err := json.Unmarshal(rawDef, &output)
if err != nil {
return errors.Wrapf(err, "invalid parameter source definition for key %s", sourceKey)
}
(*m)[ParameterSourceTypeOutput] = output
case ParameterSourceTypeDependencyOutput:
var depOutput DependencyOutputParameterSource
err := json.Unmarshal(rawDef, &depOutput)
if err != nil {
return errors.Wrapf(err, "invalid parameter source definition for key %s", sourceKey)
}
(*m)[ParameterSourceTypeDependencyOutput] = depOutput
default:
return errors.Errorf("unsupported parameter source key %s", sourceKey)
}
}
return nil
}
type ParameterSourceDefinition interface {
}
// OutputParameterSource represents a parameter that is set using the value from
// a bundle output.
type OutputParameterSource struct {
OutputName string `json:"name" mapstructure:"name"`
}
// DependencyOutputParameterSource represents a parameter that is set using the value
// from a bundle's dependency output.
type DependencyOutputParameterSource struct {
Dependency string `json:"dependency" mapstructure:"dependency"`
OutputName string `json:"name" mapstructure:"name"`
}
// ReadParameterSources is a convenience method for returning a bonafide
// ParameterSources reference after reading from the applicable section from
// the provided bundle
func (b ExtendedBundle) ReadParameterSources() (ParameterSources, error) {
raw, err := b.ParameterSourcesReader()
if err != nil {
return nil, err
}
ps, ok := raw.(ParameterSources)
if !ok {
return nil, errors.New("unable to read parameter sources extension data")
}
return ps, nil
}
// ParameterSourcesReader is a Reader for the ParameterSourcesExtension,
// which reads from the applicable section in the provided bundle and
// returns the raw data in the form of an interface
func ParameterSourcesReader(bun ExtendedBundle) (interface{}, error) {
return bun.ParameterSourcesReader()
}
// ParameterSourcesReader is a Reader for the ParameterSourcesExtension,
// which reads from the applicable section in the provided bundle and
// returns the raw data in the form of an interface
func (b ExtendedBundle) ParameterSourcesReader() (interface{}, error) {
data, ok := b.Custom[ParameterSourcesExtensionKey]
if !ok {
return nil, errors.Errorf("attempted to read parameter sources from bundle but none are defined")
}
dataB, err := json.Marshal(data)
if err != nil {
return nil, errors.Wrapf(err, "could not marshal the untyped %q extension data %q",
ParameterSourcesExtensionKey, string(dataB))
}
ps := ParameterSources{}
err = json.Unmarshal(dataB, &ps)
if err != nil {
return nil, errors.Wrapf(err, "could not unmarshal the %q extension %q",
ParameterSourcesExtensionKey, string(dataB))
}
return ps, nil
}
// SupportsParameterSources checks if the bundle supports parameter sources.
func (b ExtendedBundle) SupportsParameterSources() bool {
return b.SupportsExtension(ParameterSourcesExtensionKey)
}
// GetParameterSources checks if the parameter sources extension is present and returns its
// extension configuration.
func (e ProcessedExtensions) GetParameterSources() (ParameterSources, bool, error) {
rawExt, required := e[ParameterSourcesExtensionKey]
ext, ok := rawExt.(ParameterSources)
if !ok && required {
return ParameterSources{}, required, errors.Errorf("unable to parse Parameter Sources extension config: %+v", rawExt)
}
return ext, required, nil
}
// HasParameterSources returns whether or not the bundle has parameter sources defined.
func (b ExtendedBundle) HasParameterSources() bool {
_, ok := b.Custom[ParameterSourcesExtensionKey]
return ok
}
// ParameterHasSource determines if the specified parameter has a parameter
// source defined.
func (b ExtendedBundle) ParameterHasSource(paramName string) bool {
sources, err := b.ReadParameterSources()
if err != nil {
return false
}
_, hasSource := sources[paramName]
return hasSource
}