Completed
Pull Request — master (#17)
by Tobias
03:11
created

ComposeManager::ips()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 10
Ratio 100 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 10
loc 10
rs 9.4285
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
3
namespace DockerCompose\Manager;
4
5
use DockerCompose\Exception\ComposeFileNotFoundException;
6
use DockerCompose\Exception\DockerHostConnexionErrorException;
7
use DockerCompose\Exception\DockerInstallationMissingException;
8
use DockerCompose\Exception\NoSuchServiceException;
9
use DockerCompose\ComposeFileCollection;
10
use mikehaertl\shellcommand\Command;
11
use Exception;
12
13
/**
14
 * DockerCompose\Manager\ComposeManager
15
 */
16
class ComposeManager
17
{
18
19
    /**
20
     * @var array environment variables for command
21
     */
22
    public $env = [];
23
24
    /**
25
     * @var array environment variables for command
26
     */
27
    public $cwd = null;
28
29
    /**
30
     * Start service containers
31
     *
32
     * @param mixed $composeFiles The compose files names
33
     */
34
    public function start($composeFiles = array())
35
    {
36
        return $this->processResult(
37
            $this->execute(
38
                $this->formatCommand('up -d', $this->createComposeFileCollection($composeFiles))
39
            )
40
        );
41
    }
42
43
    /**
44
     * Stop service containers
45
     *
46
     * @param mixed $composeFiles The compose files names
47
     */
48
    public function stop($composeFiles = array())
49
    {
50
        return $this->processResult(
51
            $this->execute(
52
                $this->formatCommand('stop', $this->createComposeFileCollection($composeFiles))
53
            )
54
        );
55
    }
56
57
    /**
58
     * Stop service containers
59
     *
60
     * @param mixed   $composeFiles  The compose files names
61
     * @param boolean $force         If the remove need to be force (default=false)
62
     * @param boolean $removeVolumes If we need to remove the volumes (default=false)
63
     */
64
    public function remove($composeFiles = array(), $force = false, $removeVolumes = false)
0 ignored issues
show
Unused Code introduced by
The parameter $force is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
65
    {
66
        $command = 'rm --force';
67
68
        if ($removeVolumes) {
69
            $command .= ' -v';
70
        }
71
72
        return $this->processResult(
73
            $this->execute(
74
                $this->formatCommand($command, $this->createComposeFileCollection($composeFiles))
75
            )
76
        );
77
    }
78
79
     /**
80
     * Stop service containers
81
     *
82
     * @param mixed   $composeFiles  The compose files names
83
     * @param string  $signal        Optionnal to precise SIGNAL to send to the container for SIGKILL replacement.
84
     */
85 View Code Duplication
    public function kill($composeFiles = array(), $signal = 'SIGKILL')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
    {
87
        $command = 'kill';
88
89
        if ($signal !== 'SIGKILL') {
90
            $command .= ' -s ' . $signal;
91
        }
92
93
        return $this->processResult(
94
            $this->execute(
95
                $this->formatCommand($command, $this->createComposeFileCollection($composeFiles))
96
            )
97
        );
98
    }
99
100
    /**
101
     * Build service images
102
     *
103
     * @param mixed   $composeFiles  The compose files names
104
     * @param boolean $pull          If we want attempt to pull a newer version of the from image
105
     * @param boolean $forceRemove   If we want remove the intermediate containers
106
     * @param bollean $cache         If we can use the cache when building the image
107
     */
108
    public function build($composeFiles = array(), $pull = true, $forceRemove = false, $cache = true)
109
    {
110
        $command = 'build';
111
112
        if ($pull) {
113
            $command .= ' --pull';
114
        }
115
116
        if ($forceRemove) {
117
            $command .= ' --force-rm';
118
        }
119
120
        if (!$cache) {
121
            $command .= ' --no-cache';
122
        }
123
124
        return $this->processResult(
125
            $this->execute(
126
                $this->formatCommand($command, $this->createComposeFileCollection($composeFiles))
127
            )
128
        );
129
    }
130
131
    /**
132
     * Pull service images
133
     *
134
     * @param mixed   $composeFiles  The compose files names
135
     */
136
    public function pull($composeFiles = array())
137
    {
138
        $command = 'pull';
139
140
        return $this->processResult(
141
            $this->execute(
142
                $this->formatCommand($command, $this->createComposeFileCollection($composeFiles))
143
            )
144
        );
145
    }
146
147
148
    /**
149
     * Restart running containers
150
     *
151
     * @param mixed   $composeFiles  The compose files names
152
     * @param integer $timeout       If we want attempt to pull a newer version of the from image
153
     */
154 View Code Duplication
    public function restart($composeFiles = array(), $timeout = 10)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155
    {
156
        $command = 'restart';
157
158
        if ($timeout != 10) {
159
            $command .= ' --timeout='.$timeout;
160
        }
161
162
        return $this->processResult(
163
            $this->execute(
164
                $this->formatCommand($command, $this->createComposeFileCollection($composeFiles))
165
            )
166
        );
167
    }
168
169
    /**
170
     * Run service with command
171
     *
172
     * @param string $service Service name
173
     * @param string $command Command to pass to service
174
     * @param mixed   $composeFiles  The compose files names
175
     */
176
    public function run($service, $command, $composeFiles = array())
177
    {
178
        $command = 'run --rm ' . $service . ' ' . $command;
179
        $result = $this->execute(
180
            $this->formatCommand($command, $this->createComposeFileCollection($composeFiles))
181
        );
182
183
        if ($result['code'] == 1 && strpos($result['output'], 'service') != false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing strpos($result['output'], 'service') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
184
            throw new NoSuchServiceException($result['output']);
185
        }
186
187
        return $this->processResult($result);
188
    }
189
190
    /**
191
     * List containers
192
     *
193
     * @param mixed $composeFiles The compose files names
194
     */
195
    public function ps($composeFiles = array())
196
    {
197
        return $this->processResult(
198
            $this->execute(
199
                $this->formatCommand('ps', $this->createComposeFileCollection($composeFiles))
200
            )
201
        );
202
    }
203
204
    /**
205
     * Show configuration (yaml)
206
     *
207
     * @param mixed $composeFiles The compose files names
208
     */
209
    public function config($composeFiles = array())
210
    {
211
        return $this->processResult(
212
            $this->execute(
213
                $this->formatCommand('config', $this->createComposeFileCollection($composeFiles))
214
            )
215
        );
216
    }
217
218
    /**
219
     * List IP containers
220
     *
221
     * @param mixed $composeFiles The compose files names
222
     */
223 View Code Duplication
    public function ips($composeFiles = array())
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
224
    {
225
        $command = $this->formatCommand('ps', $this->createComposeFileCollection($composeFiles));
226
227
        $command = 'for CONTAINER in $(' . $command . ' -q); ';
228
        $command .= 'do echo "$(docker inspect --format \' {{ .Name }} \' $CONTAINER)\t';
229
        $command .= '$(docker inspect --format \' {{ .NetworkSettings.IPAddress }} \' $CONTAINER)"; done';
230
231
        return $this->processResult($this->execute($command));
0 ignored issues
show
Documentation introduced by
$command is of type string, but the function expects a object<mikehaertl\shellcommand\Command>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
232
    }
233
234
    /**
235
     * Process result with returned code and output
236
     *
237
     * @param array $result The result of command with output and returnCode
238
     *
239
     * @throws DockerInstallationMissingException When returned code is 127
240
     * @throws ComposeFileNotFoundException When no compose file precise and docker-compose.yml not found
241
     * @throws DockerHostConnexionErrorException When we can't connect to docker host
242
     * @throws \Exception When an unknown error is returned
243
     */
244
    private function processResult($result)
245
    {
246
        if ($result['code'] === 127) {
247
            throw new DockerInstallationMissingException();
248
        }
249
250
        if ($result['code'] === 1) {
251
            if (!strpos($result['output'], 'DOCKER_HOST')) {
252
                if (!strpos($result['output'], 'docker-compose.yml')) {
253
                    throw new Exception($result['output']);
254
                } else {
255
                    throw new ComposeFileNotFoundException();
256
                }
257
            } else {
258
                throw new DockerHostConnexionErrorException();
259
            }
260
        }
261
262
        return $result['output'];
263
    }
264
265
    /**
266
     * Create the composeFileCollection from the type of value given
267
     *
268
     * @param mixed $composeFiles The docker-compose files (can be array, string or ComposeFile)
269
     *
270
     * @return ComposeFileCollection
271
     */
272
    private function createComposeFileCollection($composeFiles)
273
    {
274
        if (!$composeFiles instanceof ComposeFileCollection) {
275
            if (!is_array($composeFiles)) {
276
                return new ComposeFileCollection([$composeFiles]);
277
            } else {
278
                return new ComposeFileCollection($composeFiles);
279
            }
280
        } else {
281
            return $composeFiles;
282
        }
283
    }
284
285
    /**
286
     * Format the command to execute
287
     *
288
     * @param string                $subcommand   The subcommand to pass to docker-compose command
289
     * @param ComposeFileCollection $composeFiles The compose files to precise in the command
290
     */
291
    private function formatCommand($subcommand, ComposeFileCollection $composeFiles)
292
    {
293
        $command = new Command("docker-compose");
294
295
        # Set working directory
296
        if (!empty($this->cwd)) {
297
            $command->procCwd = $this->cwd;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->cwd of type array is incompatible with the declared type string|null of property $procCwd.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
298
        }
299
300
        # Set environment variables
301
        if (!empty($this->env)) {
302
            $command->procEnv = $this->env;
303
        }
304
305
        # Add files names
306
        foreach ($composeFiles->getAll() as $composeFile) {
307
            $command->addArg('-f', $composeFile->getFileName());
308
        }
309
310
        # Add project name
311
        if ($composeFiles->getProjectName() != null) {
312
            $command->addArg('--project-name', $composeFiles->getProjectName());
313
        }
314
315
        $command->addArg($subcommand);
316
317
        return $command;
318
    }
319
320
    /**
321
     * Execute docker-compose commande
322
     * @codeCoverageIgnore
323
     * @param Command $command The command to execute.
324
     */
325
    protected function execute($command)
326
    {
327
        if ($command->execute()) {
328
            $output = $command->getOutput();
329
        } else {
330
            $output = $command->getError();
331
        }
332
333
        return array(
334
            'output' => $output,
335
            'code' => $command->getExitCode()
336
        );
337
    }
338
}
339