diff --git a/Dockerfile b/Dockerfile index 439dcaf..786fbc3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,5 @@ FROM php:cli -RUN apt-get update && apt-get install -yq --no-install-recommends cron && rm -r /var/lib/apt/lists/* RUN docker-php-ext-install pdo_mysql -CMD [ "cron", "-f", "-L", "15" ] -#ENTRYPOINT [ "/app/bin/console" ] -#CMD [ "/app/bin/console", "watch" ] +WORKDIR /app diff --git a/Prod.Dockerfile b/Prod.Dockerfile new file mode 100644 index 0000000..70603ea --- /dev/null +++ b/Prod.Dockerfile @@ -0,0 +1,27 @@ +FROM php:cli AS build + +RUN apt-get update && apt-get install -yq --no-install-recommends git unzip && rm -r /var/lib/apt/lists/* +COPY --from=composer /usr/bin/composer /usr/bin/composer + +USER 1000 +WORKDIR /code +RUN git clone --branch master http://git.provm.cl/ProVM/remote_ip.git /code +RUN composer -d /code/app install + +FROM php:cli + +ENV MYSQL_HOST '' +ENV MYSQL_DATABASE '' +ENV MYSQL_USER '' +ENV MYSQL_PASSWORD '' + +RUN docker-php-ext-install pdo_mysql + +WORKDIR /app +COPY --from=build /code/app /app + +ENTRYPOINT [ "/app/bin/console" ] + +CMD [ "/app/bin/console", "watch" ] +#RUN apt-get update && apt-get install -yq --no-install-recommends cron && rm -r /var/lib/apt/lists/* && cp /app/crontab /var/spool/cron/crontabs/root +#CMD [ "cron", "-f", "-L", "15" ] diff --git a/app/common/Command/UpdateIp.php b/app/common/Command/UpdateIp.php index c6d3284..2128483 100644 --- a/app/common/Command/UpdateIp.php +++ b/app/common/Command/UpdateIp.php @@ -8,6 +8,7 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use ProVM\Service\Remote; +use Symfony\Component\Console\Style\SymfonyStyle; #[AsCommand( name: 'update', @@ -22,8 +23,13 @@ class UpdateIp extends Command public function execute(InputInterface $input, OutputInterface $output): int { + $io = new SymfonyStyle($input, $output); + $io->title('Update IP'); + try { + $io->info('Obtaining IP and updating database'); $this->service->update(); + $io->info('Done'); return Command::SUCCESS; } catch (PDOException $e) { $this->logger->warning($e); diff --git a/app/common/Command/Watch.php b/app/common/Command/Watch.php index 5bf5e87..397bcbf 100644 --- a/app/common/Command/Watch.php +++ b/app/common/Command/Watch.php @@ -7,6 +7,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use function Safe\shell_exec; #[AsCommand( @@ -15,27 +16,35 @@ use function Safe\shell_exec; )] class Watch extends Command { - public function __construct(protected string $period, string $name = 'watch') + public function __construct(protected string $command, protected string $period, protected LoggerInterface $logger, string $name = 'watch') { parent::__construct($name); } public function execute(InputInterface $input, OutputInterface $output): int { + $io = new SymfonyStyle($input, $output); + $io->title('Watch'); + $period = new DateInterval($this->period); $current = new DateTimeImmutable(); + $io->info('Starting'); while(true) { $now = new DateTimeImmutable(); if ($now->diff($current) === $period) { + $io->info('Running Update'); $this->runUpdate(); $current = $now; } + $wait = (new DateTimeImmutable((new DateTimeImmutable())->format('Y-m-d H:i:0')))->add(new DateInterval('PT1M')); + time_sleep_until($wait->getTimestamp()); } return Command::SUCCESS; } protected function runUpdate(): void { - $command = '/app/bin/console update'; + $command = "{$this->command} update"; + $this->logger->info("Running '{$command}'"); shell_exec($command); } } diff --git a/app/common/Service/Connector.php b/app/common/Service/Connector.php new file mode 100644 index 0000000..7c8c6bc --- /dev/null +++ b/app/common/Service/Connector.php @@ -0,0 +1,41 @@ +connection)) { + $this->logger->debug('Connecting'); + $r = 0; + $exception = null; + while($r < $this->retries) { + try { + $dsn = "mysql:host={$this->host};dbname={$this->name}"; + $this->connection = new PDO($dsn, $this->username, $this->password); + return $this->connection; + } catch (PDOException $e) { + $this->logger->debug('Retrying'); + if ($exception !== null) { + $e = new PDOException($e->getMessage(), $e->getCode(), $exception); + } + $exception = $e; + } + $r ++; + } + throw $exception; + } + return $this->connection; + } +} diff --git a/app/common/Service/Ipify.php b/app/common/Service/Ipify.php index 1ed9d1a..2136521 100644 --- a/app/common/Service/Ipify.php +++ b/app/common/Service/Ipify.php @@ -22,6 +22,7 @@ class Ipify if (!isset($json->ip)) { throw new Exception('Missing `ip` in JSON response'); } + $this->logger->debug("Current IP: {$json->ip}"); return $json->ip; } } diff --git a/app/common/Service/Repository.php b/app/common/Service/Repository.php index f358748..7300a46 100644 --- a/app/common/Service/Repository.php +++ b/app/common/Service/Repository.php @@ -6,28 +6,28 @@ use Psr\Log\LoggerInterface; class Repository { - public function __construct(protected PDO $connection, protected string $table, protected LoggerInterface $logger) {} + public function __construct(protected Connector $connector, protected string $table, protected LoggerInterface $logger) {} public function update(string $ip): void { $this->logger->debug('Updating Database'); $old_ip = $this->getOld(); - $this->logger->debug($old_ip); + $this->logger->debug("Old IP: {$old_ip}"); if ($old_ip === $ip) { $this->logger->debug('No change in IP'); return; } - $this->doUpdate(); + $this->doUpdate($ip); $this->logger->debug('Updated IP'); } protected function getOld(): string { $query = "SELECT `ip` FROM `{$this->table}` WHERE `host` = ?"; - $statement = $this->connection->prepare($query); + $statement = $this->connector->connect()->prepare($query); $statement->execute(['vialdelamaza']); return $statement->fetch()['ip']; @@ -35,7 +35,7 @@ class Repository protected function doUpdate(string $ip): void { $query = "UPDATE `remote_ip` SET `ip` = ?, `updated` = CURRENT_TIMESTAMP() WHERE `host` = ?"; - $statement = $this->connection->prepare($query); + $statement = $this->connector->connect()->prepare($query); $statement->execute([$ip, 'vialdelamaza']); } } diff --git a/app/public/index.php b/app/public/index.php index 0606ece..cd4984c 100644 --- a/app/public/index.php +++ b/app/public/index.php @@ -4,4 +4,10 @@ $app = require_once implode(DIRECTORY_SEPARATOR, [ 'setup', 'app.php' ]); -$app->run(); +try { + $app->run(); +} catch (Exception $e) { + $app->getContainer()->get(Psr\Log\LoggerInterface::class)->warning($e); +} catch (Error $e) { + $app->getContainer()->get(Psr\Log\LoggerInterface::class)->error($e); +} diff --git a/app/setup/middlewares/log.php b/app/setup/middlewares/log.php new file mode 100644 index 0000000..b81e521 --- /dev/null +++ b/app/setup/middlewares/log.php @@ -0,0 +1,2 @@ +getContainer()->get(Psr\Log\LoggerInterface::class)); diff --git a/app/setup/settings/01_env.php b/app/setup/settings/01_env.php index f991737..6ceb90b 100644 --- a/app/setup/settings/01_env.php +++ b/app/setup/settings/01_env.php @@ -10,10 +10,13 @@ return [ 'password' => $_ENV['MYSQL_PASSWORD'] ]); }, - 'table' => 'remote_ip', + 'table' => $_ENV['MYSQL_TABLE'] ?? 'remote_ip', ]); }, - 'uri' => 'https://api64.ipify.org', - 'period' => 'PT20M', - 'retries' => 5 + 'error_logs_file' => $_ENV['ERROR_LOGS_FILE'] ?? '/logs/remote.error.log', + 'debug_logs_file' => $_ENV['DEBUG_LOGS_FILE'] ?? '/logs/remote.debug.log', + 'uri' => $_ENV['IPIFY_URI'] ?? 'https://api64.ipify.org', + 'command' => 'php /app/public/index.php', + 'period' => $_ENV['WATCH_PERIOD'] ?? 'PT20M', + 'retries' => $_ENV['CONNECTION_RETRIES'] ?? 5 ]; diff --git a/app/setup/setups/commands.php b/app/setup/setups/commands.php index d4ee224..d34ca97 100644 --- a/app/setup/setups/commands.php +++ b/app/setup/setups/commands.php @@ -3,6 +3,10 @@ use Psr\Container\ContainerInterface; return [ ProVM\Command\Watch::class => function(ContainerInterface $container) { - return new ProVM\Command\Watch($container->get('period')); - } + return new ProVM\Command\Watch( + $container->get('command'), + $container->get('period'), + $container->get(Psr\Log\LoggerInterface::class) + ); + }, ]; diff --git a/app/setup/setups/services.php b/app/setup/setups/services.php index b7150fd..d4e86a0 100644 --- a/app/setup/setups/services.php +++ b/app/setup/setups/services.php @@ -5,12 +5,12 @@ return [ Psr\Log\LoggerInterface::class => function(ContainerInterface $container) { return new Monolog\Logger('file', [ new Monolog\Handler\FilterHandler( - new Monolog\Handler\RotatingFileHandler('/var/log/remote.debug.log'), + new Monolog\Handler\RotatingFileHandler($container->get('debug_logs_file')), Monolog\Level::Debug, Monolog\Level::Warning ), new Monolog\Handler\FilterHandler( - new Monolog\Handler\RotatingFileHandler('/var/log/remote.error.log'), + new Monolog\Handler\RotatingFileHandler($container->get('error_logs_file')), Monolog\Level::Error ) ], [ @@ -32,28 +32,20 @@ return [ $container->get(Psr\Log\LoggerInterface::class) ); }, - PDO::class => function(ContainerInterface $container) { + ProVM\Service\Connector::class => function(ContainerInterface $container) { $database = $container->get('database'); - $retries = $container->get('retries'); - $r = 0; - $exception = null; - while($r < $retries) { - try { - $dsn = "mysql:host={$database->get('host')};dbname={$database->get('name')}"; - return new PDO($dsn, $database->get('user')->get('name'), $database->get('user')->get('password')); - } catch (PDOException $e) { - if ($exception !== null) { - $e = new PDOException($e->getMessage(), $e->getCode(), $exception); - } - $exception = $e; - $container->get(Psr\Log\LoggerInterface::class)->debug('Retrying Connection'); - } - } - throw $exception; + return new ProVM\Service\Connector( + $database->get('host'), + $database->get('name'), + $database->get('user')->get('name'), + $database->get('user')->get('password'), + $container->get('retries'), + $container->get(Psr\Log\LoggerInterface::class) + ); }, ProVM\Service\Repository::class => function(ContainerInterface $container) { return new ProVM\Service\Repository( - $container->get(PDO::class), + $container->get(ProVM\Service\Connector::class), $container->get('database')->get('table'), $container->get(Psr\Log\LoggerInterface::class) ); diff --git a/docker-compose.yml b/docker-compose.yml index e43fdf3..f6d5a14 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,4 +6,5 @@ services: env_file: .env volumes: - ./app:/app - - ./app/crontab:/var/spool/cron/crontabs/root + - ./logs:/logs +# - ./app/crontab:/var/spool/cron/crontabs/root