Completed
Push — master ( 9b76a9...b93dde )
by David
10s
created

Service::getDockerfileCommands()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace TheAentMachine\Service;
4
5
use Opis\JsonSchema\ValidationError;
6
use Opis\JsonSchema\Validator;
7
use TheAentMachine\Service\Enum\EnvVariableTypeEnum;
8
use TheAentMachine\Service\Enum\VolumeTypeEnum;
9
use TheAentMachine\Service\Environment\EnvVariable;
10
use TheAentMachine\Service\Exception\ServiceException;
11
use TheAentMachine\Service\Volume\BindVolume;
12
use TheAentMachine\Service\Volume\NamedVolume;
13
use TheAentMachine\Service\Volume\TmpfsVolume;
14
15
class Service implements \JsonSerializable
16
{
17
    /** @var string */
18
    private $serviceName = '';
19
    /** @var string|null */
20
    private $image = null;
21
    /** @var string[] */
22
    private $command = [];
23
    /** @var int[] */
24
    private $internalPorts = [];
25
    /** @var string[] */
26
    private $dependsOn = [];
27
    /** @var mixed[] */
28
    private $ports = [];
29
    /** @var mixed[] */
30
    private $labels = [];
31
    /** @var mixed[] */
32
    private $environment = [];
33
    /** @var mixed[] */
34
    private $volumes = [];
35
    /** @var \stdClass */
36
    private $validatorSchema;
37
    /** @var string[] */
38
    private $dockerfileCommands = [];
39
40
    /**
41
     * Service constructor.
42
     */
43
    public function __construct()
44
    {
45
        $this->validatorSchema = json_decode((string)file_get_contents(__DIR__ . '/ServiceJsonSchema.json'), false);
46
    }
47
48
    /**
49
     * @param mixed[] $payload
50
     * @return Service
51
     * @throws ServiceException
52
     */
53
    public static function parsePayload(array $payload): Service
54
    {
55
        $service = new self();
56
        $service->checkValidity($payload);
57
        $service->serviceName = $payload['serviceName'] ?? '';
58
        $s = $payload['service'] ?? [];
59
        if (!empty($s)) {
60
            $service->image = $s['image'] ?? null;
61
            $service->command = $s['command'] ?? [];
62
            $service->internalPorts = $s['internalPorts'] ?? [];
63
            $service->dependsOn = $s['dependsOn'] ?? [];
64
            $service->ports = $s['ports'] ?? [];
65
            $service->labels = $s['labels'] ?? [];
66
            if (!empty($s['environment'])) {
67
                foreach ($s['environment'] as $key => $env) {
68
                    $service->addEnvVar($key, $env['value'], $env['type']);
69
                }
70
            }
71
            if (!empty($s['volumes'])) {
72
                foreach ($s['volumes'] as $vol) {
73
                    $service->addVolume($vol['type'], $vol['source'], $vol['target'] ?? '', $vol['readOnly'] ?? false);
74
                }
75
            }
76
        }
77
        $service->dockerfileCommands = $payload['dockerfileCommands'] ?? [];
78
        return $service;
79
    }
80
81
    /**
82
     * Specify data which should be serialized to JSON
83
     * @link http://php.net/manual/en/jsonserializable.jsonserialize.php
84
     * @return array data which can be serialized by <b>json_encode</b>,
85
     * which is a value of any type other than a resource.
86
     * @since 5.4.0
87
     * @throws ServiceException
88
     */
89
    public function jsonSerialize(): array
90
    {
91
        $jsonSerializeMap = function (\JsonSerializable $obj): array {
92
            return $obj->jsonSerialize();
93
        };
94
95
        $array = array(
96
            'serviceName' => $this->serviceName,
97
            'service' => array_filter([
98
                'image' => $this->image,
99
                'command' => $this->command,
100
                'internalPorts' => $this->internalPorts,
101
                'dependsOn' => $this->dependsOn,
102
                'ports' => $this->ports,
103
                'labels' => $this->labels,
104
                'environment' => array_map($jsonSerializeMap, $this->environment),
105
                'volumes' => array_map($jsonSerializeMap, $this->volumes),
106
            ]),
107
        );
108
109
        if (!empty($this->dockerfileCommands)) {
110
            $array['dockerfileCommands'] = $this->dockerfileCommands;
111
        }
112
113
        $this->checkValidity($array);
114
        return $array;
115
    }
116
117
    /**
118
     * @param \stdClass|array|string $data
119
     * @return bool
120
     * @throws ServiceException
121
     */
122
    private function checkValidity($data): bool
123
    {
124
        if (\is_array($data)) {
125
            $data = \GuzzleHttp\json_decode(\GuzzleHttp\json_encode($data), false);
126
        }
127
        $validator = new Validator();
128
        $result = $validator->dataValidation($data, $this->validatorSchema);
129
        if (!$result->isValid()) {
130
            /** @var ValidationError $vError */
131
            $vError = $result->getFirstError();
132
            throw ServiceException::invalidServiceData($vError);
133
        }
134
        return $result->isValid();
135
    }
136
137
    /**
138
     * @return string
139
     */
140
    public function getServiceName(): string
141
    {
142
        return $this->serviceName;
143
    }
144
145
    /**
146
     * @return string|null
147
     */
148
    public function getImage(): ?string
149
    {
150
        return $this->image;
151
    }
152
153
    /**
154
     * @return string[]
155
     */
156
    public function getCommand(): array
157
    {
158
        return $this->command;
159
    }
160
161
    /**
162
     * @return int[]
163
     */
164
    public function getInternalPorts(): array
165
    {
166
        return $this->internalPorts;
167
    }
168
169
    /**
170
     * @return string[]
171
     */
172
    public function getDependsOn(): array
173
    {
174
        return $this->dependsOn;
175
    }
176
177
    /**
178
     * @return mixed[]
179
     */
180
    public function getPorts(): array
181
    {
182
        return $this->ports;
183
    }
184
185
    /**
186
     * @return mixed[]
187
     */
188
    public function getLabels(): array
189
    {
190
        return $this->labels;
191
    }
192
193
    /**
194
     * @return mixed[]
195
     */
196
    public function getEnvironment(): array
197
    {
198
        return $this->environment;
199
    }
200
201
    /**
202
     * @return mixed[]
203
     */
204
    public function getVolumes(): array
205
    {
206
        return $this->volumes;
207
    }
208
209
    /**
210
     * @return string[]
211
     */
212
    public function getDockerfileCommands(): array
213
    {
214
        return $this->dockerfileCommands;
215
    }
216
217
    /**
218
     * @param string $serviceName
219
     */
220
    public function setServiceName(string $serviceName): void
221
    {
222
        $this->serviceName = $serviceName;
223
    }
224
225
    /**
226
     * @param string|null $image
227
     */
228
    public function setImage(?string $image): void
229
    {
230
        $this->image = $image;
231
    }
232
233
    /**
234
     * @param string[] $command
235
     */
236
    public function setCommand(array $command): void
237
    {
238
        $this->command = $command;
239
    }
240
241
    /**
242
     * @param int[] $internalPorts
243
     */
244
    public function setInternalPorts(array $internalPorts): void
245
    {
246
        $this->internalPorts = $internalPorts;
247
    }
248
249
    /**
250
     * @param string[] $dependsOn
251
     */
252
    public function setDependsOn(array $dependsOn): void
253
    {
254
        $this->dependsOn = $dependsOn;
255
    }
256
257
    /**
258
     * @param string $command
259
     */
260
    public function addCommand(string $command): void
261
    {
262
        $this->command[] = $command;
263
    }
264
265
    /**
266
     * @param int $internalPort
267
     */
268
    public function addInternalPort(int $internalPort): void
269
    {
270
        $this->internalPorts[] = $internalPort;
271
    }
272
273
    /**
274
     * @param string $dependsOn
275
     */
276
    public function addDependsOn(string $dependsOn): void
277
    {
278
        $this->dependsOn[] = $dependsOn;
279
    }
280
281
    /**
282
     * @param int $source
283
     * @param int $target
284
     */
285
    public function addPort(int $source, int $target): void
286
    {
287
        $this->ports[] = array(
288
            'source' => $source,
289
            'target' => $target,
290
        );
291
    }
292
293
    /**
294
     * @param string $key
295
     * @param string $value
296
     */
297
    public function addLabel(string $key, string $value): void
298
    {
299
        $this->labels[$key] = array(
300
            'value' => $value,
301
        );
302
    }
303
304
    /**
305
     * @param string $key
306
     * @param string $value
307
     * @param string $type
308
     * @throws ServiceException
309
     */
310
    private function addEnvVar(string $key, string $value, string $type): void
311
    {
312
        switch ($type) {
313
            case EnvVariableTypeEnum::SHARED_ENV_VARIABLE:
314
                $this->addSharedEnvVariable($key, $value);
315
                break;
316
            case EnvVariableTypeEnum::SHARED_SECRET:
317
                $this->addSharedSecret($key, $value);
318
                break;
319
            case EnvVariableTypeEnum::IMAGE_ENV_VARIABLE:
320
                $this->addImageEnvVariable($key, $value);
321
                break;
322
            case EnvVariableTypeEnum::CONTAINER_ENV_VARIABLE:
323
                $this->addContainerEnvVariable($key, $value);
324
                break;
325
            default:
326
                throw ServiceException::unknownEnvVariableType($type);
327
        }
328
    }
329
330
    /**
331
     * @param string $key
332
     * @param string $value
333
     */
334
    public function addSharedEnvVariable(string $key, string $value): void
335
    {
336
        $this->environment[$key] = new EnvVariable($value, 'sharedEnvVariable');
337
    }
338
339
    /**
340
     * @param string $key
341
     * @param string $value
342
     */
343
    public function addSharedSecret(string $key, string $value): void
344
    {
345
        $this->environment[$key] = new EnvVariable($value, 'sharedSecret');
346
    }
347
348
    /**
349
     * @param string $key
350
     * @param string $value
351
     */
352
    public function addImageEnvVariable(string $key, string $value): void
353
    {
354
        $this->environment[$key] = new EnvVariable($value, 'imageEnvVariable');
355
    }
356
357
    /**
358
     * @param string $key
359
     * @param string $value
360
     */
361
    public function addContainerEnvVariable(string $key, string $value): void
362
    {
363
        $this->environment[$key] = new EnvVariable($value, 'containerEnvVariable');
364
    }
365
366
    /**
367
     * @param string $type
368
     * @param string $source
369
     * @param string $target
370
     * @param bool $readOnly
371
     * @throws ServiceException
372
     */
373
    private function addVolume(string $type, string $source, string $target = '', bool $readOnly = false): void
374
    {
375
        switch ($type) {
376
            case VolumeTypeEnum::NAMED_VOLUME:
377
                $this->addNamedVolume($source, $target, $readOnly);
378
                break;
379
            case VolumeTypeEnum::BIND_VOLUME:
380
                $this->addBindVolume($source, $target, $readOnly);
381
                break;
382
            case VolumeTypeEnum::TMPFS_VOLUME:
383
                $this->addTmpfsVolume($source);
384
                break;
385
            default:
386
                throw ServiceException::unknownVolumeType($type);
387
        }
388
    }
389
390
    /**
391
     * @param string $source
392
     * @param string $target
393
     * @param bool $readOnly
394
     */
395
    public function addNamedVolume(string $source, string $target, bool $readOnly = false): void
396
    {
397
        $this->volumes[] = new NamedVolume($source, $target, $readOnly);
398
    }
399
400
    /**
401
     * @param string $source
402
     * @param string $target
403
     * @param bool $readOnly
404
     */
405
    public function addBindVolume(string $source, string $target, bool $readOnly = false): void
406
    {
407
        $this->volumes[] = new BindVolume($source, $target, $readOnly);
408
    }
409
410
    /**
411
     * @param string $source
412
     */
413
    public function addTmpfsVolume(string $source): void
414
    {
415
        $this->volumes[] = new TmpfsVolume($source);
416
    }
417
418
    /**
419
     * @param string $dockerfileCommand
420
     */
421
    public function addDockerfileCommand(string $dockerfileCommand): void
422
    {
423
        $this->dockerfileCommands[] = $dockerfileCommand;
424
    }
425
}
426