-
Notifications
You must be signed in to change notification settings - Fork 1
/
ansible.go
144 lines (125 loc) · 3.91 KB
/
ansible.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
package ansible
import (
"bufio"
"fmt"
"io"
"log"
"os/exec"
"syscall"
"github.com/ekara-platform/engine/component"
"github.com/ekara-platform/engine/util"
)
type (
//Manager executes an ansible playbook
Manager interface {
// Execute runs a playbook within a component
//
// Parameters:
// cr: the component holding the playbook to launch
// playbook: the name of the playbook to launch
// extraVars: the extra vars passed to the playbook
// envars: the environment variables set before launching the playbook
// data: the template context required to template a used component
//
Execute(cr component.UsableComponent, playbook string, extraVars ExtraVars, envars EnvVars) (int, error)
}
manager struct {
lC util.LaunchContext
componentManager component.Manager
}
)
//CreateAnsibleManager returns a new AnsibleManager, able to launch playbook
//holded by the given component manager
func CreateAnsibleManager(lC util.LaunchContext, componentManager component.Manager) Manager {
return &manager{
lC: lC,
componentManager: componentManager,
}
}
func (aM manager) Execute(uc component.UsableComponent, playbook string, extraVars ExtraVars, envars EnvVars) (int, error) {
ok, playBookPath := uc.ContainsFile(playbook)
if !ok {
return 0, fmt.Errorf("The component \"%s\" does not contains the playbook : %s", uc.Name(), playbook)
}
aM.lC.Log().Println("- - - - - - - - - - - - - - - - - - - - - - - - - - -")
aM.lC.Log().Println("* * * * * A N S I B L E - - P L A Y B O O K * * * * ")
aM.lC.Log().Println("- - - - - - - - - - - - - - - - - - - - - - - - - - -")
aM.lC.Log().Printf(util.LOG_STARTING_PLAYBOOK, playBookPath.RelativePath(), playBookPath.Component().RootPath())
aM.lC.Log().Println("- - - - - - - - - - - - - - - - - - - - - - - - - - -")
var args = []string{playbook}
modulePaths := aM.componentManager.ContainsDirectory(util.ComponentModuleFolder)
defer modulePaths.Release()
if modulePaths.Count() > 0 {
pathsStrings := modulePaths.JoinAbsolutePaths(":")
aM.lC.Log().Printf("Playbook modules directories: %s", pathsStrings)
args = append(args, "--module-path", pathsStrings)
} else {
aM.lC.Log().Printf("No playbook module")
}
inventoryPaths := aM.componentManager.ContainsDirectory(util.InventoryModuleFolder)
defer inventoryPaths.Release()
if inventoryPaths.Count() > 0 {
asArgs := inventoryPaths.PrefixPaths("-i")
aM.lC.Log().Printf("Playbook inventory directories: %s", inventoryPaths.JoinAbsolutePaths(":"))
for _, v := range asArgs {
if v == "-i" {
continue
}
}
args = append(args, asArgs...)
} else {
aM.lC.Log().Printf("No playbook inventory")
}
if extraVars.Bool {
aM.lC.Log().Printf("Playbook extra vars: %s", extraVars.String())
args = append(args, "--extra-vars", extraVars.String())
} else {
aM.lC.Log().Printf("No playbook extra-vars")
}
cmd := exec.Command("ansible-playbook", args...)
cmd.Dir = uc.RootPath()
cmd.Env = []string{}
for k, v := range envars.Content {
cmd.Env = append(cmd.Env, k+"="+v)
}
if len(cmd.Env) > 0 {
aM.lC.Log().Printf("Playbook environment vars: %s", cmd.Env)
} else {
aM.lC.Log().Printf("No playbook environment vars")
}
errReader, err := cmd.StderrPipe()
if err != nil {
return 0, err
}
logPipe(errReader, aM.lC.Log())
outReader, err := cmd.StdoutPipe()
if err != nil {
return 0, err
}
logPipe(outReader, aM.lC.Log())
err = cmd.Start()
if err != nil {
return 0, err
}
err = cmd.Wait()
if err != nil {
e, ok := err.(*exec.ExitError)
if ok {
s := e.Sys().(syscall.WaitStatus)
code := s.ExitStatus()
aM.lC.Log().Printf("Ansible returned error code : %v\n", ReturnedError(code))
return code, err
}
return 0, err
}
return 0, nil
}
// logPipe logs the given pipe, reader/closer on the given logger
func logPipe(rc io.ReadCloser, l *log.Logger) {
s := bufio.NewScanner(rc)
go func() {
for s.Scan() {
l.Printf("%s\n", s.Text())
}
}()
}