Organiser   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 143
Duplicated Lines 0 %

Test Coverage

Coverage 97.14%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 15
eloc 32
dl 0
loc 143
ccs 34
cts 35
cp 0.9714
rs 10
c 1
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A pullImages() 0 9 4
A findBuildVersion() 0 5 1
A pushImages() 0 5 2
A buildImages() 0 11 3
A updateConfigVersionForImage() 0 10 1
A hasImage() 0 5 1
A readVersion() 0 9 2
1
<?php
2
3
namespace App\Support\Images\Organiser;
4
5
use App\Support\Contracts\Cli;
6
use App\Support\Contracts\ImageRepository;
7
use App\Support\Images\Image;
8
use Illuminate\Contracts\Filesystem\FileNotFoundException;
9
use Illuminate\Filesystem\Filesystem;
10
11
class Organiser
12
{
13
    /** @var ImageRepository */
14
    protected $repository;
15
16
    /** @var Cli */
17
    protected $cli;
18
19
    /** @var Filesystem */
20
    protected $filesystem;
21
22 14
    public function __construct(ImageRepository $repository, Cli $cli, Filesystem $filesystem)
23
    {
24 14
        $this->repository = $repository;
25 14
        $this->cli = $cli;
26 14
        $this->filesystem = $filesystem;
27
    }
28
29
    /**
30
     * Build the current images.
31
     *
32
     * @param string|null $service
33
     * @param bool        $fresh
34
     *
35
     * @throws FileNotFoundException
36
     */
37 4
    public function buildImages($service = null, $fresh = false)
38
    {
39 4
        foreach ($this->repository->findByServiceName($service, $firstPartyOnly = true) as $image) {
40
            /** @var Image $image */
41 3
            $version = $this->findBuildVersion($image);
42 3
            $name = $image->getUnVersionedName();
43 3
            $freshen = $fresh ? ' --pull --no-cache' : '';
44
45 3
            $this->cli->passthru("docker build{$freshen} -t {$name}:{$version} -t {$name}:latest --rm {$image->getLocalPath()} --");
46
47 3
            $this->updateConfigVersionForImage($image, $version);
48
        }
49
    }
50
51
    /**
52
     * Find the build version for an image.
53
     * Look in the first line of the Dockerfile.
54
     *
55
     * @param Image $image
56
     *
57
     * @throws FileNotFoundException
58
     *
59
     * @return string
60
     */
61 4
    public function findBuildVersion(Image $image)
62
    {
63 4
        $dockerFile = $this->filesystem->get($image->getLocalPath().'/Dockerfile');
64
65 4
        return (string) $this->readVersion(strtok($dockerFile, "\n"));
66
    }
67
68
    /**
69
     * Read the version string, validate and return version.
70
     *
71
     * @param string $versionString
72
     *
73
     * @throws \Exception
74
     *
75
     * @return string
76
     */
77 6
    public function readVersion($versionString)
78
    {
79 6
        if (!preg_match('/#VERSION:\s{0,}\d+\.\d+\.\d+/', $versionString)) {
80 1
            throw new \Exception(
81
                "The version must be the first line of the Dockerfile and in the format '#VERSION: x.y.z'"
82
            );
83
        }
84
85 5
        return trim(str_replace('#VERSION:', '', $versionString));
86
    }
87
88
    /**
89
     * Update the version stored in the config.json file.
90
     *
91
     * @param Image $image
92
     * @param $version
93
     *
94
     * @throws FileNotFoundException
95
     */
96 4
    public function updateConfigVersionForImage(Image $image, $version)
97
    {
98 4
        $configFile = $this->repository->getPath().'/config.json';
99 4
        $config = json_decode($this->filesystem->get($configFile), true);
100
101 4
        $serviceName = substr($image->getUnVersionedName(), strlen($config['name']) + 1);
102
103 4
        $config['firstParty'][$serviceName] = $version;
104
105 4
        $this->filesystem->put($configFile, json_encode($config, JSON_PRETTY_PRINT));
106
    }
107
108
    /**
109
     * Push the current images.
110
     *
111
     * @param string|null $service
112
     *
113
     * @throws \Exception
114
     */
115 3
    public function pushImages($service = null)
116
    {
117 3
        foreach ($this->repository->findByServiceName($service, $firstPartyOnly = true) as $image) {
118
            /* @var Image $image */
119 2
            $this->cli->passthru("docker push {$image->getName()}");
120
        }
121
    }
122
123
    /**
124
     * Pull our docker images.
125
     *
126
     * @param string|null $service
127
     *
128
     * @throws \Exception
129
     */
130 3
    public function pullImages($service = null)
131
    {
132 3
        foreach ($this->repository->findByServiceName($service) as $image) {
133
            /** @var Image $image */
134 3
            if (running_tests() && $this->hasImage($image)) {
135
                continue;
136
            }
137
138 3
            $this->cli->passthru("docker pull {$image->getName()}");
139
        }
140
    }
141
142
    /**
143
     * Check if we already have the image.
144
     *
145
     * @param Image $image
146
     *
147
     * @return bool
148
     */
149 3
    public function hasImage(Image $image)
150
    {
151 3
        $output = $this->cli->exec("docker image inspect {$image->getName()}");
152
153 3
        return strpos($output, "Error: No such image: {$image->getName()}") === false;
154
    }
155
}
156