Passed
Push — test ( 0b385b...4e7e0f )
by Tom
02:31
created

StepContainer::execRun()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 5
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 3
rs 10
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines\Runner;
6
7
use Ktomk\Pipelines\Cli\Docker;
8
use Ktomk\Pipelines\Cli\Exec;
9
use Ktomk\Pipelines\Cli\Streams;
10
use Ktomk\Pipelines\File\Pipeline\Step;
11
use Ktomk\Pipelines\Lib;
12
13
/**
14
 * Class StepContainer
15
 *
16
 * @package Ktomk\Pipelines\Runner
17
 */
18
class StepContainer
19
{
20
    /**
21
     * @var null|string id of the (running) container
22
     */
23
    private $id;
24
25
    /**
26
     * @var null|string name of the container
27
     */
28
    private $name;
29
30
    /**
31
     * @var Step
32
     */
33
    private $step;
34
35
    /**
36
     * @var Exec
37
     */
38
    private $exec;
39
40
    /**
41
     * @param Step $step
42
     * @param null|Exec $exec
43
     *
44
     * @return StepContainer
45
     */
46 6
    public static function create(Step $step, Exec $exec = null)
47
    {
48 6
        if (null === $exec) {
49 2
            $exec = new Exec();
50
        }
51
52 6
        return new self($step, $exec);
53
    }
54
55
    /**
56
     * @param Step $step
57
     * @param string $prefix
58
     * @param string $project name
59
     *
60
     * @return string
61
     */
62 1
    public static function createName(Step $step, $prefix, $project)
63
    {
64 1
        return self::create($step)->generateName($prefix, $project);
65
    }
66
67
    /**
68
     * kill and remove static implementation
69
     *
70
     * @param Exec $exec
71
     * @param string $idOrIds container id(s) or name(s)
72
     * @param bool $kill
73
     * @param bool $remove
74
     */
75 4
    public static function execKillAndRemove(Exec $exec, $idOrIds, $kill, $remove)
76
    {
77 4
        if ($kill) {
78 2
            Docker::create($exec)->getProcessManager()->kill($idOrIds);
79
        }
80
81 4
        if ($remove) {
82 3
            Docker::create($exec)->getProcessManager()->remove($idOrIds);
83
        }
84 4
    }
85
86
    /**
87
     * @param Exec $exec
88
     * @param array $args
89
     *
90
     * @return array array(int $status, string $out, string $err, string|null $id)
91
     */
92 4
    public static function execRun(Exec $exec, array $args)
93
    {
94 4
        $status = $exec->capture('docker', Lib::merge('run', $args), $out, $err);
95
96 4
        $id = null;
97 4
        if (0 === $status) {
98 4
            $id = rtrim($out) ?: null;
99
        }
100
101 4
        return array($status, $out, $err, $id);
102
    }
103
104
    /**
105
     * @param Exec $exec
106
     * @param Streams $streams
107
     * @param string|string[] $idOrIds
108
     * @param int $status
109
     * @param Flags $flags
110
     * @param string $message
111
     * @param string $id
112
     *
113
     * @see StepRunner::shutdownStepContainer
114
     */
115 4
    public static function execShutdownContainer(Exec $exec, Streams $streams, $idOrIds, $status, Flags $flags, $message)
116
    {
117
        # keep container on error
118 4
        if (0 !== $status && $flags->keepOnError()) {
119 2
            $streams->err(sprintf("error, %s\n", $message));
120
121 2
            return;
122
        }
123
124
        # keep or kill/remove container
125 2
        self::execKillAndRemove($exec, $idOrIds, $flags->killContainer(), $flags->removeContainer());
0 ignored issues
show
Bug introduced by
It seems like $idOrIds can also be of type string[]; however, parameter $idOrIds of Ktomk\Pipelines\Runner\S...er::execKillAndRemove() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

125
        self::execKillAndRemove($exec, /** @scrutinizer ignore-type */ $idOrIds, $flags->killContainer(), $flags->removeContainer());
Loading history...
126
127 2
        if ($flags->keep()) {
128 1
            $streams->out(sprintf("%s\n", $message));
129
        }
130 2
    }
131
132
    /**
133
     * StepContainer constructor.
134
     *
135
     * @param Step $step
136
     * @param Exec $exec
137
     */
138 14
    public function __construct(Step $step, Exec $exec)
139
    {
140 14
        $this->step = $step;
141 14
        $this->exec = $exec;
142 14
    }
143
144
    /**
145
     * generate step container name
146
     *
147
     * example: pipelines-1.pipeline-features-and-introspection.default.app
148
     *              ^    `^`                  ^                `    ^  ` ^
149
     *              |     |                   |                     |    |
150
     *              | step number        step name           pipeline id |
151
     *           prefix                                                project
152
     *
153
     * @param string $prefix for the name (normally "pipelines")
154
     * @param string $project name
155
     *
156
     * @return string
157
     */
158 9
    public function generateName($prefix, $project)
159
    {
160 9
        $step = $this->step;
161
162 9
        $idContainerSlug = preg_replace('([^a-zA-Z0-9_.-]+)', '-', $step->getPipeline()->getId());
163 9
        if ('' === $idContainerSlug) {
164 9
            $idContainerSlug = 'null';
165
        }
166 9
        $nameSlug = preg_replace(array('( )', '([^a-zA-Z0-9_.-]+)'), array('-', ''), $step->getName());
167 9
        if ('' === $nameSlug) {
168 9
            $nameSlug = 'no-name';
169
        }
170
171 9
        return $this->name = $prefix . '-' . implode(
172 9
                '.',
173
                array(
174 9
                    $step->getIndex() + 1,
175 9
                    $nameSlug,
176 9
                    trim($idContainerSlug, '-'),
177 9
                    $project,
178
                )
179
            );
180
    }
181
182
    /**
183
     * the display id
184
     *
185
     *   side-effect: if id is null, this signals a dry-run which is made
186
     * visible by the string "*dry-run*"
187
     *
188
     * @return string
189
     */
190 8
    public function getDisplayId()
191
    {
192 8
        return isset($this->id) ? $this->id : '*dry-run*';
193
    }
194
195
    /**
196
     * @return null|string ID of (once) running container or null if not yet running
197
     */
198 3
    public function getId()
199
    {
200 3
        return $this->id;
201
    }
202
203
    /**
204
     * @return null|string name of the container, NULL if no name generated yet
205
     */
206 3
    public function getName()
207
    {
208 3
        return $this->name;
209
    }
210
211
    /**
212
     * @param bool $keep a container on true, kill on false (if it exists)
213
     *
214
     * @return null|string
215
     */
216 7
    public function keepOrKill($keep)
217
    {
218 7
        $name = $this->name;
219 7
        if (null === $name) {
220 1
            throw new \BadMethodCallException('Container has no name yet');
221
        }
222
223 6
        $processManager = Docker::create($this->exec)->getProcessManager();
224
225 6
        if (false === $keep) {
226 2
            $processManager->zapContainersByName($name);
227
228 2
            return $this->id = null;
229
        }
230
231 5
        return $this->id = $processManager->findContainerIdByName($name);
232
    }
233
234
    /**
235
     * @param bool $kill
236
     * @param bool $remove
237
     *
238
     * @return void
239
     */
240 2
    public function killAndRemove($kill, $remove)
241
    {
242 2
        $id = $this->getDisplayId();
243
244 2
        self::execKillAndRemove($this->exec, $id, $kill, $remove);
245 2
    }
246
247
    /**
248
     * @param array $args
249
     *
250
     * @return array array(int $status, string $out, string $err)
251
     */
252 4
    public function run(array $args)
253
    {
254 4
        $execRun = self::execRun($this->exec, $args);
255 4
        $this->id = array_pop($execRun);
256
257 4
        return $execRun;
258
    }
259
}
260