Completed
Branch development (67b918)
by Marc
02:48
created

Ansible::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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