/
base_render_options.go
158 lines (126 loc) · 3.86 KB
/
base_render_options.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
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package templating
import (
"fmt"
"strings"
"time"
"github.com/pkg/errors"
)
// BaseRenderOptions represents additional information for the composition of the final rendering.
type BaseRenderOptions struct {
// Path to the task file.
TaskFile string
// Base64 encoded task file.
Base64EncodedTaskFile string
// Path to a values file.
ValuesFile string
// Base64 encoded values file.
Base64EncodedValuesFile string
// Override values.
TemplateValues []string
// ID is a unique identifier for the run.
ID string
// Commit is the SHA the run was triggered against.
Commit string
// Repository is the repository the run was triggered against.
Repository string
// Branch is the branch the run was triggered against.
Branch string
// TriggeredBy is the reason the run was triggered.
TriggeredBy string
// GitTag is the git tag the run was triggered against.
GitTag string
// Registry is the container registry being used.
Registry string
// Date is the UTC date of the run.
Date time.Time
// SharedVolume is the name of the shared volume.
SharedVolume string
// OS is the GOOS.
OS string
// Architecture is the GOARCH.
Architecture string
}
// OverrideValuesWithBuildInfo overrides the specified config's values and provides a default set of values.
func OverrideValuesWithBuildInfo(c1 *Config, c2 *Config, opts *BaseRenderOptions) (Values, error) {
base := map[string]interface{}{
"Build": map[string]interface{}{
"ID": opts.ID,
},
"Run": map[string]interface{}{
"ID": opts.ID,
"Commit": opts.Commit,
"Repository": opts.Repository,
"Branch": opts.Branch,
"GitTag": opts.GitTag,
"TriggeredBy": opts.TriggeredBy,
"Registry": opts.Registry,
"Date": opts.Date.Format("20060102-150405z"), // yyyyMMdd-HHmmssz
"SharedVolume": opts.SharedVolume,
"OS": opts.OS,
"Architecture": opts.Architecture,
},
}
vals, err := OverrideValues(c1, c2)
if err != nil {
return base, err
}
base["Values"] = vals
return base, nil
}
// LoadAndRenderSteps loads a template file and renders it according to an optional values file, --set values,
// and base render options.
func LoadAndRenderSteps(template *Template, opts *BaseRenderOptions) (string, error) {
var err error
config := &Config{}
if opts.ValuesFile != "" {
if config, err = LoadConfig(opts.ValuesFile); err != nil {
return "", err
}
} else if opts.Base64EncodedValuesFile != "" {
if config, err = DecodeConfig(opts.Base64EncodedValuesFile); err != nil {
return "", err
}
}
setConfig := &Config{}
if len(opts.TemplateValues) > 0 {
rawVals, err := parseValues(opts.TemplateValues)
if err != nil {
return "", err
}
setConfig = &Config{RawValue: rawVals, Values: map[string]*Value{}}
}
mergedVals, err := OverrideValuesWithBuildInfo(config, setConfig, opts)
if err != nil {
return "", fmt.Errorf("Failed to override values: %v", err)
}
engine := NewEngine()
rendered, err := engine.Render(template, mergedVals)
if err != nil {
return "", fmt.Errorf("Error while rendering templates: %v", err)
}
if rendered == "" {
return "", errors.New("Rendered template was empty")
}
return rendered, nil
}
// parseValues receives a slice of values in key=val format
// and serializes them into YAML. If a key is specified more
// than once, the key will be overridden.
func parseValues(values []string) (string, error) {
ret := Values{}
for _, v := range values {
i := strings.Index(v, "=")
if i < 0 {
return "", errors.New("failed to parse --set data; invalid format, no = assignment found")
}
key := v[:i]
if key == "" {
return "", errors.New("failed to parse --set data; expected a key=val format")
}
val := v[i+1:] // Skip the = separator
ret[key] = val
}
return ret.ToYAMLString()
}