/
payload.go
138 lines (112 loc) · 3.64 KB
/
payload.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
package context
import (
"io/ioutil"
"path/filepath"
"strings"
OrbitError "github.com/gulien/orbit/app/error"
"github.com/gulien/orbit/app/helpers"
"github.com/gulien/orbit/app/logger"
"gopkg.in/yaml.v2"
)
// default payload file path.
const payloadFilePath = "orbit-payload.yml"
type (
// orbitPayload contains the various entries provided by the user.
orbitPayload struct {
// PayloadEntries is a simple array of orbitPayloadEntry.
PayloadEntries []*orbitPayloadEntry `yaml:"payload,omitempty"`
// TemplatesEntries is a simple array of string.
TemplatesEntries []string `yaml:"templates,omitempty"`
}
// orbitPayloadEntry is an entry from a file or from a string.
orbitPayloadEntry struct {
// Key is the unique identifier of a value.
Key string `yaml:"key"`
// Value is a raw data or a file path.
Value string `yaml:"value"`
}
)
// populateFromFile populates the instance of orbitPayload
// with entries provided by a YAML file.
func (p *orbitPayload) populateFromFile(filePath string) error {
if filePath == "" {
filePath = payloadFilePath
}
// first, checks if the file exists.
if !helpers.FileExists(filePath) {
logger.Debugf("payload file %s does not exist, skipping", filePath)
return nil
}
// alright, let's read it to retrieve its data...
data, err := ioutil.ReadFile(filePath)
if err != nil {
return OrbitError.NewOrbitErrorf("unable to read the payload file %s. Details:\n%s", filePath, err)
}
// ...then parses the YAML.
if err := yaml.Unmarshal(data, &p); err != nil {
return OrbitError.NewOrbitErrorf("payload file %s is not a valid YAML file. Details:\n%s", filePath, err)
}
return nil
}
// populateFromString populates the instance of orbitPayload
// with entries provided by a string.
func (p *orbitPayload) populateFromString(payload string, templates string) error {
// first, checks if a payload has been given.
if payload == "" && templates == "" {
logger.Debugf("no payload and templates flags given, skipping")
return nil
}
if payload != "" {
// the payload string should be in the following format:
// key,value;key,value.
entries := strings.Split(payload, ";")
for _, entry := range entries {
entry := strings.Split(entry, ",")
if len(entry) == 1 {
return OrbitError.NewOrbitErrorf("unable to process the payload entry %s", entry)
}
p.PayloadEntries = append(p.PayloadEntries, &orbitPayloadEntry{
Key: entry[0],
Value: strings.Join(entry[1:], ","),
})
}
}
if templates != "" {
// the templates string should be in the following format:
// path,path,path.
entries := strings.Split(templates, ",")
for _, entry := range entries {
p.TemplatesEntries = append(p.TemplatesEntries, entry)
}
}
return nil
}
// retrievePayloadData parses all the payload entries from the instance of orbitPayload
// to retrieve the data which will be applied to a data-driven template.
func (p *orbitPayload) retrievePayloadData() (map[string]interface{}, error) {
result := make(map[string]interface{})
for _, payloadEntry := range p.PayloadEntries {
d := getDecoder(payloadEntry.Value)
value, err := d.decode()
if err != nil {
return nil, err
}
result[payloadEntry.Key] = value
}
return result, nil
}
// getDecoder returns the correct decoder for a given value.
func getDecoder(value string) orbitDecoder {
if !helpers.FileExists(value) {
return &orbitDumbDecoder{value: value}
}
switch extension := filepath.Ext(value); extension {
case ".yaml", ".yml":
return &orbitYAMLDecoder{value: value}
case ".toml":
return &orbitTOMLDecoder{value: value}
case ".json":
return &orbitJSONDecoder{value: value}
}
return &orbitEnvFileDecoder{value: value}
}