-
Notifications
You must be signed in to change notification settings - Fork 2
/
RoboFile.php
342 lines (329 loc) · 11.7 KB
/
RoboFile.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
<?php
use Indatus\Assembler\Traits\FormatProductLine;
use Indatus\Assembler\Traits\FabricatorTrait;
use Indatus\Assembler\Traits\LoaderTrait;
use Indatus\Assembler\Traits\CustomizerTrait;
use Indatus\Assembler\Traits\StockerTrait;
use Indatus\Assembler\Traits\ProvisionTrait;
use Indatus\Assembler\Traits\PackagerTrait;
use Indatus\Assembler\Traits\DestroyerTrait;
use \Symfony\Component\Yaml\Yaml;
use Indatus\Assembler\Traits\ShipperTrait;
use Robo\Result;
use Robo\Tasks;
/**
* Assemblers's console commands configuration for Robo task runner.
*
* @see http://robo.li/
*/
class RoboFile extends Tasks
{
use FormatProductLine;
use FabricatorTrait;
use CustomizerTrait;
use StockerTrait;
use LoaderTrait;
use ProvisionTrait;
use PackagerTrait;
use DestroyerTrait;
use ShipperTrait;
/**
* Retrieve, organize, and create instructions for materials related to a product line
*
* @param string $productLine represents the product line being stocked
* @param array $opts
* @option boolean $clean when this flag is set then prior to the goods-path and the custom-data-path
* being written to they will be emptied if they already exist
* @option string $goodsPath path to where each of the suppliers will be written to
* @option string $customDataPath path to where any custom data should be stored
*
* @return array|\Robo\Result
*/
public function assemblerStock(
$productLine,
$opts = [
'clean' => false,
'force' => false,
'goodsPath' => 'repos',
'customDataPath' => 'custom_data'
]
) {
$manifest = $this->taskFormatProductLine($productLine)
->forSalt()
->run();
$this->say("Created the manifest...");
$stockerResult = $this->taskStockShelf(
$opts['goodsPath'],
$manifest->getData(),
$opts['clean'],
$opts['force']
)->run();
if ($stockerResult->getExitCode() > 0) {
$this->say("Unable to stock shelves.");
return $stockerResult;
}
// If we have any special instructions for this productLine, put them in the custom data folder
if (!is_null($manifest->getData()['custom-data'])) {
$customizer = $this->taskCustomizeData(
$manifest->getData()['custom-data'],
$opts['customDataPath'],
$productLine,
$opts['clean'],
$opts['force']
);
$result = $customizer->run();
if ($result->getExitCode() > 0) {
$this->say("Unable to process custom data.");
return $result;
}
}
$this->say("Shelves have been stocked!");
$data = [
'goodsPath' => realpath($opts['goodsPath']),
'customDataPath' => realpath($opts['customDataPath']),
];
return new Result($stockerResult->getTask(), 0,"Successfully stocked", $data);
}
/**
* Fabricates the specified docker container
*
* @param string $pathToDockerFile path to the directory where the docker file lives
* @param string $tag repository name (and optionally a tag) for the image
*
* @return \Robo\Result
*/
public function assemblerFabricate($pathToDockerFile, $tag)
{
$this->say("Building the docker container located at $pathToDockerFile.");
$result = $this->taskFabricateContainer($pathToDockerFile, $tag)
->run();
$this->say("Finished fabricating container!");
return $result;
}
/**
* Loads the specified container with goods
*
* @param string $containerId id of the image to load or the image name/repository
* @param string $shelfPath path to the raw_goods to be loaded
* @param string $customPath path to the custom data
*
* @return \Robo\Result
*/
public function assemblerLoad($containerId, $shelfPath, $customPath = null)
{
$this->say("Loading container with goods from shelf at $shelfPath...");
$result = $this->taskLoadContainer($containerId, $shelfPath, $customPath)
->run();
$this->say('Loaded the container with an id of: ' . $result->getCid());
return $result;
}
/**
* Commits and pushes a specified container
*
* @param string $containerId id of the container being packaged for shipping
* @param string $repository repository being pushed to
* @param array $opts
* @option boolean $push true if you want to push to a hub
* @option string $username your user name on the repository
* @option string $password your password for the repository being pushed to
* @email string $email your email for the repository being pushed to
*
* @return \Robo\Result
*/
public function assemblerPackage(
$containerId,
$repository,
$opts = [
'push' => false,
'username' => null,
'password' => null,
'email' => null
]
) {
$push = $opts['push'];
$username = $opts['username'];
$password = $opts['password'];
$email = $opts['email'];
return $this->taskPackage(
$containerId,
$repository,
$push,
$username,
$password,
$email
)->run();
}
/**
* Stocks the raw_goods, fabricates a base container, loads the conatiner, packages the container
*
* @param string $productLine
* @param array $opts
*
* @option boolean $clean set this if you want to empty goods and custom paths
* @option boolean $force set this if you don't want to be prompted to confirm clean
* @option string $goodsPath set the path where you want your rawgoods to live
* @option string $customDataPath set the path where you want your custom-data to be
* @option string $dockerfilePath set the path to the base dockerfile default is the current working directory
* @option string $repo repos you want to push to also will be name of image
* @option boolean $push set this if you want to push to the remote repo
* @option string $username your username for the docker registry
* @option string $password your password for the docker registry
* @option string $email your email on the docker registry
*
* @return array|\Robo\Result
*/
public function assemblerMake(
$productLine,
$opts = [
'clean' => false,
'force' => false,
'goodsPath' => 'repos',
'customDataPath' => 'custom_data',
'dockerfilePath' => './',
'repo' => null,
'push' => false,
'username' => null,
'password' => null,
'email' => null
]
) {
$baseName = "base_image".uniqid();
$stockResult = $this->assemblerStock(
$productLine,
$opts
);
if ($stockResult->getExitCode() > 0)
{
return $stockResult;
}
$fabricateResult = $this->assemblerFabricate(
realpath($opts['dockerfilePath']),
$baseName
);
if ($fabricateResult->getExitCode() > 0)
{
return $fabricateResult;
}
$loadResult = $this->assemblerLoad(
$baseName,
$stockResult->getData()["goodsPath"],
$stockResult->getData()["customDataPath"]
);
if ($loadResult->getExitCode() > 0) {
return $loadResult;
}
return $this->assemblerPackage($loadResult->getCid(), $opts['repo'], $opts);
}
/**
* Destroys the cloud server
* @param $machineFile the path to the machine file being described
* @return Result
*/
public function destroy($machineFile)
{
$data = Yaml::parse(realpath($machineFile));
return $this->taskDestroyServer($data['id'])
->run();
}
/**
* Provision a fresh server puts machine data to a file
* @param $hostname
* @param array $opts
* @option string $region the region where you want your server to be located
* @option string $size the size of the machine being created defaults to 512mb
* @option string $image the image used to generate the machine
* @option bool $backups true if you want backups of your machine
* @option bool $ipv6 true if you want ipv6 networking
* @option bool $privateNetworking true if you want private networking
* @option string $machineFilePath path to the machine file
* @return Result
*/
public function provision(
$hostname,
$opts = [
'region' => 'nyc3',
'size' => '512mb',
'image' => 'docker',
'backups' => false,
'ipv6' => false,
'privateNetworking' => false,
'machineFilePath' => './'
]
) {
$machineFile = realpath($opts['machineFilePath']);
$region = $opts['region'];
$size = $opts['size'];
$image = $opts['image'];
$backups = $opts['backups'];
$ipv6 = $opts['ipv6'];
$privateNetworking = $opts['privateNetworking'];
$result = $this->taskProvisionServer(
$hostname,
$region,
$size,
$image,
$backups,
$ipv6,
$privateNetworking
)->run();
$machineFile = $machineFile . '/.machine_' . $hostname;
$data = $result->getData();
$this->say("Provisioned server with id of: $data->id");
$machineData = Yaml::dump([
'id' => $data->id,
'ip' => $data->ip,
'hostName' => $hostname,
'region' => $region,
'size' => $size,
'image' => $image,
'backups' => $backups,
'ipv6' => $ipv6,
'ipAddress' => $data->ip,
'privateNetworking' => $privateNetworking
]);
file_put_contents($machineFile, $machineData);
return $result;
}
/**
* Ship a container
*
* @param string $image Docker image to be shipped
* @param array $opts
* @option $ip IP address of the container host
* @option $machineFile the path to a machine file
* @option $ports Comma separated list of ports to open between host and container
* @option $remote_command Command to run after contaier is started
* @return \Robo\Result|int
*/
public function ship(
$image,
$opts = [
'ip' => '',
'machineFile' => '',
'ports' => '',
'remote_command' => '',
'remote_user' => 'root',
'sudo' => false
]
) {
$ip = $opts['ip'];
$machineFile = $opts['machineFile'];
if (empty($ip) && empty($machineFile)) {
$this->say('Cannot ship with out an ip address or a machine file');
return 1;
}
if (!empty($ip) && !empty($machineFile)) {
$this->say('You must specify an ip address or a machine file not both');
return 1;
}
$ip = $ip ? $ip : Yaml::parse(realpath($machineFile))['ip'];
return $this->taskShipContainer(
$image,
$ip,
$opts['ports'],
$opts['remote_command'],
$opts['remote_user'],
$opts['sudo']
)->run();
}
}