Compare commits
8 Commits
v1.0.0
...
f5c7982641
Author | SHA1 | Date | |
---|---|---|---|
f5c7982641 | |||
079b244ce0 | |||
4f9b96b401 | |||
c53f7b6719 | |||
98adc9f572 | |||
390c15a45c | |||
4472a26412 | |||
8d8eb84e20 |
@ -2,3 +2,12 @@ MYSQL_HOST=provm.cl
|
|||||||
MYSQL_DATABASE=incoviba
|
MYSQL_DATABASE=incoviba
|
||||||
MYSQL_USER=remote_incoviba
|
MYSQL_USER=remote_incoviba
|
||||||
MYSQL_PASSWORD=43918b603b84dd8bb29fd29a0ea21ba751de5dc90b26f36c
|
MYSQL_PASSWORD=43918b603b84dd8bb29fd29a0ea21ba751de5dc90b26f36c
|
||||||
|
MYSQL_TABLE=remote_ip
|
||||||
|
|
||||||
|
ERROR_LOGS_FILE=php://stderr
|
||||||
|
DEBUG_LOGS_FILE=php://stdout
|
||||||
|
|
||||||
|
IPIFY_URI=https://api64.ipify.org
|
||||||
|
COMMAND=/app/bin/console
|
||||||
|
WATCH_PERIOD=PT20M
|
||||||
|
CONNECTION_RETRIES=5
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
FROM php:cli
|
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
|
RUN docker-php-ext-install pdo_mysql
|
||||||
|
|
||||||
CMD [ "cron", "-f", "-L", "15" ]
|
WORKDIR /app
|
||||||
|
COPY ./app /app
|
||||||
|
RUN chmod a+x /app/bin/console
|
||||||
|
|
||||||
#ENTRYPOINT [ "/app/bin/console" ]
|
#ENTRYPOINT [ "/app/bin/console" ]
|
||||||
#CMD [ "/app/bin/console", "watch" ]
|
CMD [ "/app/bin/console", "watch" ]
|
||||||
|
25
Prod.Dockerfile
Normal file
25
Prod.Dockerfile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
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
|
||||||
|
|
||||||
|
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" ]
|
@ -8,6 +8,7 @@ use Symfony\Component\Console\Command\Command;
|
|||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use ProVM\Service\Remote;
|
use ProVM\Service\Remote;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
|
|
||||||
#[AsCommand(
|
#[AsCommand(
|
||||||
name: 'update',
|
name: 'update',
|
||||||
@ -22,8 +23,13 @@ class UpdateIp extends Command
|
|||||||
|
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
public function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$io->title('Update IP');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$io->info('Obtaining IP and updating database');
|
||||||
$this->service->update();
|
$this->service->update();
|
||||||
|
$io->info('Done');
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$this->logger->warning($e);
|
$this->logger->warning($e);
|
||||||
|
@ -7,6 +7,8 @@ use Psr\Log\LoggerInterface;
|
|||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Style\StyleInterface;
|
||||||
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
use function Safe\shell_exec;
|
use function Safe\shell_exec;
|
||||||
|
|
||||||
#[AsCommand(
|
#[AsCommand(
|
||||||
@ -15,27 +17,48 @@ use function Safe\shell_exec;
|
|||||||
)]
|
)]
|
||||||
class Watch extends Command
|
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);
|
parent::__construct($name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function execute(InputInterface $input, OutputInterface $output): int
|
public function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
|
$io = new SymfonyStyle($input, $output);
|
||||||
|
$io->title('Watch');
|
||||||
|
|
||||||
$period = new DateInterval($this->period);
|
$period = new DateInterval($this->period);
|
||||||
$current = new DateTimeImmutable();
|
$current = $this->updateTime($period);
|
||||||
|
$io->info('Starting');
|
||||||
|
$io->info("Start: {$current->format('Y-m-d H:i:s')}");
|
||||||
while(true) {
|
while(true) {
|
||||||
$now = new DateTimeImmutable();
|
$io->info('Running Update');
|
||||||
if ($now->diff($current) === $period) {
|
$this->runUpdate($io);
|
||||||
$this->runUpdate();
|
$current = $this->updateTime($period);
|
||||||
$current = $now;
|
$wait = $current->add($period);
|
||||||
}
|
$io->text("Waiting until {$wait->format('Y-m-d H:i:s')}");
|
||||||
|
time_sleep_until($wait->getTimestamp());
|
||||||
}
|
}
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
protected function runUpdate(): void
|
protected function updateTime(DateInterval $interval): DateTimeImmutable
|
||||||
{
|
{
|
||||||
$command = '/app/bin/console update';
|
$t0 = new DateTimeImmutable((new DateTimeImmutable())->format('Y-m-d 00:00:00'));
|
||||||
shell_exec($command);
|
$tf = new DateTimeImmutable((new DateTimeImmutable())->add(new DateInterval('P1D'))->format('Y-m-d 00:00:00'));
|
||||||
|
$now = new DateTimeImmutable();
|
||||||
|
for ($t = $t0; $t < $tf; $t = $t->add($interval)) {
|
||||||
|
$t1 = $t->add($interval);
|
||||||
|
if ($t < $now and $now < $t1) {
|
||||||
|
return $t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $now;
|
||||||
|
}
|
||||||
|
protected function runUpdate(StyleInterface $io): void
|
||||||
|
{
|
||||||
|
$command = "{$this->command} update";
|
||||||
|
$this->logger->info("Running '{$command}'");
|
||||||
|
$result = shell_exec($command);
|
||||||
|
$io->note($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
41
app/common/Service/Connector.php
Normal file
41
app/common/Service/Connector.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
namespace ProVM\Service;
|
||||||
|
|
||||||
|
use PDO;
|
||||||
|
use PDOException;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class Connector
|
||||||
|
{
|
||||||
|
public function __construct(protected string $host, protected string $name, protected string $username, protected string $password, protected string $retries, protected LoggerInterface $logger) {}
|
||||||
|
|
||||||
|
protected PDO $connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws PDOException
|
||||||
|
*/
|
||||||
|
public function connect(): PDO
|
||||||
|
{
|
||||||
|
if (!isset($this->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;
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ class Ipify
|
|||||||
if (!isset($json->ip)) {
|
if (!isset($json->ip)) {
|
||||||
throw new Exception('Missing `ip` in JSON response');
|
throw new Exception('Missing `ip` in JSON response');
|
||||||
}
|
}
|
||||||
|
$this->logger->debug("Current IP: {$json->ip}");
|
||||||
return $json->ip;
|
return $json->ip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,28 +6,28 @@ use Psr\Log\LoggerInterface;
|
|||||||
|
|
||||||
class Repository
|
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
|
public function update(string $ip): void
|
||||||
{
|
{
|
||||||
$this->logger->debug('Updating Database');
|
$this->logger->debug('Updating Database');
|
||||||
|
|
||||||
$old_ip = $this->getOld();
|
$old_ip = $this->getOld();
|
||||||
$this->logger->debug($old_ip);
|
$this->logger->debug("Old IP: {$old_ip}");
|
||||||
|
|
||||||
if ($old_ip === $ip) {
|
if ($old_ip === $ip) {
|
||||||
$this->logger->debug('No change in IP');
|
$this->logger->debug('No change in IP');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->doUpdate();
|
$this->doUpdate($ip);
|
||||||
$this->logger->debug('Updated IP');
|
$this->logger->debug('Updated IP');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getOld(): string
|
protected function getOld(): string
|
||||||
{
|
{
|
||||||
$query = "SELECT `ip` FROM `{$this->table}` WHERE `host` = ?";
|
$query = "SELECT `ip` FROM `{$this->table}` WHERE `host` = ?";
|
||||||
$statement = $this->connection->prepare($query);
|
$statement = $this->connector->connect()->prepare($query);
|
||||||
$statement->execute(['vialdelamaza']);
|
$statement->execute(['vialdelamaza']);
|
||||||
|
|
||||||
return $statement->fetch()['ip'];
|
return $statement->fetch()['ip'];
|
||||||
@ -35,7 +35,7 @@ class Repository
|
|||||||
protected function doUpdate(string $ip): void
|
protected function doUpdate(string $ip): void
|
||||||
{
|
{
|
||||||
$query = "UPDATE `remote_ip` SET `ip` = ?, `updated` = CURRENT_TIMESTAMP() WHERE `host` = ?";
|
$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']);
|
$statement->execute([$ip, 'vialdelamaza']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,4 +4,10 @@ $app = require_once implode(DIRECTORY_SEPARATOR, [
|
|||||||
'setup',
|
'setup',
|
||||||
'app.php'
|
'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);
|
||||||
|
}
|
||||||
|
2
app/setup/middlewares/log.php
Normal file
2
app/setup/middlewares/log.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
Monolog\ErrorHandler::register($app->getContainer()->get(Psr\Log\LoggerInterface::class));
|
@ -10,10 +10,13 @@ return [
|
|||||||
'password' => $_ENV['MYSQL_PASSWORD']
|
'password' => $_ENV['MYSQL_PASSWORD']
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
'table' => 'remote_ip',
|
'table' => $_ENV['MYSQL_TABLE'] ?? 'remote_ip',
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
'uri' => 'https://api64.ipify.org',
|
'error_logs_file' => $_ENV['ERROR_LOGS_FILE'] ?? '/logs/remote.error.log',
|
||||||
'period' => 'PT20M',
|
'debug_logs_file' => $_ENV['DEBUG_LOGS_FILE'] ?? '/logs/remote.debug.log',
|
||||||
'retries' => 5
|
'uri' => $_ENV['IPIFY_URI'] ?? 'https://api64.ipify.org',
|
||||||
|
'command' => $_ENV['COMMAND'] ?? 'php /app/public/index.php',
|
||||||
|
'period' => $_ENV['WATCH_PERIOD'] ?? 'PT20M',
|
||||||
|
'retries' => $_ENV['CONNECTION_RETRIES'] ?? 5
|
||||||
];
|
];
|
||||||
|
@ -3,6 +3,10 @@ use Psr\Container\ContainerInterface;
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
ProVM\Command\Watch::class => function(ContainerInterface $container) {
|
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)
|
||||||
|
);
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
@ -5,12 +5,12 @@ return [
|
|||||||
Psr\Log\LoggerInterface::class => function(ContainerInterface $container) {
|
Psr\Log\LoggerInterface::class => function(ContainerInterface $container) {
|
||||||
return new Monolog\Logger('file', [
|
return new Monolog\Logger('file', [
|
||||||
new Monolog\Handler\FilterHandler(
|
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::Debug,
|
||||||
Monolog\Level::Warning
|
Monolog\Level::Warning
|
||||||
),
|
),
|
||||||
new Monolog\Handler\FilterHandler(
|
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
|
Monolog\Level::Error
|
||||||
)
|
)
|
||||||
], [
|
], [
|
||||||
@ -32,28 +32,20 @@ return [
|
|||||||
$container->get(Psr\Log\LoggerInterface::class)
|
$container->get(Psr\Log\LoggerInterface::class)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
PDO::class => function(ContainerInterface $container) {
|
ProVM\Service\Connector::class => function(ContainerInterface $container) {
|
||||||
$database = $container->get('database');
|
$database = $container->get('database');
|
||||||
$retries = $container->get('retries');
|
return new ProVM\Service\Connector(
|
||||||
$r = 0;
|
$database->get('host'),
|
||||||
$exception = null;
|
$database->get('name'),
|
||||||
while($r < $retries) {
|
$database->get('user')->get('name'),
|
||||||
try {
|
$database->get('user')->get('password'),
|
||||||
$dsn = "mysql:host={$database->get('host')};dbname={$database->get('name')}";
|
$container->get('retries'),
|
||||||
return new PDO($dsn, $database->get('user')->get('name'), $database->get('user')->get('password'));
|
$container->get(Psr\Log\LoggerInterface::class)
|
||||||
} 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;
|
|
||||||
},
|
},
|
||||||
ProVM\Service\Repository::class => function(ContainerInterface $container) {
|
ProVM\Service\Repository::class => function(ContainerInterface $container) {
|
||||||
return new ProVM\Service\Repository(
|
return new ProVM\Service\Repository(
|
||||||
$container->get(PDO::class),
|
$container->get(ProVM\Service\Connector::class),
|
||||||
$container->get('database')->get('table'),
|
$container->get('database')->get('table'),
|
||||||
$container->get(Psr\Log\LoggerInterface::class)
|
$container->get(Psr\Log\LoggerInterface::class)
|
||||||
);
|
);
|
||||||
|
@ -6,4 +6,4 @@ services:
|
|||||||
env_file: .env
|
env_file: .env
|
||||||
volumes:
|
volumes:
|
||||||
- ./app:/app
|
- ./app:/app
|
||||||
- ./app/crontab:/var/spool/cron/crontabs/root
|
- ./logs:/logs
|
||||||
|
6
prod.docker-compose.yml
Normal file
6
prod.docker-compose.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
services:
|
||||||
|
remote_ip:
|
||||||
|
container_name: remote_ip
|
||||||
|
build: ./Prod.Dockerfile
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: .env
|
Reference in New Issue
Block a user