11<?php namespace RancherizeBlueprintPhpCli \PhpCliBlueprint ;
22
3+ use Closure ;
34use Rancherize \Blueprint \Blueprint ;
5+ use Rancherize \Blueprint \Cron \CronService \CronService ;
6+ use Rancherize \Blueprint \Cron \Schedule \Exceptions \NoScheduleConfiguredException ;
7+ use Rancherize \Blueprint \Cron \Schedule \ScheduleParser ;
48use Rancherize \Blueprint \Flags \HasFlagsTrait ;
59use Rancherize \Blueprint \Infrastructure \Dockerfile \Dockerfile ;
610use Rancherize \Blueprint \Infrastructure \Infrastructure ;
11+ use Rancherize \Blueprint \Infrastructure \Service \Service ;
12+ use Rancherize \Blueprint \Infrastructure \Service \Services \AppService ;
713use Rancherize \Blueprint \Scheduler \SchedulerInitializer \SchedulerInitializer ;
14+ use Rancherize \Blueprint \Scheduler \SchedulerParser \SchedulerParser ;
15+ use Rancherize \Blueprint \TakesDockerAccount ;
816use Rancherize \Blueprint \Validation \Exceptions \ValidationFailedException ;
917use Rancherize \Blueprint \Validation \Traits \HasValidatorTrait ;
1018use Rancherize \Configuration \Configurable ;
1422use Rancherize \Configuration \Services \ConfigurableFallback ;
1523use Rancherize \Configuration \Services \ConfigurationFallback ;
1624use Rancherize \Configuration \Services \ConfigurationInitializer ;
25+ use Rancherize \Docker \DockerAccount ;
1726use Symfony \Component \Console \Input \InputInterface ;
1827use Symfony \Component \Console \Output \OutputInterface ;
1928
2029/**
2130 * Class PhpCliBlueprint
2231 * @package RancherizeBlueprintPhpCli\PhpCliBlueprint
2332 */
24- class PhpCliBlueprint implements Blueprint {
33+ class PhpCliBlueprint implements Blueprint, TakesDockerAccount {
34+
35+ private $ targetDirectory = '/var/cli/app ' ;
2536
2637 /**
2738 * Provider $this->getFlag('dev', false) to detect `rancherize init php-cli --dev` in init.
@@ -30,6 +41,11 @@ class PhpCliBlueprint implements Blueprint {
3041
3142 use HasValidatorTrait;
3243
44+ /**
45+ * @var SchedulerParser
46+ */
47+ protected $ rancherSchedulerParser ;
48+
3349 /**
3450 * Fill the configurable with all possible options with explanatory default options set
3551 *
@@ -148,6 +164,11 @@ public function build( Configuration $configuration, string $environment, string
148164 $ infrastructure ->setDockerfile ($ dockerfile );
149165
150166 // TODO: Implement build() method.
167+ $ service = $ this ->makeServerService ($ config , $ projectConfigurable );
168+ $ infrastructure ->addService ($ service );
169+ $ this ->addAppContainer ($ version , $ config , $ service , $ infrastructure );
170+
171+ $ this ->parseCronSchedule ( $ config , $ service );
151172
152173 return $ infrastructure ;
153174 }
@@ -159,18 +180,23 @@ public function build( Configuration $configuration, string $environment, string
159180 protected function makeDockerfile (Configuration $ config ):Dockerfile {
160181 $ dockerfile = new Dockerfile ();
161182
162- $ baseimage = $ config ->has ('php ' )
163- ? 'php: ' . $ config ->get ('php ' , '7.0 ' ) . '-alpine '
164- : $ config ->get ('docker.base-image ' , 'php:7.0-alpine ' );
183+ /**
184+ * @IMPORTANT
185+ *
186+ * This is NOT the php version that will later run the image.
187+ * It is the base of the app DATA image.
188+ * The php image that will actually run the app is the one set for the ServerService with $serverService->setImage()
189+ */
190+ $ baseimage = $ config ->get ('docker.base-image ' , 'php:7.0-alpine ' );
165191 $ dockerfile ->setFrom ($ baseimage );
166192
167- $ dockerfile ->addVolume (' /var/www/app ' );
193+ $ dockerfile ->addVolume ( $ this -> targetDirectory );
168194
169- $ dockerfile ->setWorkdir (' /var/www/app ' );
195+ $ dockerfile ->setWorkdir ( $ this -> targetDirectory );
170196
171197 $ copySuffix = $ config ->get ('work-sub-directory ' , '' );
172198 $ targetSuffix = $ config ->get ('target-sub-directory ' , '' );
173- $ dockerfile ->copy ('. ' .$ copySuffix , ' /var/www/app ' .$ targetSuffix );
199+ $ dockerfile ->copy ('. ' .$ copySuffix , $ this -> targetDirectory .$ targetSuffix );
174200
175201 if ($ config ->get ('add-composer ' , false )) {
176202 $ dockerfile ->run ('php -r "copy( \'https://getcomposer.org/installer \', \'composer-setup.php \');" \
@@ -192,11 +218,168 @@ protected function makeDockerfile(Configuration $config):Dockerfile {
192218 $ dockerfile ->addVolume ($ path );
193219 }
194220 }
195- $ dockerfile ->run ('rm -Rf /var/www/app /.rancherize ' );
221+ $ dockerfile ->run ('rm -Rf ' . $ this -> targetDirectory . ' /.rancherize ' );
196222
197- $ dockerfile ->setCommand ('php ' .$ config ->get ('command ' , '-i ' ));
198223
199224 return $ dockerfile ;
200225 }
201226
227+ /**
228+ * @param Configuration $config
229+ * @param Configuration $default
230+ * @return Service
231+ */
232+ protected function makeServerService (Configuration $ config , Configuration $ default ) : Service {
233+ $ serverService = new Service ();
234+ $ serverService ->setName ($ config ->get ('service-name ' ));
235+
236+ $ phpImage = $ config ->has ('php ' )
237+ ? 'php: ' . $ config ->get ('php ' , '7.0 ' ) . '-alpine '
238+ : $ config ->get ('docker.base-image ' , 'php:7.0-alpine ' );
239+ $ serverService ->setImage ($ config ->get ('docker.image ' , $ phpImage ));
240+
241+ if ( $ config ->get ('sync-user-into-container ' , false ) ) {
242+ $ serverService ->setEnvironmentVariable ('USER_ID ' , getmyuid ());
243+ $ serverService ->setEnvironmentVariable ('GROUP_ID ' , getmygid ());
244+ }
245+
246+ if ($ config ->get ('mount-workdir ' , false )) {
247+ $ mountSuffix = $ config ->get ('work-sub-directory ' , '' );
248+ $ targetSuffix = $ config ->get ('target-sub-directory ' , '' );
249+
250+ $ hostDirectory = getcwd () . $ mountSuffix ;
251+ $ containerDirectory = $ this ->targetDirectory . $ targetSuffix ;
252+ $ serverService ->addVolume ($ hostDirectory , $ containerDirectory );
253+ }
254+
255+
256+ $ command = 'php ' . $ config ->get ( 'command ' , '-i ' );
257+ $ serverService ->setCommand ($ command );
258+ $ serverService ->setRestart ( Service::RESTART_START_ONCE );
259+ $ serverService ->setWorkDir ( $ this ->targetDirectory );
260+
261+ $ persistentDriver = $ config ->get ('docker.persistent-driver ' , 'pxd ' );
262+ $ persistentOptions = $ config ->get ('docker.persistent-options ' , [
263+ 'repl ' => '3 ' ,
264+ 'shared ' => 'true ' ,
265+ ]);
266+ foreach ( $ config ->get ('persistent-volumes ' , []) as $ volumeName => $ path ) {
267+ $ volume = new \Rancherize \Blueprint \Infrastructure \Service \Volume ();
268+ $ volume ->setDriver ($ persistentDriver );
269+ $ volume ->setOptions ($ persistentOptions );
270+ $ volume ->setExternalPath ($ volumeName );
271+ $ volume ->setInternalPath ($ path );
272+ $ serverService ->addVolume ( $ volume );
273+ }
274+
275+ $ this ->addAll ([$ default , $ config ], 'environment ' , function (string $ name , $ value ) use ($ serverService ) {
276+ $ serverService ->setEnvironmentVariable ($ name , $ value );
277+ });
278+
279+ $ this ->addAll ([$ default , $ config ], 'labels ' , function (string $ name , $ value ) use ($ serverService ) {
280+ $ serverService ->addLabel ($ name , $ value );
281+ });
282+
283+ if ($ config ->has ('external_links ' )) {
284+ foreach ($ config ->get ('external_links ' ) as $ name => $ value )
285+ $ serverService ->addExternalLink ($ value , $ name );
286+ }
287+
288+ $ this ->rancherSchedulerParser ->parse ($ serverService , $ config );
289+
290+ return $ serverService ;
291+ }
292+
293+ /**
294+ * @param Configuration[] $configs
295+ * @param string $label
296+ * @param Closure $closure
297+ */
298+ private function addAll (array $ configs , string $ label , Closure $ closure ) {
299+ foreach ($ configs as $ c ) {
300+ if (!$ c ->has ($ label ))
301+ continue ;
302+
303+ foreach ($ c ->get ($ label ) as $ name => $ value )
304+ $ closure ($ name , $ value );
305+ }
306+ }
307+
308+ /**
309+ * @param $config
310+ * @param $service
311+ */
312+ protected function parseCronSchedule ( $ config , $ service ) {
313+ /**
314+ * @var ScheduleParser $scheduleParser
315+ */
316+ $ scheduleParser = container ( 'schedule-parser ' );
317+ try {
318+ $ schedule = $ scheduleParser ->parseSchedule ( $ config );
319+ } catch ( NoScheduleConfiguredException $ e ) {
320+ return ;
321+ }
322+
323+ /**
324+ * @var CronService $cronService
325+ */
326+ $ cronService = container ( 'cron-service ' );
327+ $ cronService ->makeCron ( $ service , $ schedule );
328+ }
329+
330+ /**
331+ * @param string $version
332+ * @param Configuration $config
333+ * @param Service $serverService
334+ * @param Infrastructure $infrastructure
335+ */
336+ protected function addAppContainer ($ version , Configuration $ config , Service $ serverService , Infrastructure $ infrastructure ) {
337+ if (!$ config ->get ('use-app-container ' , true ))
338+ return ;
339+
340+ $ imageName = $ config ->get ('docker.repository ' ) . ': ' . $ config ->get ('docker.version-prefix ' ) . $ version ;
341+ $ imageNameWithServer = $ this ->applyServer ($ imageName );
342+
343+ $ appService = new AppService ($ imageNameWithServer );
344+ $ appService ->setName ($ config ->get ('service-name ' ) . 'App ' );
345+
346+ $ serverService ->addSidekick ($ appService );
347+ $ serverService ->addVolumeFrom ($ appService );
348+ $ infrastructure ->addService ($ appService );
349+ }
350+
351+ /**
352+ * @var DockerAccount
353+ */
354+ protected $ dockerAccount = null ;
355+
356+ protected function applyServer (string $ imageName ) {
357+ if ( $ this ->dockerAccount === null )
358+ return $ imageName ;
359+
360+ $ server = $ this ->dockerAccount ->getServer ();
361+ if ( empty ($ server ) )
362+ return $ imageName ;
363+
364+ $ serverHost = parse_url ($ server , PHP_URL_HOST );
365+ $ imageNameWithServer = $ serverHost .'/ ' .$ imageName ;
366+
367+ return $ imageNameWithServer ;
368+ }
369+
370+ /**
371+ * @param DockerAccount $dockerAccount
372+ * @return $this
373+ */
374+ public function setDockerAccount ( DockerAccount $ dockerAccount ) {
375+ $ this ->dockerAccount = $ dockerAccount ;
376+ return $ this ;
377+ }
378+
379+ /**
380+ * @param SchedulerParser $rancherSchedulerParser
381+ */
382+ public function setRancherSchedulerParser ( SchedulerParser $ rancherSchedulerParser ) {
383+ $ this ->rancherSchedulerParser = $ rancherSchedulerParser ;
384+ }
202385}
0 commit comments