Passed
Pull Request — master (#14)
by
unknown
03:26
created

Service::setCommand()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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