forked from realvnc-labs/tacoscript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuilder.go
More file actions
109 lines (88 loc) · 2.45 KB
/
builder.go
File metadata and controls
109 lines (88 loc) · 2.45 KB
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
package script
import (
"bytes"
"errors"
"fmt"
"os"
"text/template"
"github.com/cloudradar-monitoring/tacoscript/utils"
"github.com/cloudradar-monitoring/tacoscript/tasks"
"gopkg.in/yaml.v2"
)
type FileDataProvider struct {
Path string
}
func (fdp FileDataProvider) Read() ([]byte, error) {
return os.ReadFile(fdp.Path)
}
type RawDataProvider interface {
Read() ([]byte, error)
}
type TemplateVariablesProvider interface {
GetTemplateVariables() (map[string]interface{}, error)
}
type Builder struct {
DataProvider RawDataProvider
TaskBuilder tasks.Builder
TemplateVariablesProvider TemplateVariablesProvider
}
func (p Builder) BuildScripts() (tasks.Scripts, error) {
yamlTemplate, err := p.DataProvider.Read()
if err != nil {
return tasks.Scripts{}, err
}
templateVariables, err := p.TemplateVariablesProvider.GetTemplateVariables()
if err != nil {
return tasks.Scripts{}, err
}
yamlBody, err := p.render(yamlTemplate, templateVariables)
if err != nil {
return tasks.Scripts{}, err
}
if len(yamlBody) == 0 {
return tasks.Scripts{}, errors.New("empty script provided: nothing to execute")
}
rawScripts := yaml.MapSlice{}
err = yaml.Unmarshal(yamlBody, &rawScripts)
if err != nil {
return tasks.Scripts{}, fmt.Errorf("invalid script provided: %w", err)
}
scripts := make(tasks.Scripts, 0, len(rawScripts))
errs := utils.Errors{}
for _, rawTask := range rawScripts {
scriptID := rawTask.Key.(string)
script := tasks.Script{
ID: scriptID,
Tasks: []tasks.Task{},
}
index := 0
if steps, ok := rawTask.Value.(yaml.MapSlice); ok {
for _, step := range steps {
taskTypeID := step.Key.(string)
index++
task, e := p.TaskBuilder.Build(taskTypeID, fmt.Sprintf("%s.%s[%d]", scriptID, taskTypeID, index), step.Value)
if e != nil {
return tasks.Scripts{}, e
}
errs.Add(task.Validate())
script.Tasks = append(script.Tasks, task)
}
} else {
errs.Add(fmt.Errorf("script failed to run. input YAML is malformed"))
}
scripts = append(scripts, script)
}
err = ValidateScripts(scripts)
errs.Add(err)
return scripts, errs.ToError()
}
func (p Builder) render(templateData []byte, variables map[string]interface{}) (result []byte, err error) {
templ := template.New("goyaml")
pageTemplate, err := templ.Parse(string(templateData))
if err != nil {
return result, err
}
buf := bytes.Buffer{}
err = pageTemplate.Execute(&buf, variables)
return buf.Bytes(), err
}