Skip to main content

Declarative Infrastructure as Code (IaC) for Odoo via XML-RPC

Project description

Odoo Online Deploy (ood) — Infrastructure as Code (IaC)

Python Version Odoo Compatibility IaC Paradigm

Ce package Python, nommé Odoo Online Deploy (ood), implémente un moteur de configuration et de personnalisation Infrastructure as Code (IaC) inspiré du fonctionnement de Terraform pour n'importe quelle instance d'ERP Odoo (y compris les instances Odoo Online, On-Premise ou Odoo.sh).

Grâce à ce moteur, vous pouvez déclarer la structure de votre base de données, vos règles de sécurité, vos vues utilisateur, vos automatisations et vos crons dans un fichier déclaratif YAML unique (main.ood), puis les appliquer de façon déterministe, ordonnée et idempotente via XML-RPC.


🏗️ Architecture du Système

Le moteur IaC orchestre le cycle de vie de vos personnalisations à travers trois fichiers clés :

  [ main.ood ]       [ variables.ood ]       [ ood.oodstate ]
(Configurations)    (Paramètres/Secrets)     (État local JSON)
       │                     │                     │
       └─────────────┬───────┴─────────────────────┘
                     ▼
              [ Moteur CLI ood ]
                     │
                     ▼
           { Compilateur de Diff }
                     │  (Analyse comparative)
                     ▼
         [ Arbre d'actions (Diff) ]   ──►  + create, ~ update, - destroy
                     │  (Approbation utilisateur)
                     ▼
           [ Handlers XML-RPC ]
                     │  (Modifications ordonnées)
                     ▼
        [( Instance Odoo 18 / 19 )]
                     │
                     ▼  (Enregistrement des IDs Odoo)
              [ ood.oodstate ]
  • main.ood : Fichier YAML décrivant l'ensemble de votre infrastructure et de vos personnalisations (applications, champs, règles de sécurité, automatisations).
  • variables.ood : Fichier contenant les variables d'environnement locales et les secrets de connexion.
  • ood.oodstate : Fichier d'état local auto-généré (analogue à un fichier terraform.tfstate) qui conserve la trace des identifiants uniques (IDs) des ressources créées pour assurer l'idempotence et les suppressions propres.

⚙️ Installation

1. Prérequis

Assurez-vous de disposer de Python >= 3.8.

2. Installation depuis PyPI (Production)

Pour installer l'outil globalement ou au sein de votre projet :

pip install ood-cli

3. Installation locale pour le développement (Mode Éditable)

Si vous modifiez directement le code source du projet :

# Créez et activez un environnement virtuel (optionnel mais fortement recommandé)
python3 -m venv venv
source venv/bin/activate

# Installation en mode éditable
pip install -e .

Cette commande installe les dépendances requises et enregistre un point d'entrée global dans votre terminal. Vous pouvez désormais lancer le moteur en saisissant la commande :

ood --help

🚀 Workflow d'Exécution (Terraform-like)

Étape 1 : Initialisation (ood init)

Initialise le répertoire de travail, teste la validité des paramètres de connexion à l'instance Odoo cible et génère un fichier ood.oodstate vide s'il n'existe pas.

ood init

Étape 2 : Comparaison et Prévisualisation (ood plan)

Compare les déclarations du fichier main.ood avec l'état enregistré dans ood.oodstate. Le moteur compile un arbre de différences (diff) ordonné selon les dépendances et affiche un aperçu coloré des actions à effectuer :

  • + create : Ressources déclarées dans la configuration mais absentes de l'état.
  • ~ update : Ressources modifiées (par exemple, code d'un cron ou d'une action serveur mis à jour).
  • - destroy : Ressources supprimées du fichier main.ood mais toujours présentes dans l'état (le moteur les désinstalle proprement d'Odoo).
ood plan

Étape 3 : Application des Changements (ood apply)

Valide le plan, demande confirmation à l'utilisateur (sauf si --auto-approve est fourni), applique les modifications dans l'ordre strict des dépendances et met à jour le fichier d'état avec les identifiants réels renvoyés par la base de données.

ood apply
# ou pour une exécution automatisée (ex: CI/CD)
ood apply --auto-approve

Étape 4 : Destruction Complète (ood destroy)

Wipe et nettoie l'intégralité des personnalisations créées en les supprimant proprement en base d'Odoo en ordre inverse de dépendance, afin de restituer une instance parfaitement propre.

ood destroy
# ou sans confirmation manuelle
ood destroy --auto-approve

📝 Guide de la Gestion des Variables et Secrets (variables.ood)

Le fichier variables.ood centralise les secrets et les valeurs d'interpolation dynamique de votre projet. Les valeurs y sont injectées au sein de vos configurations via la syntaxe ${MA_VARIABLE}.

1. Variables globales et modulaires

  • Fichier global : Un fichier variables.ood à la racine de votre workspace définit les paramètres généraux (configurations de connexion, etc.).
  • Fichiers locaux : Lorsque vous découpez vos configurations dans des sous-dossiers (voir section include ci-dessous), vous pouvez placer un fichier variables.ood local au sein de chaque dossier fonctionnel (ex : modules/sales/variables.ood). Le moteur IaC compile automatiquement l'ensemble de ces fichiers pour alimenter l'interpolation.

2. Sécurité contre les collisions de noms (Validation stricte)

Pour éviter qu'une variable ne soit écrasée par inadvertance, le moteur effectue une validation de sécurité stricte lors du chargement. Si une même clé de variable est déclarée dans plus d'un fichier variables.ood, l'initialisation s'interrompt immédiatement en levant une erreur descriptive indiquant les chemins exacts en conflit :

Error: Failed to load and compile configuration: La variable 'MON_SECRET' est déclarée plusieurs fois : dans 'variables.ood' et dans 'modules/sales/variables.ood'.

Exemple standard :

# variables.ood
ODOO_URL: "http://localhost:8069"
ODOO_DB: "odoo"
ODOO_LOGIN: "admin"
ODOO_PASSWORD: "mon_api_key_ou_password"
ODOO_VERSION: "19.0"  # Permet d'adapter les syntaxes XML et sécurité (18.0 ou 19.0)

🛠️ Spécifications du fichier main.ood

Le fichier main.ood est structuré autour de trois sections principales :

  1. connection : Référence les paramètres de connexion à l'instance Odoo (généralement interpolés depuis variables.ood).
  2. include (Optionnel) : Une liste de motifs de chemins (glob patterns) pour importer des sous-fichiers de configuration .ood de façon modulaire et ordonnée.
  3. resources : Une liste d'objets YAML définissant les composants à provisionner directement dans ce fichier.

📁 Découpage Modulaire via la Balise include

Pour des projets complexes, vous pouvez éclater vos ressources dans des sous-fichiers configurables. Les chemins sont résolus relativement au dossier du fichier déclarant l'inclusion. Le moteur supporte la recherche par jokers (wildcards globbing) et les inclusions récursives.

# main.ood
connection:
  url: "${ODOO_URL}"
  db: "${ODOO_DB}"
  username: "${ODOO_LOGIN}"
  password: "${ODOO_PASSWORD}"
  odoo_version: "${ODOO_VERSION}"

include:
  - "modules/security/*.ood"
  - "modules/sales/**/*.ood"

resources:
  - type: app
    name: base

Les ressources importées sont compilées et insérées avant les ressources déclarées localement. De plus, toutes les variables définies dans les fichiers variables.ood locaux aux dossiers importés sont compilées et appliquées à l'ensemble du projet.

📋 Types de Ressources Supportés (Règles syntaxiques)

Voici la liste exhaustive des types de ressources configurables, avec leur ordre de déploiement topologique :

Ordre Type (type) Modèle Odoo cible Description
1 app ir.module.module Installe une application ou un module du catalogue natif.
2 privilege res.groups.privilege Définit une catégorie de privilège (spécifique Odoo 19).
3 group res.groups Gère les groupes de sécurité, l'héritage (implied) et les privilèges.
4 model ir.model Crée un nouveau modèle de données personnalisé (avec auto-correction du préfixe x_ et gestion des mixins comme Chatter ou Activités via inherit).
5 field ir.model.fields Crée des champs personnalisés de type standard (char, float, selection, many2one...) ou calculés (compute).
6 acl ir.model.access Renseigne les droits de CRUD au niveau du modèle d'objet pour un groupe donné.
7 rule ir.rule Applique des filtres de sécurité ligne par ligne (domaines de restriction dynamic).
8 server_action ir.actions.server Déploie des scripts Python exécutés côté serveur.
9 base_automation base.automation Lie un trigger événementiel (on_write, on_create) à un script serveur.
10 cron ir.cron Programme des exécutions régulières et répétées de scripts Python.
11 view ir.ui.view Hérite/surcharge des vues standard XML ou crée des templates QWeb autonomes (ex : pages web).
12 window_action_filter ir.actions.act_window Injecte dynamiquement des filtres par défaut au niveau du contexte d'une action.
13 website_page website.page Crée une page web dynamique publique liée à un template QWeb.
14 attachment ir.attachment Stocke des fichiers bruts (CSS, SCSS, JS, OWL) sous forme de pièces jointes binaires à URL virtuelle.
15 asset ir.asset Enregistre et lie des pièces jointes à des bundles d'assets Odoo pour compilation et rendu direct.
16 record Modèle variable Modifie ou crée des enregistrements de données (valeurs de champs) de façon idempotente (recherche par ID, XML-ID ou domaine).

📖 Dictionnaire des Ressources et Exemples YAML

1. Applications (app)

Installe un module d'Odoo s'il n'est pas encore présent.

  • Balises requises :
    • name : Nom technique du module dans le catalogue d'Odoo (ex : sale_management, crm).
- type: app
  name: sale_management

2. Privilèges (privilege)

Crée un profil de privilèges applicatifs pour la sécurité (Introduit en Odoo 19). Géré avec repli transparent automatique vers category_id sur Odoo 18.

  • Balises requises :
    • name : Identifiant local unique de la ressource.
    • privilege_name : Nom affiché de la règle de privilège dans le menu.
    • category_xml_id : Lien XML-ID vers la catégorie d'app Odoo parente (ex : base.module_category_all).
- type: privilege
  name: contacts_privilege
  privilege_name: "Contacts"
  category_xml_id: "base.module_category_all"

3. Groupes de sécurité (group)

Définit un groupe d'utilisateurs avec héritage de droits d'autres groupes.

  • Balises requises :
    • name : Identifiant local unique.
    • group_name : Libellé utilisateur du groupe dans l'interface Odoo.
  • Balises optionnelles :
    • privilege_name : Lien vers le privilège déclaratif créé ci-dessus.
    • implied_xml_ids : Liste des groupes parents dont ce groupe hérite les droits (ex: base.group_user ou d'autres groupes personnalisés).
- type: group
  name: contacts_user_group
  group_name: "Contacts / Utilisateur"
  privilege_name: "contacts_privilege"
  implied_xml_ids:
    - "base.group_user"

4. Champs personnalisés (field)

Étend la structure des bases de données Odoo. Supporte les champs liés (related), les sélections et les champs calculés complexes (compute) persistés en base.

  • Balises requises :
    • name : Identifiant unique.
    • model : Nom technique du modèle Odoo à étendre (ex : res.partner).
    • field_name : Nom technique du champ (doit obligatoirement commencer par x_).
    • ttype : Type de données (char, float, boolean, date, selection, many2one).
    • field_description : Libellé affiché à l'écran.
  • Balises optionnelles :
    • relation : Modèle de liaison (requis si ttype: many2one).
    • selection : Liste de tuples au format chaîne de caractères Python (requis si ttype: selection).
    • related : Chemin du champ lié (ex : partner_id.x_first_name).
    • compute : Code Python s'exécutant pour alimenter le champ de façon automatique.
    • depends : Liste des champs déclenchant le calcul du compute.
    • store : Booléen déterminant si la valeur calculée est stockée physiquement en base (true ou false).
    • readonly : Empêche la modification manuelle par l'utilisateur.
# Champ de sélection simple
- type: field
  name: res_partner_x_type_contrat_habituel
  model: res.partner
  field_name: x_type_contrat_habituel
  ttype: selection
  selection: "[('regie', 'Régie'), ('forfait', 'Forfait'), ('accord_cadre', 'Accord-Cadre')]"
  field_description: "Type de contrat habituel"

# Champ calculé stocké en base
- type: field
  name: product_template_x_productivite_heure
  model: product.template
  field_name: x_productivite_heure
  ttype: float
  field_description: "Productivité heure"
  compute: |
    for record in self:
        record['x_productivite_heure'] = round((record.x_productivite_jour or 0.0) / 7.0, 1)
  depends: "x_productivite_jour"
  store: true
  readonly: true

5. Droits d'accès (acl)

Définit les autorisations de lecture, d'écriture, de création et de suppression (CRUD) sur un modèle Odoo pour un groupe donné.

  • Balises requises :
    • name : Identifiant local unique.
    • acl_name : Nom descriptif de la règle ACL.
    • model : Nom technique du modèle ciblé.
    • group_name : Identifiant du groupe de sécurité personnalisé associé (ou XML-ID global).
    • perm_read, perm_write, perm_create, perm_unlink : Valeurs booléennes (true ou false).
- type: acl
  name: contacts_user_acl
  acl_name: "Contacts User"
  model: res.partner
  group_name: "contacts_user_group"
  perm_read: true
  perm_write: true
  perm_create: false
  perm_unlink: false

6. Règles d'enregistrement (rule)

Fournit une sécurité dynamique au niveau de la ligne de données en utilisant les expressions de filtre Odoo (Domaines).

  • Balises requises :
    • name : Identifiant local unique.
    • rule_name : Titre explicite de la règle de sécurité.
    • model : Modèle Odoo ciblé.
    • domain_force : Expression de filtre dynamique au format chaîne (ex : structure de tuples Odoo).
  • Balises optionnelles :
    • group_name : Groupe de sécurité limitant la portée de la règle (si absent, la règle devient globale à tous les utilisateurs).
    • perm_read, perm_write, perm_create, perm_unlink : Portée des opérations soumises à la restriction.
- type: rule
  name: crm_user_rule
  rule_name: "CRM Lead / Utilisateur"
  model: crm.lead
  group_name: "crm_user_group"
  domain_force: "['|', ('user_id', '=', user.id), ('message_partner_ids', 'in', [user.partner_id.id])]"
  perm_read: true
  perm_write: true
  perm_create: false
  perm_unlink: false

7. Actions Serveur (server_action)

Déploie un bloc de code Python à exécuter à la demande ou via une automatisation.

  • Balises requises :
    • name : Identifiant local unique.
    • action_name : Libellé descriptif de l'action de serveur.
    • model : Modèle d'évaluation principal.
    • code : Script Python complet.
- type: server_action
  name: won_crm_lead_sa
  action_name: "Action: Won CRM Lead on Sales Order confirmed"
  model: sale.order
  code: |
    for record in records:
        if record.opportunity_id:
            record.opportunity_id.action_set_won()

8. Règles d'automatisation (base_automation)

Orchestre l'exécution d'actions de serveur à la suite de modifications en base.

  • Balises requises :
    • name : Identifiant local unique.
    • rule_name : Nom explicite de l'automatisation.
    • model : Modèle de données surveillé.
    • trigger : Type d'événement déclencheur (on_create_or_write, on_write, on_create).
    • server_actions : Liste des actions serveur (par leur identifiant déclaratif) à lancer.
  • Balises optionnelles :
    • trigger_fields : Liste des champs techniques dont la mise à jour déclenche la règle.
- type: base_automation
  name: won_crm_lead_rule
  rule_name: "Won CRM Lead on Sales Order confirmed"
  model: sale.order
  trigger: on_create_or_write
  trigger_fields:
    - state
  server_actions:
    - won_crm_lead_sa

9. Tâches Planifiées (cron)

Planifie l'exécution cyclique de scripts Python côté serveur. Le moteur IaC gère automatiquement la création/mise à jour synchronisée de la tâche planifiée et de son action serveur interne.

  • Balises requises :
    • name : Identifiant local unique.
    • cron_name : Intitulé compréhensible dans le menu des crons.
    • model : Modèle d'exécution.
    • code : Code Python exécuté périodiquement.
  • Balises optionnelles :
    • interval_number : Fréquence d'exécution (défaut : 1).
    • interval_type : Unité de temps (minutes, hours, days, weeks, months).
- type: cron
  name: crm_inactivity_cron
  cron_name: "Cron CRM : Alerte inactivité 15j"
  model: crm.lead
  code: |
    limit_date_start = datetime.datetime.now() - datetime.timedelta(days=16)
    limit_date_end = datetime.datetime.now() - datetime.timedelta(days=15)
    leads = env['crm.lead'].search([
        ('stage_id', 'in', [3, 8, 9]),
        ('write_date', '>=', limit_date_start),
        ('write_date', '<=', limit_date_end),
    ])
    for record in leads:
        # Code d'alerte ou de notification...
  interval_number: 1
  interval_type: "days"

10. Vues utilisateur (view)

Surcharge et hérite de l'architecture des vues Odoo via XPath sans réécriture complète. Le moteur IaC compile et traduit automatiquement les balises de structure de carte en fonction de la version majeure d'Odoo ciblée (par exemple, traduction dynamique bidirectionnelle entre <kanban-box> et <card> pour les vues Kanban Odoo 18 / 19).

  • Balises requises :
    • name : Identifiant local unique.
    • view_name : Nom d'identification technique de la vue.
    • model : Modèle Odoo auquel la vue est rattachée.
    • inherit_xml_id : XML-ID de la vue parente héritée (ex : base.view_partner_form).
    • arch : Structure de modification XML / XPath.
  • Balises optionnelles :
    • priority : Priorité de chargement de la vue (défaut : 16).
- type: view
  name: res_company_form_mycompany
  view_name: "res.company.form.mycompany"
  model: res.company
  inherit_xml_id: "base.view_company_form"
  priority: 16
  arch: |
    <data>
        <xpath expr="//field[@name='company_registry']" position="after">
            <field name="x_forme_juridique" string="Forme juridique"/>
            <field name="x_capital_social" string="Capital social"/>
        </xpath>
    </data>

11. Filtres d'actions (window_action_filter)

Injecte dynamiquement des critères de recherche par défaut lors de l'ouverture de menus ou de fenêtres standard d'Odoo.

  • Balises requises :
    • name : Identifiant unique de la ressource.
    • xml_id : XML-ID de l'action de fenêtre parente à altérer (ex : account.action_move_out_invoice_type).
    • filter_key : Clé de filtre de recherche par défaut (ex : search_default_late).
    • filter_value : Valeur d'activation du filtre (généralement 1 pour vrai).
- type: window_action_filter
  name: invoicing_out_invoice_filter_main
  xml_id: "account.action_move_out_invoice_type"
  filter_key: "search_default_late"
  filter_value: 1

12. Modèles de Données Personnalisés (model)

Crée un nouveau modèle de données en base. Le moteur applique une auto-correction automatique pour garantir le préfixe obligatoire x_ sur les modèles personnalisés en base, et supporte les listes d'héritage standard (inherit) avec mappage automatique des fonctionnalités transverses Odoo (Chatter/messagerie via mail.thread, activités planifiées via mail.activity.mixin, etc.).

  • Balises requises :
    • name : Identifiant unique local du modèle (auto-corrigé avec préfixe x_ en base de données si nécessaire).
    • model_name : Libellé utilisateur du modèle affiché dans l'interface Odoo.
  • Balises optionnelles :
    • inherit : Liste de modèles Odoo de type mixin dont on souhaite hériter (ex : mail.thread, mail.activity.mixin, mail.blacklist, mail.thread.sms).
- type: model
  name: x_test_iac_model
  model_name: "Modèle de Test IaC"
  inherit:
    - "mail.thread"
    - "mail.activity.mixin"

13. Pages Web (website_page)

Crée et publie des pages web publiques ou privées sur le portail Odoo.

  • Balises requises :
    • name : Identifiant local de la ressource.
    • url : Route HTTP publique d'accès à la page (ex : /test-iac-page).
    • view_ref : Identifiant local unique (ou XML-ID) du template QWeb décrivant la structure HTML de la page (de type view).
  • Balises optionnelles :
    • is_published : Rend la page immédiatement visible aux visiteurs publics (true ou false).
    • website_indexed : Autorise l'indexation de la page par les moteurs de recherche (true ou false).
- type: website_page
  name: test_iac_website_page
  url: "/test-iac-page"
  view_ref: test_iac_page_template
  is_published: true
  website_indexed: true

14. Pièces Jointes Binaires (attachment)

Permet d'héberger des fichiers arbitraires (images, PDF, ou code source comme CSS, SCSS, JS) en base de données avec des URLs virtuelles d'accès. Utile pour injecter des scripts et styles personnalisés.

  • Balises requises :
    • name : Nom affiché du fichier dans la gestion documentaire Odoo.
    • url : URL virtuelle relative d'accès pour appeler le fichier depuis un template ou un bundle (ex : /test_iac/static/src/scss/test_style.scss).
    • mimetype : Type MIME du fichier (ex : text/css, text/scss, application/javascript).
    • raw_content : Code brut ou contenu texte du fichier (le moteur l'encode automatiquement en Base64 pour le stockage binaire).
- type: attachment
  name: test_iac_custom_style
  url: "/test_iac/static/src/scss/test_style.scss"
  mimetype: "text/scss"
  raw_content: |
    .my-dynamic-style {
        background-color: #f9fafb !important;
        border: 3px dashed #10b981 !important;
        border-radius: 12px;
        padding: 30px;
        transition: all 0.3s ease;
        
        &:hover {
            transform: translateY(-5px);
        }
    }

15. Liaison d'Assets (asset)

Permet d'injecter des fichiers (téléversés au préalable via attachment) au sein des pipelines de compilation et de chargement d'Odoo en ciblant un bundle particulier (comme web.assets_backend ou web.assets_frontend).

  • Balises requises :
    • name : Identifiant local unique de la règle d'asset.
    • bundle : Nom technique du bundle ciblé (ex : web.assets_frontend ou web.assets_backend).
    • path : URL virtuelle relative de la pièce jointe à charger (identique au champ url de l'attachment).
  • Balises optionnelles :
    • directive : Instruction de traitement de l'asset (append, prepend, include, remove, replace, défaut : append).
    • sequence : Poids ordonné de chargement du fichier (défaut : 16).
- type: asset
  name: test_iac_custom_asset
  bundle: "web.assets_frontend"
  path: "/test_iac/static/src/scss/test_style.scss"
  directive: "append"

16. Modifications de valeurs de champs (record)

Permet de modifier les valeurs de champs d'enregistrements système existants (comme la société principale, les configurations par défaut, etc.) ou d'insérer de nouvelles données personnalisées de manière parfaitement idempotente.

  • Balises requises :
    • name : Identifiant local unique de la ressource.
    • model : Nom technique du modèle Odoo ciblé (ex : res.company, res.partner).
    • values : Dictionnaire clé-valeur contenant les champs techniques et les valeurs à écrire.
  • Balises d'identification (au moins une requise) :
    • xml_id : XML-ID de l'enregistrement à identifier (ex : base.main_company). Recommandé pour la portabilité.
    • res_id : Identifiant numérique de l'enregistrement en base de données.
    • search : Liste représentant un domaine de recherche Odoo pour identifier l'enregistrement dynamique (ex : [('name', '=', 'Mycompany')]).
# Exemple 1 : Modification d'une valeur de champ sur un enregistrement système existant
- type: record
  name: update_main_company_phone
  model: res.company
  xml_id: "base.main_company"
  values:
    phone: "+33 1 23 45 67 89"

# Exemple 2 : Création (ou mise à jour) d'une nouvelle donnée personnalisée
- type: record
  name: create_custom_partner
  model: res.partner
  values:
    name: "Emmanuel"
    email: "emmanuel@my-company.com"
    phone: "+33 6 12 34 56 78"
    comment: "Créé via Odoo IaC Engine"

---

### 17. Importation Dynamique de Données (`import`)
Permet de peupler et synchroniser des enregistrements Odoo en masse à partir de fichiers locaux CSV ou Excel (`.xlsx`), avec un mapping déclaratif de colonnes et une gestion de l'unicité pour une idempotence absolue.
*   **Balises requises** :
    *   `name` : Identifiant local unique de la ressource.
    *   `model` : Nom technique du modèle Odoo ciblé (ex : `res.partner`, `product.template`).
    *   `file_path` : Chemin du fichier à importer sur le système local (CSV ou Excel). Les dépendances `pandas` et `openpyxl` sont incluses dans le package pour une installation automatique et transparente.
    *   `mapping` : Dictionnaire mappant le nom technique du champ Odoo au nom de la colonne du fichier.
        *   **Champs traduisibles (JSONB)** : Si un champ nécessite des traductions, vous pouvez passer un sous-dictionnaire où les clés sont les codes de langue Odoo (ex: `fr_FR`, `en_US`) et les valeurs sont les noms des colonnes contenant les traductions correspondantes.
*   **Balises optionnelles** :
    *   `unique_by` : Nom du champ Odoo (ou liste de champs) servant de clé d'unicité. Si un enregistrement correspondant est trouvé, il est mis à jour (`write`) ; sinon, il est créé (`create`). Permet une idempotence parfaite.

```yaml
# Exemple 1 : Importation de contacts standard
- type: import
  name: test_partners_import
  model: res.partner
  file_path: test_contacts.xlsx
  unique_by: email
  mapping:
    name: Nom
    email: Email
    phone: Mobile

# Exemple 2 : Importation de produits avec traductions multiples (champs traduisibles JSONB)
- type: import
  name: test_products_import
  model: product.template
  file_path: test_products.csv
  unique_by: default_code
  mapping:
    default_code: "Référence"
    list_price: "Prix de vente"
    # Nom traduisible en Français et Anglais à partir de colonnes séparées
    name:
      fr_FR: "Nom Français"
      en_US: "Nom Anglais"

🛡️ Sécurité, Robustesse & Validation en Phase de Compilation (Premium Enhancements)

Pour répondre aux exigences des environnements de production et des chaînes CI/CD d'entreprise, le moteur IaC ood intègre des fonctionnalités avancées de protection et de validation pré-vol :

1. Masquage des Variables Sensibles

Toutes les valeurs des attributs dont le nom de clé contient un mot clé sensible (comme password, key, token, secret, credential, private) sont automatiquement interceptées et masquées sous la forme ********** dans toutes les sorties du terminal (ood plan, ood apply, logs de compilation). Cela élimine tout risque de fuite de secrets dans les tableaux de bord CI/CD ou les fichiers de log.

2. Résolution Dynamique des relations Many2one

Lors de l'importation de données complexes via la ressource import, vous pouvez effectuer des recherches de relations Many2one à la volée. Le moteur utilise un sous-dictionnaire déclaratif pour interroger Odoo par XML-RPC et obtenir dynamiquement l'ID SQL de l'enregistrement lié (par exemple, associer un produit à sa catégorie via son nom) :

- type: import
  name: import_products_with_categories
  model: product.template
  file_path: articles.xlsx
  mapping:
    default_code: "Référence"
    list_price: "Prix"
    # Résolution Many2one dynamique du modèle product.category
    categ_id:
      relation: "product.category"
      search_by: "name"
      column: "Nom Catégorie"

3. Contrôle de Syntaxe Python Automatique

Tous les scripts Python embarqués dans les ressources server_action, cron ou base_automation sont compilés et validés par le parseur natif Python de l'hôte lors de l'exécution de la commande ood plan. En cas d'erreur de syntaxe ou d'indentation (SyntaxError, IndentationError), la phase de planification s'interrompt immédiatement en affichant un rapport clair contenant :

  • Le message d'erreur précis du compilateur.
  • Le numéro de la ligne en faute.
  • L'extrait de code concerné.

4. Validation Stricte des Schémas Odoo

Pendant l'étape ood plan, pour chaque ressource de type record ou import, le moteur effectue une vérification précoce ("fail-fast") en interrogeant le dictionnaire de structure (fields_get) de l'instance Odoo (avec mise en cache optimisée à un seul appel par modèle).

  • Si le modèle Odoo cible n'existe pas, la planification échoue avec une erreur descriptive.
  • Si un champ technique cible n'existe pas sur le modèle Odoo (ex: faute de frappe emaiil au lieu de email), la planification échoue immédiatement en listant la liste des champs valides disponibles pour ce modèle.

⚡ Robustesse, Vitesse & Transactionnalité d'Entreprise

Pour supporter les déploiements industriels à grande échelle et garantir une intégrité absolue de la base de données Odoo même en cas de panne réseau ou de mauvaise configuration applicative, le moteur IaC ood intègre les mécanismes avancés suivants :

1. Déploiement Parallèle Multi-threadé

Afin d'accélérer drastiquement la phase d'apply, le moteur regroupe les actions du plan par tier topologique (les ressources de même type et même action, par exemple la création en masse de 50 champs personnalisés).

  • Parallélisme avec ThreadPoolExecutor : Les ressources d'un même tier sont déployées en parallèle.
  • Isolation Thread-Local du Client XML-RPC : Le partage de connexions ou de proxies XML-RPC entre les threads d'exécution pouvant causer des corruptions de protocole HTTP, le client OdooClient encapsule ses proxies et sessions dans un état thread-local (threading.local). Chaque thread dispose ainsi de sa propre connexion isolée sans surcharge mémoire.
  • Verrou de Sécurité sur l'État Local : Les écritures dans le fichier d'état local ood.oodstate sont synchronisées via un verrou d'exclusion mutuelle (threading.Lock), garantissant une intégrité parfaite des données d'état.
  • Configuration : Le paramètre optionnel max_workers peut être renseigné sous la clé connection de votre configuration (par défaut 4).

2. Audits de Sécurité Pré-vol ACL

Le déploiement IaC requiert des droits élevés d'administration (création de champs, vues, automatisations). Pour éviter qu'une exécution s'interrompe à mi-chemin à cause d'une permission manquante, le moteur effectue une vérification précoce de sécurité avant tout déploiement :

  • Analyse Pré-vol des Permissions : Le moteur interroge Odoo via check_access_rights sur tous les modèles cibles affectés par le plan (ex : ir.model.fields, ir.ui.view, ir.cron, etc.).
  • Exclusion Intelligente des Nouveaux Modèles : Si le plan contient la création de modèles personnalisés (de type model), le moteur omet dynamiquement ces tables lors de la vérification pré-vol de sécurité, puisqu'elles n'existent pas encore physiquement en base.
  • Fail-Fast : Si une seule autorisation CRUD requise fait défaut, le déploiement s'interrompt immédiatement avec un rapport détaillé avant toute écriture en base.

3. Rollback Transactionnel sur Échec

En cas d'erreur inattendue survenant lors d'un apply (panne réseau, erreur système Odoo, validation métier bloquante) :

  • Restauration Automatique de l'État : Le moteur IaC dépile la pile d'exécution dans l'ordre rigoureusement inverse de leur application.
  • Annulation des Créations : Les ressources créées durant la session courante sont supprimées d'Odoo (unlink).
  • Rétablissement des Mises à Jour : Pour chaque ressource mise à jour, sa configuration d'origine (préalablement sauvegardée en mémoire avant modification) est réécrite en base Odoo pour restaurer son état original exact.
  • Persistance Atomique : À chaque étape du rollback, le fichier d'état local ood.oodstate est mis à jour en temps réel pour refléter le statut physique réel de la base, évitant tout désalignement d'état en cas d'interruption abrupte.

📄 Licence

Ce projet est distribué sous licence libre GNU General Public License v3 (GPLv3). Pour plus de détails, veuillez consulter le fichier [LICENSE] situé à la racine du projet.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ood_cli-1.0.1.tar.gz (65.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ood_cli-1.0.1-py3-none-any.whl (43.5 kB view details)

Uploaded Python 3

File details

Details for the file ood_cli-1.0.1.tar.gz.

File metadata

  • Download URL: ood_cli-1.0.1.tar.gz
  • Upload date:
  • Size: 65.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for ood_cli-1.0.1.tar.gz
Algorithm Hash digest
SHA256 e8d948fb1a2bc3caa4a7cd740a481c772528fe519527047d1c6b5d4b5d7f5c9f
MD5 4761e7b1c81ddf0528a8c0fddd497679
BLAKE2b-256 1e04a838b04914138d92b8b0570b1233105769e31cfb161db6d6be45a3c978b1

See more details on using hashes here.

File details

Details for the file ood_cli-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: ood_cli-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 43.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for ood_cli-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8ab9f99974682e358e6caafbaa3d48f34e4a443ac417ee2b1c6653ba70e30bef
MD5 e84461b964c6c39e0eccfa8056226b52
BLAKE2b-256 dc80198d51c3e83515451877b4aa7b26dab4fe6a1144b5d9fe37c2af6b167cea

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page