Passed
Pull Request — master (#91)
by Keoghan
07:48
created

Organiser::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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