La migration des données depuis Ecoloweb se fait via une commande CLI (command line interface) de Django.
Les exports de données nous sont transmis au format .pgsql
. Pour pouvoir les charger
sur la base @ Scalingo, le seul moyen stable est de créer un tunnel SSH.
Une fois celui-ci en place, il reste à supprimer les tables existantes et importer
le fichier de dump:
DB_URL=postgres://<user>:<password>@localhost:10000/<dbname>
for table in $(psql "${DB_URL}" -t -c "SELECT \"tablename\" FROM pg_tables WHERE schemaname='ecolo'"); do
psql "${DB_URL}" -c "DROP TABLE IF EXISTS \"${table}\" CASCADE;"
done
pg_restore -d "${DB_URL}" --clean --no-acl --no-owner --no-privileges <fichier_dump>.pgsql
Sur Ecoloweb, les informations clefs et pérennes d'une convention sont gardées éternellement dans la table ecolo_conventionapl
.
On y trouve par exemple le numéro, l'administration qui en est à l'origine et globalement toutes les infos inaltérables.
Pour autant une convention évolue avec le temps, en étant soit reconduite sur une nouvelle période, soit altérée via
un avenant. Chaque altération crée une nouvelle entrée dans la table ecolo_conventiondonneesgenerales
. Ces données
générales incluent les dates de début et de fin, une éventuelle référence vers la table ecolo_avenant
, toutes les
dates d'évènements d'envoi, signature, publication ou encore le notaire ou le bureau CAF concerné. Surtout, à chaque
donnée générale sont associées des ecolo_programmelogement
, eux-mêmes constitués de ecolo_logement
et ecolo_annexe
,
soit plus largement des infos détaillant le contenu de ce qui est conventionné.
On peut donc obtenir rapidement le détail de toutes les altérations successives d'une convention en examinant le contenu
derrière chaque donnée générale liée à une même ecolo_conventiondonneesgenerales.conventionapl_id
.
La commande se nomme ecoloweb_import_departement
est lancée via Django (i.e. manage.py
).
Un accès en lecture seule à une base de données est nécessaire via la variable d'environnement ECOLO_DATABASE_URL
qui
reste optionnelle sur le reste du projet.
L'ensemble des requêtes effectuées au cours d'un import n'est pas joué au sein d'une transaction SQL. Il est cependant
possible de le faire via l'option --use-transaction
. En outre, un système de références est mis en place pour éviter
d'importer 2 fois une donnée vers la base APiLos.
Pour lancer l'import des conventions sur un département, il faut ajouter le code INSEE de celui-ci en argument:
# Importer les données des Bouches du Rhône:
./manage.py ecoloweb_import_departement 13
# Importer les données de la Haute Corse
./manage.py ecoloweb_import_departement 2B
D'autres options, réellement optionnelles celles-ci, sont disponibles:
--no-progress
: ne pas afficher la barre de progression dynamique (utile pour analyser les logs depuis Scalingo)--debug
: affiche des informations supplémentaires au développeur (à conjuguer avec l'option--no-progress
)--setup
: supprime et recrée la materialized viewecolo_conventionhistorique
, en charge de retranscrire l'historique Ecolo vers celui d'Apilos. Comme cette étape est assez longue, cette option n'est utile qu'après un changement de structure de cette view ou après l'import d'un dump de base de données Ecolo--update
: si une convention a déjà été importée depuis Ecolo, et non supprimée depuis, cette option force la mise à jour des données sur Apilos avec celles issues d'Ecoloweb (⚠️ tout changement survenu entre temps sera écrasé)
Puisque le lancement d'un import sur un département peut durer entre plusieurs dizaines de minutes et quelques heures, il va nous falloir suivre la (très bonne) documentation concernant les "detached on-off" containers.
Ex: pour lancer l'import des Bouches du Rhône :
scalingo --app <app> run --detached 'python ./manage.py ecoloweb_import_departement 13 --no-progress'
Scaling va alors répondre avec un message comme suit :
Starting one-off 'python ./manage.py ecoloweb_import_departement 13 --no-progress' for app '<app>'.
Run `scalingo --region <region> --app <app> logs --filter one-off-<number>` to get the output
Le processus est ainsi lancé jusqu'à la fin de l'import qui fermera le conteneur.
On peut malgré tout toujours opérer dessus :
# Afficher les conteneurs en cours:
scalingo --app <app> ps
# Voir les logs du conteneur:
scalingo --app <app> logs --filter one-off-<number> -f
# Stopper manuellement le conteneur:
scalingo --app <app> one-off-stop one-off-<number>
2 prérequis sont nécessaires pour pouvoir exécuter les tests unitaires:
- déclarer un accès à la base de données Ecoloweb via la variable
ECOLOWEB_DB_URL
- ramener depuis le bucket S3 dédié les fichiers SQL de création et d'alimentation de cette base de données
Pour cette seconde étape, il faut au préalable utiliser la commande aws
pour récupérer
la version la plus à jour:
aws s3 sync <S3_BUCKET> ecoloweb/tests/resources/
Ce bucket est structuré de cette façon:
- un répertoire
sql
contenant toutes les requêtes de création des tables (ddl
ou Data Definition Language) ainsi que l'alimentation de celles-ci (dcl
ou Data Creation Language) - un autre répertoire
sources
contenant les requêtes qui ont permis l'extraction de certaines données depuis une source existante. Ces requête sont utiles pour isoler les requêtes de DCL, en conjonction de la fonction d'"Export as SQL inserts" des IDEs Jetbrain
Si jamais vous éditez ces fichiers, pensez à bien les synchroniser sur le bucket S3:
aws s3 sync --delete ecoloweb/tests/resources/ <S3_BUCKET>
# se connecter à la base de données via le CLI Scalingo
scalingo -a <app> pgsql-console
À noter : \dt
ne retourne aucune table, c'est normal.
Par exemple à partir de l'uuid d'une convention, en se connectant au django shell
from conventions.models import Convention
from ecoloweb.models import EcoloReference
convention_id = Convention.objects.get(uuid="c8e67014-14db-4cb2-bd28-6db24bb6cabc").id
EcoloReference.objects.get(apilos_model="conventions.Convention", apilos_id=convention_id).ecolo_id
# '12345678:PLAI:0'
Dans l'exemple ci-dessus, le première partie de l'id avant le premier :
est à utiliser dans la requête ci-dessous :
SELECT vps.*
from ecolo.ecolo_conventionhistorique ch
inner join ecolo.ecolo_conventiondonneesgenerales cdg on cdg.id = ch.conventiondonneesgenerales_id
inner join ecolo.ecolo_valeurparamstatic vps on vps.id = cdg.etatconvention_id
where ch.conventionapl_id = '12345678';