Test Failed
Branch feature__set_up_scrutinizer (ea6624)
by Robin
06:04 queued 02:46
created

Porter::restartServing()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 2.0023

Importance

Changes 0
Metric Value
eloc 11
dl 0
loc 20
ccs 11
cts 12
cp 0.9167
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2.0023
1
<?php
2
3
namespace App;
4
5
use App\Models\PhpVersion;
6
use App\Models\Setting;
7
use App\Support\Console\DockerCompose\CliCommandFactory;
8
use App\Support\Console\DockerCompose\YamlBuilder;
9
use App\Support\Contracts\Cli;
10
use App\Support\Contracts\ImageRepository;
11
use App\Support\Contracts\ImageSetRepository;
12
use App\Support\Images\Image;
13
14
class Porter
15
{
16
    /**
17
     * The docker images sets used by Porter to serve sites.
18
     *
19
     * @var ImageSetRepository
20
     */
21
    protected $imageSets;
22
23
    /**
24
     * The CLI class that executes commands.
25
     *
26
     * @var Cli
27
     */
28
    protected $cli;
29
30
    /**
31
     * The Docker composer command factory.
32
     *
33
     * @var CliCommandFactory
34
     */
35
    protected $dockerCompose;
36
37
    /**
38
     * The DockerCompose YAML file builder
39
     *
40
     * @var YamlBuilder
41
     */
42
    protected $yamlBuilder;
43
44
    /**
45
     * Porter constructor.
46
     *
47
     * @param ImageSetRepository $imageSets
48
     * @param Cli                $cli
49
     * @param CliCommandFactory  $commandFactory
50
     * @param YamlBuilder        $yamlBuilder
51
     */
52 50
    public function __construct(
53
        ImageSetRepository $imageSets,
54
        Cli $cli,
55
        CliCommandFactory $commandFactory,
56
        YamlBuilder $yamlBuilder
57
    ) {
58 50
        $this->imageSets = $imageSets;
59 50
        $this->cli = $cli;
60 50
        $this->dockerCompose = $commandFactory;
61 50
        $this->yamlBuilder = $yamlBuilder;
62 50
    }
63
64
    /**
65
     * Check if the Porter containers are running
66
     *
67
     * @param string|null $service
68
     * @return bool
69
     */
70 5
    public function isUp($service = null)
71
    {
72 5
        return (bool) stristr($this->dockerCompose->command('ps')->perform(), "porter_{$service}");
73
    }
74
75
    /**
76
     * Create the docker-compose.yaml file
77
     */
78 4
    public function compose()
79
    {
80 4
        $this->yamlBuilder->build($this->getDockerImageSet());
81 4
    }
82
83
    /**
84
     * Start Porter containers, optionally start a specific service, and force them to be recreated
85
     *
86
     * @param string|null $service
87
     * @param bool $recreate
88
     */
89 4
    public function start($service = null, $recreate = false)
90
    {
91 4
        $recreate = $recreate ? '--force-recreate ' : '';
92
93 4
        $this->dockerCompose->command("up -d {$recreate}--remove-orphans {$service}")->realTime()->perform();
94 4
    }
95
96
    /**
97
     * Stop Porter containers
98
     *
99
     * @param string|null $service
100
     */
101 2
    public function stop($service = null)
102
    {
103 2
        if ($service) {
104 1
            $this->dockerCompose->command("stop {$service}")->realTime()->perform();
105
106 1
            return;
107
        }
108
109 1
        $this->dockerCompose->command("down --remove-orphans")->realTime()->perform();
110 1
    }
111
112
    /**
113
     * Restart Porter containers
114
     *
115
     * @param string|null $service
116
     */
117 2
    public function restart($service = null)
118
    {
119 2
        if ($this->isUp($service)) {
120
            $this->stop($service);
121
        }
122
123
        // If we're restarting something it's probably because config changed - so force recreation
124 2
        $this->start($service, true);
125 2
    }
126
127
    /**
128
     * Restart serving, picking up changes in used PHP versions and NGiNX
129
     */
130 1
    public function restartServing()
131
    {
132
        // Build up docker-compose again - so we pick up any new PHP containers to be used
133 1
        $this->compose();
134
135 1
        if (! $this->isUp()) {
136
            return;
137
        }
138
139 1
        PhpVersion::active()
140 1
            ->get()
141
            ->reject(function ($phpVersion) {
142 1
                return $this->isUp($phpVersion->fpm_name);
143 1
            })
144
            ->each(function ($phpVersion) {
145 1
                $this->start($phpVersion->fpm_name);
146 1
                $this->start($phpVersion->cli_name);
147 1
            });
148
149 1
        $this->restart('nginx');
150 1
    }
151
152
    /**
153
     * Turn a service on
154
     *
155
     * @param string $service
156
     */
157 2
    public function turnOnService($service)
158
    {
159 2
        if (setting("use_{$service}") == 'on') {
160 1
            return;
161
        }
162
163 1
        Setting::updateOrCreate("use_{$service}", 'on');
164
165 1
        $this->compose();
166
167 1
        if ($this->isUp()) {
168 1
            $this->start($service);
169
        }
170 1
    }
171
172
    /**
173
     * Turn a service off
174
     *
175
     * @param string $service
176
     */
177 2
    public function turnOffService($service)
178
    {
179 2
        if (in_array(setting("use_{$service}"), [null, 'off'])) {
180 1
            return;
181
        }
182
183 1
        Setting::updateOrCreate("use_{$service}", 'off');
184
185 1
        if ($this->isUp()) {
186 1
            $this->stop($service);
187
        }
188 1
        $this->compose();
189 1
    }
190
191
    /**
192
     * (Re)build Porter containers
193
     */
194 1
    public function build()
195
    {
196 1
        $this->dockerCompose->command('build')->perform();
197 1
    }
198
199
    /**
200
     * Build the current images
201
     */
202
    public function buildImages()
203
    {
204
        foreach ($this->getDockerImageSet()->firstParty() as $image) {
205
            $this->cli->passthru("docker build -t {$image->name} --rm {$image->localPath} --");
206
        }
207
    }
208
209
    /**
210
     * Push the current images
211
     */
212 1
    public function pushImages()
213
    {
214 1
        foreach ($this->getDockerImageSet()->firstParty() as $image) {
215 1
            $this->cli->passthru("docker push {$image->name}");
216
        }
217 1
    }
218
219
    /**
220
     * Pull our docker images
221
     */
222 1
    public function pullImages()
223
    {
224 1
        foreach ($this->getDockerImageSet()->all() as $image) {
225 1
            if (running_tests() && $this->hasImage($image)) {
226
                continue;
227
            }
228
229 1
            $this->cli->passthru("docker pull {$image->name}");
230
        }
231 1
    }
232
233
    /**
234
     * Check if we already have the image
235
     *
236
     * @param Image $image
237
     * @return bool
238
     */
239 1
    public function hasImage(Image $image)
240
    {
241 1
        $output = $this->cli->exec("docker image inspect {$image->name}");
0 ignored issues
show
Bug Best Practice introduced by
The property $name is declared protected in App\Support\Images\Image. Since you implement __get, consider adding a @property or @property-read.
Loading history...
242
243 1
        return strpos($output, "Error: No such image: {$image->name}") === false;
244
    }
245
246
    /**
247
     * Get the current image set to use.
248
     *
249
     * @return ImageRepository
250
     */
251 6
    public function getDockerImageSet()
252
    {
253 6
        return $this->imageSets->getImageRepository(
254 6
            setting('docker_image_set', config('porter.default-docker-image-set'))
255
        );
256
    }
257
258
    /**
259
     * Show container status
260
     */
261 1
    public function status()
262
    {
263 1
        echo $this->dockerCompose->command('ps')->perform();
264 1
    }
265
266
    /**
267
     * Show container logs
268
     *
269
     * @param string|null $service
270
     */
271 1
    public function logs($service = null)
272
    {
273 1
        echo $this->dockerCompose->command("logs {$service}")->perform();
274 1
    }
275
}
276