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='/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/.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='/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> </container>
</containers> </containers>

View File

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

View File

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

View File

@@ -24,7 +24,11 @@ parameters:
doliActive: '%env(resolve:DOLIBARR_ACTIVE)%' doliActive: '%env(resolve:DOLIBARR_ACTIVE)%'
doliApiKey: '%env(resolve:DOLIBARR_API_KEY)%' doliApiKey: '%env(resolve:DOLIBARR_API_KEY)%'
doliUri: '%env(resolve:DOLIBARR_URI)%' 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: services:
# default configuration for services in *this* file # default configuration for services in *this* file
_defaults: _defaults:

View File

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

View File

@@ -15,6 +15,8 @@ use Doctrine\ORM\Id\AssignedGenerator;
use App\Entity\User; use App\Entity\User;
use App\Entity\Nature; use App\Entity\Nature;
use App\Entity\Domaine;
class AppInitCommand extends Command class AppInitCommand extends Command
@@ -58,6 +60,9 @@ class AppInitCommand extends Command
$this->insertNature(-90,"Non Facturable",false); $this->insertNature(-90,"Non Facturable",false);
$this->insertNature(-80,"Prestation",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 // Création du compte admin si non existant
$this->insertUser("admin","admin"); $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() { protected function insertUser() {
$metadata = $this->em->getClassMetaData('App:User'); $metadata = $this->em->getClassMetaData('App:User');
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE); $metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);

View File

@@ -57,94 +57,33 @@ class CronInitCommand extends Command
} }
protected function insertCron() { protected function insertCron() {
/*
$metadata = $this->em->getClassMetaData('App:Cron'); $metadata = $this->em->getClassMetaData('App:Cron');
$metadata->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_NONE);
$metadata->setIdGenerator(new AssignedGenerator());
// Job Mail
// Job Récupératoin la table de référence des articles // Toute les minutes
// Toute les 1mn $entity = $this->em->getRepository('App:Cron')->findOneBy(["command"=>"app:sendMail"]);
$entity = $this->em->getRepository('App:Cron')->find(10);
if(!$entity) { if(!$entity) {
$entity = new Cron; $entity = new Cron;
$entity->setId(10); $entity->setCommand("app:sendMail");
$entity->setCommand("app:CrousGo"); $entity->setDescription("Execution du spool de mail en attente");
$entity->setDescription("Récupératoin des commandes CROUS & GO");
$entity->setStatut(2); $entity->setStatut(2);
$entity->setRepeatcall(0); $entity->setRepeatcall(0);
$entity->setRepeatexec(0); $entity->setRepeatexec(0);
$entity->setRepeatinterval(60); $entity->setRepeatinterval(60);
$entity->setNextexecdate($entity->getSubmitdate()); $entity->setNextexecdate($entity->getSubmitdate());
$this->em->persist($entity); $entity->setJsonargument('{"message-limit":"100","env":"prod"}');
}
// 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);
$this->em->persist($entity); $this->em->persist($entity);
} }
// Job reinit des piles à 0 // Job Dump
// Toute les 24h à 3h00 // Toute les 24h à 2h00
$entity = $this->em->getRepository('App:Cron')->find(1010); $entity = $this->em->getRepository('App:Cron')->findOneBy(["command"=>"app:dumpBdd"]);
if(!$entity) { if(!$entity) {
$entity = new Cron; $entity = new Cron;
$nextdate=$entity->getSubmitdate(); $nextdate=$entity->getSubmitdate();
$nextdate->setTime(3,0); $nextdate->setTime(2,0);
$entity->setCommand("app:dumpBdd");
$entity->setId(1010); $entity->setDescription("Sauvegarde de la BDD");
$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");
$entity->setStatut(2); $entity->setStatut(2);
$entity->setRepeatcall(0); $entity->setRepeatcall(0);
$entity->setRepeatexec(0); $entity->setRepeatexec(0);
@@ -152,9 +91,8 @@ class CronInitCommand extends Command
$entity->setNextexecdate($nextdate); $entity->setNextexecdate($nextdate);
$this->em->persist($entity); $this->em->persist($entity);
} }
// On flush // 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\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use App\Entity\Cron as Entity; use App\Entity\Cron as Entity;
use App\Form\CronType as Form; 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(); $path = $this->getParameter('kernel.project_dir');
$entity = $em->getRepository($this->labelentity)->find($id); if($id=="dump")
$file = $path . '/var/log/' . $this->getParameter("appAlias") . '.sql';
if (!$entity) { else
throw $this->createNotFoundException('Unable to find entity.'); $file = $path . '/var/log/'.$id.'.log';
}
$response = new BinaryFileResponse($file);
$kernel = $this->get('kernel'); $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
$application = new Application($kernel); return $response;
$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
]);
}
protected function getErrorForm($id,$form,$request,$data,$mode) { protected function getErrorForm($id,$form,$request,$data,$mode) {

View File

@@ -28,6 +28,12 @@ class Domaine
*/ */
private $name; private $name;
/**
* @ORM\Column(name="category", type="string")
*
*/
private $category;
/** /**
* @ORM\Column(type="text", nullable=true) * @ORM\Column(type="text", nullable=true)
*/ */
@@ -55,6 +61,13 @@ class Domaine
return $this->id; return $this->id;
} }
public function setId(int $id): self
{
$this->id = $id;
return $this;
}
public function getName(): ?string public function getName(): ?string
{ {
return $this->name; 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; 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 JOBS
</h1> </h1>
<p><a class="btn btn-success" href={{ path('app_crous_submit') }}>Ajouter</a></p>
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<i class="fa fa-table fa-fw"></i> Liste des Jobs <i class="fa fa-table fa-fw"></i> Liste des Jobs
@@ -18,11 +16,10 @@ JOBS
<thead> <thead>
<tr> <tr>
<th width="70px" class="no-sort">Action</th> <th width="70px" class="no-sort">Action</th>
<th class="no-string">Order</th> <th>Prochaine exécution</th>
<th>Command</th> <th>Command</th>
<th>Description</th> <th>Description</th>
<th>Statut</th> <th>Statut</th>
<th>Prochaine exécution</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -31,11 +28,10 @@ JOBS
<td> <td>
<a href="{{path("app_cron_update",{id:cron.id})}}"><i class="fa fa-file"></i></a> <a href="{{path("app_cron_update",{id:cron.id})}}"><i class="fa fa-file"></i></a>
</td> </td>
<td>{{cron.id}}</td> <td>{{cron.nextexecdate|date("d/m/Y H:i")}}</td>
<td>{{cron.command}}</td> <td>{{cron.command}}</td>
<td>{{cron.description}}</td> <td>{{cron.description}}</td>
<td>{{cron.statutlabel}}</td> <td>{{cron.statutlabel}}</td>
<td>{{cron.nextexecdate|date("m/d/Y H:i")}}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

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

View File

@@ -486,6 +486,21 @@
</a> </a>
</li> </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 %} {% endif %}
</ul> </ul>
</div> </div>

1
tmpl/schedule.cron Normal file
View File

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