-
Notifications
You must be signed in to change notification settings - Fork 0
/
preparer.go
123 lines (112 loc) · 3.54 KB
/
preparer.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
package ops
import (
"fmt"
"github.com/jevi061/ops/internal/connector"
"github.com/jevi061/ops/internal/transfer"
)
type Preparer interface {
Prepare(*Opsfile)
}
type connectorPreparer struct {
}
type connectorTaskPreparer struct {
preparedExpandableTask map[string]int
}
func (p *connectorPreparer) Prepare(conf *Opsfile, tag string) []connector.Connector {
localConnector := connector.NewLocalConnector()
if conf.Servers != nil && len(conf.Servers.Names) > 0 {
selectedServers := make([]*Server, 0)
if tag == "" {
for _, v := range conf.Servers.Names {
selectedServers = append(selectedServers, v)
}
} else {
for _, v := range conf.Servers.Names {
for _, t := range v.Tags {
if t == tag {
selectedServers = append(selectedServers, v)
}
}
}
}
connectors := make([]connector.Connector, len(selectedServers))
for i, c := range selectedServers {
connectors[i] = connector.NewSSHConnector(c.Host,
connector.WithPort(c.Port), connector.WithUser(c.User), connector.WithPassword(c.Password))
}
return append(connectors, localConnector)
}
return []connector.Connector{localConnector}
}
func (p *connectorTaskPreparer) Prepare(conf *Opsfile, tasks ...string) ([]connector.Task, error) {
p.preparedExpandableTask = make(map[string]int)
connectorTasks := make([]connector.Task, 0)
for _, taskName := range tasks {
if runs, err := p.PrepareTask(conf, taskName); err != nil {
return nil, err
} else {
connectorTasks = append(connectorTasks, runs...)
}
}
return connectorTasks, nil
}
func (p *connectorTaskPreparer) PrepareTask(conf *Opsfile, taskName string) ([]connector.Task, error) {
tasks := make([]connector.Task, 0)
// valid task
if task, ok := conf.Tasks.Names[taskName]; ok {
// deps
if len(task.Deps) > 0 {
p.preparedExpandableTask[taskName]++
for _, depTaskName := range task.Deps {
if p.preparedExpandableTask[taskName] > 1 && len(conf.Tasks.Names[depTaskName].Deps) > 0 {
return nil, fmt.Errorf("ParseTaskError: found circular task node: %s", depTaskName)
}
if depTaskRuns, err := p.Prepare(conf, depTaskName); err != nil {
return nil, err
} else {
tasks = append(tasks, depTaskRuns...)
}
}
}
// task itself
mergedEnvs := mergeEnvs(conf.Environments.Envs, task.Envs)
if task.Transfer != "" { // upload task
absSrc, dest, err := transfer.ParseTransferWithEnvs(task.Transfer, mergedEnvs)
if err != nil {
return nil, fmt.Errorf("invalid task: %s : %w", task.Name, err)
}
// build cmd
cmd := fmt.Sprintf(`tar -C %s -xvzf - `, dest)
stdin := transfer.PipeFile(absSrc)
t := connector.NewCommonTask(connector.WithName(task.Name),
connector.WithDesc(task.Desc),
connector.WithShell(conf.Shell),
connector.WithCommand(cmd),
connector.WithEnvironments(mergedEnvs),
connector.WithLocal(false),
connector.WithStdin(stdin))
tasks = append(tasks, t)
} else {
t := connector.NewCommonTask(connector.WithName(task.Name),
connector.WithDesc(task.Desc),
connector.WithShell(conf.Shell),
connector.WithCommand(task.Cmd),
connector.WithEnvironments(mergedEnvs),
connector.WithLocal(task.Local))
tasks = append(tasks, t)
}
} else { // invalid task
return nil, &ParseError{target: taskName, Err: fmt.Errorf("%s is not a valid task", taskName)}
}
return tasks, nil
}
func mergeEnvs(base, special map[string]string) map[string]string {
merged := make(map[string]string, len(base)+len(special))
for k, v := range base {
merged[k] = v
}
for k, v := range special {
merged[k] = v
}
return merged
}