forked from eclipse-xpanse/xpanse-agent
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun_playbook.go
117 lines (105 loc) · 3.32 KB
/
run_playbook.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
/*
* SPDX-License-Identifier: Apache-2.0
* SPDX-FileCopyrightText: Huawei Inc.
*/
package ansible
import (
"bytes"
"context"
"fmt"
"github.com/apenella/go-ansible/v2/pkg/execute"
results "github.com/apenella/go-ansible/v2/pkg/execute/result/json"
"github.com/apenella/go-ansible/v2/pkg/execute/stdoutcallback"
"github.com/apenella/go-ansible/v2/pkg/playbook"
"io"
"xpanse-agent/pkg/git"
"xpanse-agent/pkg/logger"
)
func RunPlaybook(playbookName string,
extraVars map[string]interface{},
inventory *map[string]interface{},
virtualEnvRootDir string,
pythonVersion string,
manageVirtualEnv bool,
requirementsFileNameInRepo string,
galaxyFile string) (*results.AnsiblePlaybookJSONResults, error) {
var res *results.AnsiblePlaybookJSONResults
var err error
buff := new(bytes.Buffer)
buffError := new(bytes.Buffer)
var inventoryFileName string
var usedVirtualEnvVar = GetVirtualEnvRootDirectory(virtualEnvRootDir)
if manageVirtualEnv {
logger.Logger.Info("preparing virtual environment in " + usedVirtualEnvVar)
err = createVirtualEnv(usedVirtualEnvVar, pythonVersion, requirementsFileNameInRepo)
if err != nil {
return nil, err
}
}
logger.Logger.Info("Running ansible task using ansible installed in venv " + usedVirtualEnvVar)
if inventory != nil {
inventoryFile, err := createInventoryFile(inventory)
if err != nil {
return nil, err
}
inventoryFileName = inventoryFile.Name()
} else {
inventoryFileName = ""
}
err = installGalaxyDependencies(galaxyFile, virtualEnvRootDir)
if err != nil {
return nil, err
}
ansiblePlaybookOptions := &playbook.AnsiblePlaybookOptions{
Become: true,
Inventory: inventoryFileName,
ExtraVars: extraVars,
}
// constructs the ansible command to be executed.
playbookCmd := playbook.NewAnsiblePlaybookCmd(
playbook.WithPlaybooks(playbookName),
playbook.WithPlaybookOptions(ansiblePlaybookOptions),
playbook.WithBinary(fmt.Sprintf("%s/bin/ansible-playbook", usedVirtualEnvVar)),
)
// execute the ansible command constructed above.
exec := stdoutcallback.NewJSONStdoutCallbackExecute(
execute.NewDefaultExecute(
execute.WithCmd(playbookCmd),
execute.WithCmdRunDir(git.GetRepoDirectory()),
execute.WithErrorEnrich(playbook.NewAnsiblePlaybookErrorEnrich()),
execute.WithWrite(io.Writer(buff)),
execute.WithWriteError(io.Writer(buffError)),
),
)
err = exec.Execute(context.TODO())
if err != nil {
logger.Logger.Error(err.Error())
return nil, err
}
// all warnings from Ansible are written to stderr stream.
if buffError.Len() > 0 {
for _, line := range bytes.Split(buffError.Bytes(), []byte("\n")) {
if len(line) > 0 {
logger.Logger.Warn(string(line))
}
}
}
res, err = results.ParseJSONResultsStream(io.Reader(buff))
if err != nil {
logger.Logger.Error(err.Error())
return nil, err
}
parseAndLogAnsibleOutputForResults(res)
deleteInventoryFile(inventoryFileName)
return res, err
}
func parseAndLogAnsibleOutputForResults(ansibleOutput *results.AnsiblePlaybookJSONResults) {
for _, play := range ansibleOutput.Plays {
for _, task := range play.Tasks {
name := task.Task.Name
for host, result := range task.Hosts {
logger.Logger.Info("|" + host + "|" + play.Play.Name + "|" + name + "|" + fmt.Sprintf("%v", result.StdoutLines) + "|" + fmt.Sprintf("%t", result.Changed) + "|" + fmt.Sprintf("%t", result.Failed))
}
}
}
}