Passed
Push — master ( 889900...85cb36 )
by Keoghan
02:57
created

Organiser   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 97.5%

Importance

Changes 0
Metric Value
wmc 14
eloc 31
dl 0
loc 141
ccs 39
cts 40
cp 0.975
rs 10
c 0
b 0
f 0

8 Methods

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