Passed
Push — test ( 46930c...fc64dd )
by Tom
02:28
created

StepContainer::generateServiceName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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\Definitions\Service;
11
use Ktomk\Pipelines\File\Pipeline\Step;
12
use Ktomk\Pipelines\Lib;
13
use Ktomk\Pipelines\Runner\Containers\NameBuilder;
14
use Ktomk\Pipelines\Runner\Docker\ImageLogin;
15
16
/**
17
 * Class StepContainer
18
 *
19
 * @package Ktomk\Pipelines\Runner
20
 */
21
class StepContainer
22
{
23
    /**
24
     * @var null|string id of the (running) container
25
     */
26
    private $id;
27
28
    /**
29
     * @var null|string name of the container
30
     */
31
    private $name;
32
33
    /**
34
     * @var Step
35
     */
36
    private $step;
37
38
    /**
39
     * @var Exec
40
     */
41
    private $exec;
42
43
    /**
44
     * @param Step $step
45
     * @param null|Exec $exec
46
     *
47
     * @return StepContainer
48
     */
49 6
    public static function create(Step $step, Exec $exec = null)
50
    {
51 6
        if (null === $exec) {
52 2
            $exec = new Exec();
53
        }
54
55 6
        return new self($step, $exec);
56
    }
57
58
    /**
59
     * @param Step $step
60
     * @param string $prefix
61
     * @param string $project name
62
     *
63
     * @return string
64
     */
65 1
    public static function createName(Step $step, $prefix, $project)
66
    {
67 1
        return self::create($step)->generateName($prefix, $project);
68
    }
69
70
    /**
71
     * kill and remove static implementation
72
     *
73
     * @param Exec $exec
74
     * @param string|string[] $idOrIds container id(s) or name(s)
75
     * @param bool $kill
76
     * @param bool $remove
77
     *
78
     * @return void
79
     */
80 4
    public static function execKillAndRemove(Exec $exec, $idOrIds, $kill, $remove)
81
    {
82 4
        if ($kill) {
83 2
            Docker::create($exec)->getProcessManager()->kill($idOrIds);
84
        }
85
86 4
        if ($remove) {
87 3
            Docker::create($exec)->getProcessManager()->remove($idOrIds);
88
        }
89 4
    }
90
91
    /**
92
     * @param Exec $exec
93
     * @param array $args
94
     *
95
     * @return array array(int $status, string $out, string $err, string|null $id)
96
     */
97 4
    public static function execRun(Exec $exec, array $args)
98
    {
99 4
        $status = $exec->capture('docker', Lib::merge('run', $args), $out, $err);
100
101 4
        $id = null;
102 4
        if (0 === $status) {
103 4
            $id = rtrim($out) ?: null;
104
        }
105
106 4
        return array($status, $out, $err, $id);
107
    }
108
109
    /**
110
     * @param Exec $exec
111
     * @param Streams $streams
112
     * @param string|string[] $idOrIds
113
     * @param int $status
114
     * @param Flags $flags
115
     * @param string $message
116
     * @param string $id
117
     *
118
     * @return void
119
     *
120
     * @see StepRunner::shutdownStepContainer
121
     */
122 4
    public static function execShutdownContainer(Exec $exec, Streams $streams, $idOrIds, $status, Flags $flags, $message)
123
    {
124
        # keep container on error
125 4
        if (0 !== $status && $flags->keepOnError()) {
126 2
            $streams->err(sprintf("error, %s\n", $message));
127
128 2
            return;
129
        }
130
131
        # keep or kill/remove container
132 2
        self::execKillAndRemove($exec, $idOrIds, $flags->killContainer(), $flags->removeContainer());
133
134 2
        if ($flags->keep()) {
135 1
            $streams->out(sprintf("%s\n", $message));
136
        }
137 2
    }
138
139
    /**
140
     * @param Exec $exec
141
     * @param Service $service
142
     * @param callable $resolver
143
     * @param string $prefix
144
     * @param string $project
145
     *
146
     * @return array
147
     */
148 1
    public static function execRunServiceContainer(Exec $exec, Service $service, $resolver, $prefix, $project)
149
    {
150 1
        $network = array('--network', 'host');
151 1
        $image = $service->getImage();
152 1
        ImageLogin::loginImage($exec, $resolver, null, $image);
153
154 1
        $containerName = NameBuilder::serviceContainerName($prefix, $service->getName(), $project);
155
156 1
        $variables = $resolver($service->getVariables());
157
158
        $args = array(
159 1
            $network, '--name',
160 1
            $containerName,
161 1
            '--detach',
162 1
            Env::createArgVarDefinitions('-e', $variables),
163 1
            $image->getName(),
164
        );
165
166 1
        $status = $exec->capture('docker', Lib::merge('run', $args), $out, $err);
167
168 1
        return array($status, $network);
169
    }
170
171
    /**
172
     * @param Exec $exec
173
     * @param Service $service
174
     * @param callable $resolver
175
     * @param string $prefix
176
     * @param string $project
177
     *
178
     * @return array
179
     */
180 1
    public static function execRunServiceContainerAttached(Exec $exec, Service $service, $resolver, $prefix, $project)
181
    {
182 1
        $network = array('--network', 'host');
183 1
        $image = $service->getImage();
184 1
        ImageLogin::loginImage($exec, $resolver, null, $image);
185
186 1
        $containerName = NameBuilder::serviceContainerName($prefix, $service->getName(), $project);
187
188 1
        $variables = $resolver($service->getVariables());
189
190
        $args = array(
191 1
            $network, '--name',
192 1
            $containerName,
193 1
            '--rm',
194 1
            Env::createArgVarDefinitions('-e', $variables),
195 1
            $image->getName(),
196
        );
197
198 1
        $status = $exec->pass('docker', Lib::merge('run', $args));
199
200 1
        return array($status, $network);
201
    }
202
203
    /**
204
     * StepContainer constructor.
205
     *
206
     * @param Step $step
207
     * @param Exec $exec
208
     */
209 14
    public function __construct(Step $step, Exec $exec)
210
    {
211 14
        $this->step = $step;
212 14
        $this->exec = $exec;
213 14
    }
214
215
    /**
216
     * generate step container name
217
     *
218
     * @param string $prefix for the name (normally "pipelines")
219
     * @param string $projectName name
220
     *
221
     * @return string
222
     */
223 9
    public function generateName($prefix, $projectName)
224
    {
225 9
        return $this->name = NameBuilder::stepContainerNameByStep($this->step, $prefix, $projectName);
226
    }
227
228
    /**
229
     * the display id
230
     *
231
     *   side-effect: if id is null, this signals a dry-run which is made
232
     * visible by the string "*dry-run*"
233
     *
234
     * @return string
235
     */
236 8
    public function getDisplayId()
237
    {
238 8
        return isset($this->id) ? $this->id : '*dry-run*';
239
    }
240
241
    /**
242
     * @return null|string ID of (once) running container or null if not yet running
243
     */
244 3
    public function getId()
245
    {
246 3
        return $this->id;
247
    }
248
249
    /**
250
     * @return null|string name of the container, NULL if no name generated yet
251
     */
252 3
    public function getName()
253
    {
254 3
        return $this->name;
255
    }
256
257
    /**
258
     * @param bool $keep a container on true, kill on false (if it exists)
259
     *
260
     * @return null|string
261
     */
262 7
    public function keepOrKill($keep)
263
    {
264 7
        $name = $this->name;
265 7
        if (null === $name) {
266 1
            throw new \BadMethodCallException('Container has no name yet');
267
        }
268
269 6
        $processManager = Docker::create($this->exec)->getProcessManager();
270
271 6
        if (false === $keep) {
272 2
            $processManager->zapContainersByName($name);
273
274 2
            return $this->id = null;
275
        }
276
277 5
        return $this->id = $processManager->findContainerIdByName($name);
278
    }
279
280
    /**
281
     * @param bool $kill
282
     * @param bool $remove
283
     *
284
     * @return void
285
     */
286 2
    public function killAndRemove($kill, $remove)
287
    {
288 2
        $id = $this->getDisplayId();
289
290 2
        self::execKillAndRemove($this->exec, $id, $kill, $remove);
291 2
    }
292
293
    /**
294
     * @param array $args
295
     *
296
     * @return array array(int $status, string $out, string $err)
297
     */
298 4
    public function run(array $args)
299
    {
300 4
        $execRun = self::execRun($this->exec, $args);
301 4
        $this->id = array_pop($execRun);
302
303 4
        return $execRun;
304
    }
305
}
306