Completed
Pull Request — master (#21)
by Christian
02:46
created

Ansible::checkCommand()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.9256

Importance

Changes 5
Bugs 1 Features 2
Metric Value
cc 5
eloc 12
c 5
b 1
f 2
nc 5
nop 2
dl 0
loc 20
ccs 8
cts 12
cp 0.6667
crap 5.9256
rs 8.8571
1
<?php
2
/*
3
 * This file is part of the php-ansible package.
4
 *
5
 * (c) Marc Aschmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Asm\Ansible;
12
13
use Asm\Ansible\Command\AnsibleGalaxy;
14
use Asm\Ansible\Command\AnsibleGalaxyInterface;
15
use Asm\Ansible\Command\AnsiblePlaybook;
16
use Asm\Ansible\Command\AnsiblePlaybookInterface;
17
use Asm\Ansible\Exception\CommandException;
18
use Symfony\Component\Process\ProcessBuilder;
19
20
/**
21
 * Ansible command factory
22
 *
23
 * @package Asm\Ansible
24
 * @author Marc Aschmann <[email protected]>
25
 */
26
final class Ansible
27
{
28
29
    const DEFAULT_TIMEOUT = 300;
30
31
    /**
32
     * @var string
33
     */
34
    private $playbookCommand;
35
36
    /**
37
     * @var string
38
     */
39
    private $galaxyCommand;
40
41
    /**
42
     * @var string
43
     */
44
    private $ansibleBaseDir;
45
46
    /**
47
     * @var integer
48
     */
49
    private $timeout;
50
51
    /**
52
     * @param string $ansibleBaseDir base directory of ansible project structure
53
     * @param string $playbookCommand path to playbook executable, default ansible-playbook
54
     * @param string $galaxyCommand path to galaxy executable, default ansible-galaxy
55
     * @throws CommandException
56
     */
57 7
    public function __construct(
58
        $ansibleBaseDir,
59
        $playbookCommand = '',
60
        $galaxyCommand = ''
61
    ) {
62 7
        $this->ansibleBaseDir = $this->checkDir($ansibleBaseDir);
63 5
        $this->playbookCommand = $this->checkCommand($playbookCommand, 'ansible-playbook');
64 3
        $this->galaxyCommand = $this->checkCommand($galaxyCommand, 'ansible-galaxy');
65
66 3
        $this->timeout = Ansible::DEFAULT_TIMEOUT;
67 3
    }
68
69
    /**
70
     * AnsiblePlaybook instance creator
71
     *
72
     * @return AnsiblePlaybookInterface
73
     */
74 1
    public function playbook()
75
    {
76 1
        return new AnsiblePlaybook(
77 1
            $this->createProcess($this->playbookCommand)
78 1
        );
79
    }
80
81
    /**
82
     * AnsibleGalaxy instance creator
83
     *
84
     * @return AnsibleGalaxyInterface
85
     */
86 1
    public function galaxy()
87
    {
88 1
        return new AnsibleGalaxy(
89 1
            $this->createProcess($this->galaxyCommand)
90 1
        );
91
    }
92
93
    /**
94
     * Set process timeout in seconds.
95
     *
96
     * @param integer $timeout
97
     * @return $this
98
     */
99
    public function setTimeout($timeout)
100
    {
101
        $this->timeout = $timeout;
102
103
        return $this;
104
    }
105
106
    /**
107
     * @param string $prefix command to execute
108
     * @return ProcessBuilder
109
     */
110 2
    private function createProcess($prefix)
111
    {
112 2
        $process = new ProcessBuilder();
113
114
        return $process
115 2
            ->setPrefix($prefix)
116 2
            ->setWorkingDirectory($this->ansibleBaseDir)
117 2
            ->setTimeout($this->timeout);
118
    }
119
120
    /**
121
     * @param string $command
122
     * @param string $default
123
     * @return string
124
     * @throws CommandException
125
     */
126 5
    private function checkCommand($command, $default)
127
    {
128
        // normally ansible is in /usr/local/bin/*
129 5
        if ('' === $command) {
130 1
            if (true === shell_exec('which ' . $default)) {
131
                $command = $default;
132
            } else { // not testable without ansible installation
133 1
                throw new CommandException('No ' . $default . ' executable present in PATH!');
134
            }
135
        } else {
136 4
            if (!is_file($command)) {
137 1
                throw new CommandException('Command ' . $command . ' does not exist!');
138
            }
139 3
            if (!is_executable($command)) {
140
                throw new CommandException('Command ' . $command . ' is not executable!');
141
            }
142
        }
143
144 3
        return $command;
145
    }
146
147
    /**
148
     * @param string $dir directory to check
149
     * @return string
150
     * @throws CommandException
151
     */
152 7
    private function checkDir($dir)
153
    {
154 7
        if (!is_dir($dir)) {
155 2
            throw new CommandException('Ansible project root ' . $dir . ' not found!');
156
        }
157
158 5
        return $dir;
159
    }
160
}
161