mise en place du cron + système de moulinette + init du domaine sur les projets existant

This commit is contained in:
2021-06-02 14:59:41 +02:00
parent 0f517ec402
commit 1954c00b39
17 changed files with 377 additions and 151 deletions

View File

@@ -17,6 +17,7 @@
<file filelist='schedule' name='/etc/apache2/sites-available/schedule' source='schedule-apache.conf' />
<file filelist='schedule' name='/var/www/html/schedule/.env.local' source='schedule-env.local' rm='True'/>
<file filelist='schedule' name='/var/www/html/schedule/scripts/proxy.sh' source='schedule-proxy.sh' rm='True'/>
<file filelist='schedule' name='/etc/cron.d/schedule' source='schedule.cron' rm='True'/>
</container>
</containers>

View File

@@ -30,7 +30,7 @@ APP_ALIAS=schedule
APP_AUTH=MYSQL
APP_NAME=Schedule
APP_ENV=PROD
APP_CRON=false
APP_CRON=true
# Office hours
OFFICE_HOUR_START=09:00

View File

@@ -58,10 +58,11 @@ oneup_uploader:
resource: .
type: uploader
#== Cron ========================================================================================================
#== Cron =================================================================================================================
app_cron:
path: /admin/cron
defaults: { _controller: App\Controller\CronController:list }
defaults: { _controller: App\Controller\CronController:list }
app_cron_ajax_list:
path: /admin/cron/ajax/list
@@ -69,16 +70,20 @@ app_cron_ajax_list:
app_cron_update:
path: /admin/cron/update/{id}
defaults: { _controller: App\Controller\CronController:update }
defaults: { _controller: App\Controller\CronController:update }
app_cron_exec:
path: /admin/cron/exec/{id}
defaults: { _controller: App\Controller\CronController:exec }
defaults: { _controller: App\Controller\CronController:exec }
app_cron_log:
path: /admin/cron/log/{id}
controller: App\Controller\Cron:log
defaults: { id: "cron" }
path: /admin/cron/log
defaults: { _controller: App\Controller\CronController:log }
app_cron_getlog:
path: /admin/cron/getlog/{id}
defaults: { _controller: App\Controller\CronController:getlog }
#== User ========================================================================================================
app_user:

View File

@@ -24,7 +24,11 @@ parameters:
doliActive: '%env(resolve:DOLIBARR_ACTIVE)%'
doliApiKey: '%env(resolve:DOLIBARR_API_KEY)%'
doliUri: '%env(resolve:DOLIBARR_URI)%'
databaseName: '%env(resolve:DATABASE_NAME)%'
databaseUser: '%env(resolve:DATABASE_USER)%'
databasePassword: '%env(resolve:DATABASE_PASSWORD)%'
databaseHost: '%env(resolve:DATABASE_HOST)%'
services:
# default configuration for services in *this* file
_defaults:

View File

@@ -15,6 +15,7 @@ composer install
php bin/console app:AppInit --env=prod
php bin/console app:CronInit --env=prod
php bin/console app:Script --env=prod
# Permissions
./scripts/perm.sh www-data

View File

@@ -15,6 +15,8 @@ use Doctrine\ORM\Id\AssignedGenerator;
use App\Entity\User;
use App\Entity\Nature;
use App\Entity\Domaine;
class AppInitCommand extends Command
@@ -58,6 +60,9 @@ class AppInitCommand extends Command
$this->insertNature(-90,"Non Facturable",false);
$this->insertNature(-80,"Prestation",false);
// Création domaine par défaut
$this->insertDomaine(-100,"Administratif","Administratif");
// Création du compte admin si non existant
$this->insertUser("admin","admin");
@@ -82,6 +87,23 @@ class AppInitCommand extends Command
}
}
protected function insertDomaine($id,$category,$name) {
$metadata = $this->em->getClassMetaData('App:Domaine');
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new AssignedGenerator());
$entity = $this->em->getRepository('App:Domaine')->find($id);
if(!$entity) {
$entity = new Domaine;
$entity->setId($id);
$entity->setName($name);
$entity->setCategory($category);
$this->em->persist($entity);
$this->em->flush();
}
}
protected function insertUser() {
$metadata = $this->em->getClassMetaData('App:User');
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);

View File

@@ -57,94 +57,33 @@ class CronInitCommand extends Command
}
protected function insertCron() {
/*
$metadata = $this->em->getClassMetaData('App:Cron');
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new AssignedGenerator());
// Job Récupératoin la table de référence des articles
// Toute les 1mn
$entity = $this->em->getRepository('App:Cron')->find(10);
// Job Mail
// Toute les minutes
$entity = $this->em->getRepository('App:Cron')->findOneBy(["command"=>"app:sendMail"]);
if(!$entity) {
$entity = new Cron;
$entity->setId(10);
$entity->setCommand("app:CrousGo");
$entity->setDescription("Récupératoin des commandes CROUS & GO");
$entity->setCommand("app:sendMail");
$entity->setDescription("Execution du spool de mail en attente");
$entity->setStatut(2);
$entity->setRepeatcall(0);
$entity->setRepeatexec(0);
$entity->setRepeatinterval(60);
$entity->setNextexecdate($entity->getSubmitdate());
$this->em->persist($entity);
}
// Job Fermeture automatique des guichets
// Toute les 1mn
$entity = $this->em->getRepository('App:Cron')->find(20);
if(!$entity) {
$entity = new Cron;
$entity->setId(20);
$entity->setCommand("app:FermetureGuichet");
$entity->setDescription("Fermeture automatique des guichets");
$entity->setStatut(2);
$entity->setRepeatcall(0);
$entity->setRepeatexec(0);
$entity->setRepeatinterval(60);
$entity->setNextexecdate($entity->getSubmitdate());
$this->em->persist($entity);
}
// Job Récupératoin la table de référence des articles
// Toute les 24h à 3h00
$entity = $this->em->getRepository('App:Cron')->find(1000);
if(!$entity) {
$entity = new Cron;
$nextdate=$entity->getSubmitdate();
$nextdate->setTime(3,0);
$entity->setId(1000);
$entity->setCommand("app:CodeArticle");
$entity->setDescription("Récupératoin la table de référence des articles");
$entity->setStatut(2);
$entity->setRepeatcall(0);
$entity->setRepeatexec(0);
$entity->setRepeatinterval(86400);
$entity->setNextexecdate($nextdate);
$entity->setJsonargument('{"message-limit":"100","env":"prod"}');
$this->em->persist($entity);
}
// Job reinit des piles à 0
// Toute les 24h à 3h00
$entity = $this->em->getRepository('App:Cron')->find(1010);
// Job Dump
// Toute les 24h à 2h00
$entity = $this->em->getRepository('App:Cron')->findOneBy(["command"=>"app:dumpBdd"]);
if(!$entity) {
$entity = new Cron;
$nextdate=$entity->getSubmitdate();
$nextdate->setTime(3,0);
$entity->setId(1010);
$entity->setCommand("app:RazPile");
$entity->setDescription("Remet les piles des services à 0");
$entity->setStatut(2);
$entity->setRepeatcall(0);
$entity->setRepeatexec(0);
$entity->setRepeatinterval(86400);
$entity->setNextexecdate($nextdate);
$this->em->persist($entity);
}
// Job reinit des piles à 0
// Toute les 24h à 3h00
$entity = $this->em->getRepository('App:Cron')->find(1020);
if(!$entity) {
$entity = new Cron;
$nextdate=$entity->getSubmitdate();
$nextdate->setTime(3,0);
$entity->setId(1020);
$entity->setCommand("app:RazCommande");
$entity->setDescription("Cloture et Purge des Commandes");
$nextdate->setTime(2,0);
$entity->setCommand("app:dumpBdd");
$entity->setDescription("Sauvegarde de la BDD");
$entity->setStatut(2);
$entity->setRepeatcall(0);
$entity->setRepeatexec(0);
@@ -152,9 +91,8 @@ class CronInitCommand extends Command
$entity->setNextexecdate($nextdate);
$this->em->persist($entity);
}
// On flush
$this->em->flush();
*/
$this->em->flush();
}
}

View File

@@ -0,0 +1,92 @@
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Security\Core\Encoder\EncoderFactory;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
use Symfony\Component\Finder\Finder;
class DumpBddCommand extends Command
{
private $container;
private $em;
private $output;
private $filesystem;
private $rootlog;
private $byexec;
public function __construct(ContainerInterface $container,EntityManagerInterface $em)
{
parent::__construct();
$this->container = $container;
$this->em = $em;
}
protected function configure()
{
$this
->setName('app:dumpBdd')
->setDescription('Sauvegarde de la BDD')
->setHelp('Sauvegarde de la BDD')
->addArgument('cronid', InputArgument::OPTIONAL, 'ID Cron Job')
->addArgument('lastchance', InputArgument::OPTIONAL, 'Lastchance to run the cron')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->output = $output;
$this->filesystem = new Filesystem();
$this->rootlog = $this->container->get('kernel')->getLogDir()."/";
$alias = $this->container->getParameter('appAlias');
$this->writelnred('');
$this->writelnred('== app:dumpBdd');
$this->writelnred('==========================================================================================================');
$this->datahost = $this->container->getParameter('databaseHost');
$this->database = $this->container->getParameter('databaseName') ;
$this->username = $this->container->getParameter('databaseUser') ;
$this->password = $this->container->getParameter('databasePassword') ;
$cmd = sprintf('mysqldump -h %s -B %s -u %s --password=%s'
, $this->datahost
, $this->database
, $this->username
, $this->password
);
$result = $this->runCommand($cmd);
if($result['exit_status'] == 0) {
$this->filesystem->dumpFile($this->rootlog.$alias.".sql", implode('', $result['output']));
}
$this->writeln('');
return 1;
}
protected function runCommand($command)
{
$command .=" >&1";
exec($command, $output, $exit_status);
return array(
"output" => $output
, "exit_status" => $exit_status
);
}
private function writelnred($string) {
$this->output->writeln('<fg=red>'.$string.'</>');
$this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");
}
private function writeln($string) {
$this->output->writeln($string);
$this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Ramsey\Uuid\Uuid;
use App\Entity\Script;
class ScriptCommand extends Command
{
private $container;
private $em;
private $output;
private $filesystem;
private $rootlog;
public function __construct(ContainerInterface $container,EntityManagerInterface $em)
{
parent::__construct();
$this->container = $container;
$this->em = $em;
}
protected function configure()
{
$this
->setName('app:Script')
->setDescription('Script to call')
->setHelp('Script to call')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->output = $output;
$this->filesystem = new Filesystem();
$this->rootlog = $this->container->get('kernel')->getLogDir()."/";
$output->writeln('APP = Scripts');
$this->callscript("initdomaine");
$output->writeln('');
return 1;
}
private function callscript($name) {
$script=$this->em->getRepository("App:Script")->findOneBy(["name"=>$name]);
if(!$script) {
//$this->writelnred("== SCRIPT = ".$name);
$this->$name();
$script=new Script();
$script->setName($name);
$this->em->persist($script);
$this->em->flush();
$this->writeln("");
}
}
private function initdomaine() {
$domaine=$this->em->getRepository("App:Domaine")->find(-100);
$projects=$this->em->getRepository("App:Project")->findBy(["domaine"=>null]);
foreach($projects as $project) {
$project->setDomaine($domaine);
$this->em->persist($project);
$this->em->flush();
}
}
private function writelnred($string) {
$this->output->writeln('<fg=red>'.$string.'</>');
$this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");
}
private function writeln($string) {
$this->output->writeln($string);
$this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");
}
}

View File

@@ -11,6 +11,8 @@ use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use App\Entity\Cron as Entity;
use App\Form\CronType as Form;
@@ -70,53 +72,27 @@ class CronController extends AbstractController
]);
}
public function execAction(Request $request, $id)
public function log()
{
return $this->render($this->render.'logs.html.twig', [
'useheader' => true,
'usesidebar' => true,
]);
}
public function getlog(Request $request, $id)
{
set_time_limit(0);
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository($this->labelentity)->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find entity.');
}
$kernel = $this->get('kernel');
$application = new Application($kernel);
$application->setAutoExit(false);
$command = $application->find($entity->getCommand());
$jsonparameter=json_decode($entity->getJsonargument(),true);
$parameter = ($jsonparameter?new ArrayInput($jsonparameter):new ArrayInput([]));
$output = new BufferedOutput(OutputInterface::VERBOSITY_NORMAL,false);
$command->run($parameter, $output);
$content = $output->fetch();
return $this->render('CadolesCoreBundle:Core:command.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => true,
"title" => $entity->getDescription(),
"return_path" =>"cadoles_cron_config",
"content" =>$content
]);
}
public function logAction(Request $request, $id)
{
$kernel = $this->get('kernel');
$path = $this->get('kernel')->getRootDir() . '/../var/logs/'.$id.'.log';
$content = file_get_contents($path);
return $this->render('CadolesCronBundle:Cron:logs.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => true,
"title" => "LOG = ".$id,
"content" => $content
]);
}
$path = $this->getParameter('kernel.project_dir');
if($id=="dump")
$file = $path . '/var/log/' . $this->getParameter("appAlias") . '.sql';
else
$file = $path . '/var/log/'.$id.'.log';
$response = new BinaryFileResponse($file);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
return $response;
}
protected function getErrorForm($id,$form,$request,$data,$mode) {

View File

@@ -28,6 +28,12 @@ class Domaine
*/
private $name;
/**
* @ORM\Column(name="category", type="string")
*
*/
private $category;
/**
* @ORM\Column(type="text", nullable=true)
*/
@@ -55,6 +61,13 @@ class Domaine
return $this->id;
}
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
public function getName(): ?string
{
return $this->name;
@@ -138,6 +151,18 @@ class Domaine
}
}
return $this;
}
public function getCategory(): ?string
{
return $this->category;
}
public function setCategory(string $category): self
{
$this->category = $category;
return $this;
}

View File

@@ -0,0 +1,50 @@
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Script
*
* @ORM\Table(name="script")
* @ORM\Entity(repositoryClass="App\Repository\ScriptRepository")
*/
class Script
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", nullable=false)
* @Assert\NotBlank()
*
*/
private $name;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace App\Repository;
use App\Entity\Script;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
class ScriptRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Script::class);
}
}

View File

@@ -5,8 +5,6 @@
JOBS
</h1>
<p><a class="btn btn-success" href={{ path('app_crous_submit') }}>Ajouter</a></p>
<div class="card">
<div class="card-header">
<i class="fa fa-table fa-fw"></i> Liste des Jobs
@@ -18,11 +16,10 @@ JOBS
<thead>
<tr>
<th width="70px" class="no-sort">Action</th>
<th class="no-string">Order</th>
<th>Prochaine exécution</th>
<th>Command</th>
<th>Description</th>
<th>Statut</th>
<th>Prochaine exécution</th>
</tr>
</thead>
<tbody>
@@ -31,11 +28,10 @@ JOBS
<td>
<a href="{{path("app_cron_update",{id:cron.id})}}"><i class="fa fa-file"></i></a>
</td>
<td>{{cron.id}}</td>
<td>{{cron.nextexecdate|date("d/m/Y H:i")}}</td>
<td>{{cron.command}}</td>
<td>{{cron.description}}</td>
<td>{{cron.statutlabel}}</td>
<td>{{cron.nextexecdate|date("m/d/Y H:i")}}</td>
</tr>
{% endfor %}
</tbody>

View File

@@ -1,19 +1,16 @@
{% extends "CRWhizBundle::base.html.twig" %}
{% extends 'base.html.twig' %}
{% block body %}
<h1 class="page-header">{{ title }}</h1>
<h1 class="page-header">
Télécharger les logs
</h1>
<a class="btn btn-default" href={{ path("cadoles_cron_config_log",{"id":"cron"}) }}>Log CRON</a>
<a class="btn btn-default" href={{ path("cadoles_cron_config_log",{"id":"prod"}) }}>Log PROD</a>
<a class="btn btn-default" href={{ path("cadoles_cron_config_log",{"id":"dev"}) }}>Log DEV</a>
<br><br>
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-pencil fa-fw"></i> Logs
</div>
<div class="panel-body">
{{ content | nl2br }}
</div>
</div>
{% if appCron %}
<a class="btn btn-secondary" href={{ path("app_cron_getlog",{"id":"cron"}) }}>Log CRON</a>
{% endif %}
<a class="btn btn-secondary" href={{ path("app_cron_getlog",{"id":"prod"}) }}>Log PROD</a>
<a class="btn btn-secondary" href={{ path("app_cron_getlog",{"id":"dev"}) }}>Log DEV</a>
{% if appCron %}
<a class="btn btn-secondary" href={{ path("app_cron_getlog",{"id":"dump"}) }}>Dump de la Base</a>
{% endif %}
{% endblock %}

View File

@@ -486,6 +486,21 @@
</a>
</li>
{% if appCron %}
<li class="title">Outils</li>
<li>
<a href="{{path("app_cron")}}">
<i class="fa fa-cogs"></i>Jobs
</a>
</li>
<li class="last">
<a href="{{path("app_cron_log")}}">
<i class="fa fa-list-alt"></i>Logs / Dump
</a>
</li>
{% endif %}
{% endif %}
</ul>
</div>

1
tmpl/schedule.cron Normal file
View File

@@ -0,0 +1 @@
* * * * * root /var/www/html/schedule/scripts/cron.sh &>/dev/null