Skip to content

Commit bf7b503

Browse files
committed
refactor(be): extract Ansible to separate class
1 parent 3e559cc commit bf7b503

File tree

2 files changed

+130
-80
lines changed

2 files changed

+130
-80
lines changed

lib/AnsiblePlaybook.go

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package lib
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"github.com/ansible-semaphore/semaphore/db"
8+
"github.com/ansible-semaphore/semaphore/util"
9+
"os"
10+
"os/exec"
11+
"regexp"
12+
"strings"
13+
)
14+
15+
type AnsiblePlaybook struct {
16+
TemplateID int
17+
Logger Logger
18+
Repository db.Repository
19+
Environment db.Environment
20+
}
21+
22+
func (p AnsiblePlaybook) makeCmd(command string, args []string) *exec.Cmd {
23+
cmd := exec.Command(command, args...) //nolint: gas
24+
cmd.Dir = p.GetFullPath()
25+
p.setCmdEnvironment(cmd, p.Repository.SSHKey.GetSshCommand())
26+
return cmd
27+
}
28+
29+
func (p AnsiblePlaybook) runCmd(command string, args []string) error {
30+
cmd := p.makeCmd(command, args)
31+
p.Logger.LogCmd(cmd)
32+
return cmd.Run()
33+
}
34+
35+
func (p AnsiblePlaybook) GetHosts(args []string) (hosts []string, err error) {
36+
args = append(args, "--list-hosts")
37+
cmd := p.makeCmd("ansible-playbook", args)
38+
39+
var errb bytes.Buffer
40+
cmd.Stderr = &errb
41+
42+
out, err := cmd.Output()
43+
if err != nil {
44+
return
45+
}
46+
47+
re := regexp.MustCompile(`(?m)^\\s{6}(.*)$`)
48+
matches := re.FindAllSubmatch(out, 20)
49+
hosts = make([]string, len(matches))
50+
for i := range matches {
51+
hosts[i] = string(matches[i][1])
52+
}
53+
54+
return
55+
}
56+
57+
func (p AnsiblePlaybook) Run(args []string, process chan *os.Process) error {
58+
cmd := p.makeCmd("ansible-playbook", args)
59+
p.Logger.LogCmd(cmd)
60+
cmd.Stdin = strings.NewReader("")
61+
err := cmd.Start()
62+
if err != nil {
63+
return err
64+
}
65+
process <- cmd.Process
66+
return cmd.Wait()
67+
}
68+
69+
func (p AnsiblePlaybook) RunGalaxy(args []string) error {
70+
return p.runCmd("ansible-galaxy", args)
71+
}
72+
73+
func (p AnsiblePlaybook) GetFullPath() (path string) {
74+
path = p.Repository.GetFullPath(p.TemplateID)
75+
return
76+
}
77+
78+
func (p AnsiblePlaybook) setCmdEnvironment(cmd *exec.Cmd, gitSSHCommand string) {
79+
env := os.Environ()
80+
env = append(env, fmt.Sprintf("HOME=%s", util.Config.TmpPath))
81+
env = append(env, fmt.Sprintf("PWD=%s", cmd.Dir))
82+
env = append(env, fmt.Sprintln("PYTHONUNBUFFERED=1"))
83+
env = append(env, fmt.Sprintln("GIT_TERMINAL_PROMPT=0"))
84+
env = append(env, extractCommandEnvironment(p.Environment.JSON)...)
85+
86+
if gitSSHCommand != "" {
87+
env = append(env, fmt.Sprintf("GIT_SSH_COMMAND=%s", gitSSHCommand))
88+
}
89+
cmd.Env = env
90+
}
91+
92+
func extractCommandEnvironment(envJSON string) []string {
93+
env := make([]string, 0)
94+
var js map[string]interface{}
95+
err := json.Unmarshal([]byte(envJSON), &js)
96+
if err == nil {
97+
if cfg, ok := js["ENV"]; ok {
98+
switch v := cfg.(type) {
99+
case map[string]interface{}:
100+
for key, val := range v {
101+
env = append(env, fmt.Sprintf("%s=%s", key, val))
102+
}
103+
}
104+
}
105+
}
106+
return env
107+
}

services/tasks/runner.go

+23-80
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
package tasks
22

33
import (
4-
"bytes"
54
"crypto/md5"
65
"encoding/json"
76
"fmt"
87
"github.com/ansible-semaphore/semaphore/lib"
98
"io"
109
"io/ioutil"
1110
"os"
12-
"os/exec"
13-
"regexp"
1411
"strconv"
1512
"strings"
1613
"time"
@@ -257,10 +254,8 @@ func (t *TaskRunner) prepareRun() {
257254
return
258255
}
259256

260-
// todo: write environment
261-
262-
if stderr, err := t.listPlaybookHosts(); err != nil {
263-
t.Log("Listing playbook hosts failed: " + err.Error() + "\n" + stderr)
257+
if err := t.listPlaybookHosts(); err != nil {
258+
t.Log("Listing playbook hosts failed: " + err.Error())
264259
t.fail()
265260
return
266261
}
@@ -546,64 +541,45 @@ func (t *TaskRunner) installRequirements() error {
546541
}
547542

548543
func (t *TaskRunner) runGalaxy(args []string) error {
549-
cmd := exec.Command("ansible-galaxy", args...) //nolint: gas
550-
cmd.Dir = t.getRepoPath()
551-
552-
t.setCmdEnvironment(cmd, t.repository.SSHKey.GetSshCommand())
553-
554-
t.LogCmd(cmd)
555-
return cmd.Run()
544+
return lib.AnsiblePlaybook{
545+
Logger: t,
546+
TemplateID: t.template.ID,
547+
Repository: t.repository,
548+
}.RunGalaxy(args)
556549
}
557550

558-
func (t *TaskRunner) listPlaybookHosts() (string, error) {
559-
551+
func (t *TaskRunner) listPlaybookHosts() (err error) {
560552
if util.Config.ConcurrencyMode == "project" {
561-
return "", nil
553+
return
562554
}
563555

564556
args, err := t.getPlaybookArgs()
565557
if err != nil {
566-
return "", err
558+
return
567559
}
568-
args = append(args, "--list-hosts")
569-
570-
cmd := exec.Command("ansible-playbook", args...) //nolint: gas
571-
cmd.Dir = t.getRepoPath()
572-
t.setCmdEnvironment(cmd, "")
573560

574-
var errb bytes.Buffer
575-
cmd.Stderr = &errb
576-
577-
out, err := cmd.Output()
561+
t.hosts, err = lib.AnsiblePlaybook{
562+
Logger: t,
563+
TemplateID: t.template.ID,
564+
Repository: t.repository,
565+
}.GetHosts(args)
578566

579-
re := regexp.MustCompile(`(?m)^\\s{6}(.*)$`)
580-
matches := re.FindAllSubmatch(out, 20)
581-
hosts := make([]string, len(matches))
582-
for i := range matches {
583-
hosts[i] = string(matches[i][1])
584-
}
585-
t.hosts = hosts
586-
return errb.String(), err
567+
return
587568
}
588569

589570
func (t *TaskRunner) runPlaybook() (err error) {
590571
args, err := t.getPlaybookArgs()
591572
if err != nil {
592573
return
593574
}
594-
cmd := exec.Command("ansible-playbook", args...) //nolint: gas
595-
cmd.Dir = t.getRepoPath()
596-
t.setCmdEnvironment(cmd, "")
597575

598-
t.LogCmd(cmd)
599-
cmd.Stdin = strings.NewReader("")
600-
err = cmd.Start()
601-
if err != nil {
602-
return
603-
}
604-
t.process = cmd.Process
605-
err = cmd.Wait()
606-
return
576+
process := make(chan *os.Process)
577+
t.process = <-process
578+
return lib.AnsiblePlaybook{
579+
Logger: t,
580+
TemplateID: t.template.ID,
581+
Repository: t.repository,
582+
}.Run(args, process)
607583
}
608584

609585
func (t *TaskRunner) getExtraVars() (str string, err error) {
@@ -746,20 +722,6 @@ func (t *TaskRunner) getPlaybookArgs() (args []string, err error) {
746722
return
747723
}
748724

749-
func (t *TaskRunner) setCmdEnvironment(cmd *exec.Cmd, gitSSHCommand string) {
750-
env := os.Environ()
751-
env = append(env, fmt.Sprintf("HOME=%s", util.Config.TmpPath))
752-
env = append(env, fmt.Sprintf("PWD=%s", cmd.Dir))
753-
env = append(env, fmt.Sprintln("PYTHONUNBUFFERED=1"))
754-
env = append(env, fmt.Sprintln("GIT_TERMINAL_PROMPT=0"))
755-
env = append(env, extractCommandEnvironment(t.environment.JSON)...)
756-
757-
if gitSSHCommand != "" {
758-
env = append(env, fmt.Sprintf("GIT_SSH_COMMAND=%s", gitSSHCommand))
759-
}
760-
cmd.Env = env
761-
}
762-
763725
func hasRequirementsChanges(requirementsFilePath string, requirementsHashFilePath string) bool {
764726
oldFileMD5HashBytes, err := ioutil.ReadFile(requirementsHashFilePath)
765727
if err != nil {
@@ -783,25 +745,6 @@ func writeMD5Hash(requirementsFile string, requirementsHashFile string) error {
783745
return ioutil.WriteFile(requirementsHashFile, []byte(newFileMD5Hash), 0644)
784746
}
785747

786-
// extractCommandEnvironment unmarshalls a json string, extracts the ENV key from it and returns it as
787-
// []string where strings are in key=value format
788-
func extractCommandEnvironment(envJSON string) []string {
789-
env := make([]string, 0)
790-
var js map[string]interface{}
791-
err := json.Unmarshal([]byte(envJSON), &js)
792-
if err == nil {
793-
if cfg, ok := js["ENV"]; ok {
794-
switch v := cfg.(type) {
795-
case map[string]interface{}:
796-
for key, val := range v {
797-
env = append(env, fmt.Sprintf("%s=%s", key, val))
798-
}
799-
}
800-
}
801-
}
802-
return env
803-
}
804-
805748
// checkTmpDir checks to see if the temporary directory exists
806749
// and if it does not attempts to create it
807750
func checkTmpDir(path string) error {

0 commit comments

Comments
 (0)