Framework de test — variables manquantes dans le contexte d'assertions et surcharge cluster/tenant impossible #8

Closed
opened 2026-06-10 18:47:40 +02:00 by xmortelette · 1 comment

Contexte

En corrigeant des échecs du test summary, plusieurs aspects peu évidents (ou potentiellement des manques) du framework de test Test/TestSet ont été identifiés.


1. La variable tenant n'est pas exposée au rendu des assertions

Pour un package type: tenant, le template système utilise {{ tenant.name }} (peuplé en prod par context.tenant, dérivé du label vynil.solidite.fr/tenant).

Côté test, le moteur de rendu des selector/value des asserts ne connaît que instance, var, defaults, … — pas tenant. Toute assertion qui tente de référencer {{tenant.name}} échoue avec Failed to access variable in strict mode Some("tenant.name").

En l'absence d'un label vynil.solidite.fr/tenant sur le namespace (cas par défaut en test), tenant.name retombe sur instance.metadata.namespace. Ce comportement de repli existe dans le code (instancetenant.rs) mais n'est documenté nulle part, et aucun exemple dans le repo ne montre le bon pattern pour ce cas.

Suggestion : soit exposer tenant (avec une valeur cohérente, dérivée comme en prod) dans le contexte de rendu des assertions pour les packages tenant, soit documenter clairement le pattern de repli (instance.namespace fait office de nom de tenant par défaut).


2. La variable values n'est pas exposée au rendu des assertions

{{values.xxx}} dans un bloc value: d'assertion casse avec Failed to access variable in strict mode Some("values.xxx"). Aucun test du repo n'utilise {{values.*}} dans une assertion, ce qui suggère que ce n'est simplement pas supporté — seuls {{instance.*}}, {{var.*}} et {{defaults.*}} semblent valides à cet endroit.

Le contournement (valeur littérale au lieu de {{values.common_name}}) crée un couplage implicite entre le test et la valeur par défaut du package : si le défaut change, le test continuera de "passer" en testant la mauvaise valeur.

Suggestion : exposer values (les options résolues de l'instance, mêmes valeurs que celles disponibles aux templates système) au rendu des assertions — c'est probablement ce que les auteurs de tests attendent en écrivant {{values.xxx}}.


3. Aucun moyen de configurer context.cluster.ha depuis un Test

Un test fixait instance.options.ha: true en s'attendant à déclencher le chemin HA (2 replicas + PodDisruptionBudget). Mais :

  • Le package ne déclarait aucune option ha dans son package.yaml (donc instance.options.ha n'a aucun effet, silencieusement) ;
  • context.cluster.ha est dérivé en mode test du nombre de nœuds mockés (defaults.nodes), qui vaut ["single"] par défaut → cluster.ha = false ;
  • Il n'existe aucun moyen, dans la définition d'un Test/TestSet, de surcharger ce nombre de nœuds ou context.cluster.ha directement (pas de clé cluster:/nodes: dans le schéma Test).

Résultat : le test ne peut pas exercer le chemin HA qu'il prétend tester — il resterait sur replicas: 1 alors qu'il attend replicas: 2.

Suggestion : permettre de surcharger context.cluster.ha (ou le nombre de nœuds mockés) depuis un Test/TestSet, ou clarifier si le package doit avoir sa propre option ha plutôt que de dépendre de la capacité cluster.


Résumé

Ces trois points touchent au même concept : quelles variables sont réellement disponibles dans le contexte de rendu des assertions, et comment surcharger le contexte cluster/tenant depuis un Test. Ce n'est documenté nulle part dans le repo, et chaque "bonne pratique" applicable est une déduction du code source de l'agent plutôt qu'un pattern officiel. Une doc courte sur "ce qui est exposé où" éviterait ces allers-retours.

## Contexte En corrigeant des échecs du test summary, plusieurs aspects peu évidents (ou potentiellement des manques) du framework de test `Test`/`TestSet` ont été identifiés. --- ## 1. La variable `tenant` n'est pas exposée au rendu des assertions Pour un package `type: tenant`, le template système utilise `{{ tenant.name }}` (peuplé en prod par `context.tenant`, dérivé du label `vynil.solidite.fr/tenant`). Côté test, le moteur de rendu des `selector`/`value` des `asserts` ne connaît que `instance`, `var`, `defaults`, … — **pas `tenant`**. Toute assertion qui tente de référencer `{{tenant.name}}` échoue avec `Failed to access variable in strict mode Some("tenant.name")`. En l'absence d'un label `vynil.solidite.fr/tenant` sur le namespace (cas par défaut en test), `tenant.name` retombe sur `instance.metadata.namespace`. Ce comportement de repli existe dans le code (`instancetenant.rs`) mais n'est documenté nulle part, et aucun exemple dans le repo ne montre le bon pattern pour ce cas. **Suggestion** : soit exposer `tenant` (avec une valeur cohérente, dérivée comme en prod) dans le contexte de rendu des assertions pour les packages `tenant`, soit documenter clairement le pattern de repli (`instance.namespace` fait office de nom de tenant par défaut). --- ## 2. La variable `values` n'est pas exposée au rendu des assertions `{{values.xxx}}` dans un bloc `value:` d'assertion casse avec `Failed to access variable in strict mode Some("values.xxx")`. Aucun test du repo n'utilise `{{values.*}}` dans une assertion, ce qui suggère que ce n'est simplement pas supporté — seuls `{{instance.*}}`, `{{var.*}}` et `{{defaults.*}}` semblent valides à cet endroit. Le contournement (valeur littérale au lieu de `{{values.common_name}}`) crée un couplage implicite entre le test et la valeur par défaut du package : si le défaut change, le test continuera de "passer" en testant la mauvaise valeur. **Suggestion** : exposer `values` (les options résolues de l'instance, mêmes valeurs que celles disponibles aux templates système) au rendu des assertions — c'est probablement ce que les auteurs de tests attendent en écrivant `{{values.xxx}}`. --- ## 3. Aucun moyen de configurer `context.cluster.ha` depuis un `Test` Un test fixait `instance.options.ha: true` en s'attendant à déclencher le chemin HA (2 replicas + PodDisruptionBudget). Mais : - Le package ne déclarait **aucune option `ha`** dans son `package.yaml` (donc `instance.options.ha` n'a aucun effet, silencieusement) ; - `context.cluster.ha` est dérivé en mode test du nombre de nœuds mockés (`defaults.nodes`), qui vaut `["single"]` par défaut → `cluster.ha = false` ; - Il n'existe aucun moyen, dans la définition d'un `Test`/`TestSet`, de surcharger ce nombre de nœuds ou `context.cluster.ha` directement (pas de clé `cluster:`/`nodes:` dans le schéma `Test`). Résultat : le test ne peut pas exercer le chemin HA qu'il prétend tester — il resterait sur `replicas: 1` alors qu'il attend `replicas: 2`. **Suggestion** : permettre de surcharger `context.cluster.ha` (ou le nombre de nœuds mockés) depuis un `Test`/`TestSet`, ou clarifier si le package doit avoir sa propre option `ha` plutôt que de dépendre de la capacité cluster. --- ## Résumé Ces trois points touchent au même concept : **quelles variables sont réellement disponibles dans le contexte de rendu des assertions, et comment surcharger le contexte cluster/tenant depuis un `Test`**. Ce n'est documenté nulle part dans le repo, et chaque "bonne pratique" applicable est une déduction du code source de l'agent plutôt qu'un pattern officiel. Une doc courte sur "ce qui est exposé où" éviterait ces allers-retours.
Author

Implémenté et soumis en PR upstream : https://github.com/sebt3/vynil/pull/228

Les trois points sont traités :

  1. {{tenant.name}} dans les assertionstenant.name est maintenant exposé dans le contexte Handlebars des assertions. Pour un package type: tenant, il vaut par défaut instance.namespace (le même repli que instancetenant.rs en production). Il peut être surchargé via instance.tenant: <nom> dans la définition du Test.

  2. {{values.xxx}} et {{defaults.xxx}} dans les assertions — Les deux variables sont maintenant disponibles. defaults contient les valeurs par défaut du schéma package.options ; values fusionne ces défauts avec les instance.options du test — exactement ce que les scripts Rhai reçoivent à l'exécution.

  3. Surcharge de context.cluster.ha — Nouveau champ nodes dans VynilTestInstance. En spécifiant nodes: [master01, worker01], les objets Node sont injectés automatiquement dans la couche mock k8s. build_context.rhai::run() calcule alors ha = nodes.len() > 1 de façon naturelle, sans modifier les scripts Rhai.

Cinq tests unitaires couvrent les cas nominaux et les overrides.

Implémenté et soumis en PR upstream : https://github.com/sebt3/vynil/pull/228 Les trois points sont traités : 1. **`{{tenant.name}}` dans les assertions** — `tenant.name` est maintenant exposé dans le contexte Handlebars des assertions. Pour un package `type: tenant`, il vaut par défaut `instance.namespace` (le même repli que `instancetenant.rs` en production). Il peut être surchargé via `instance.tenant: <nom>` dans la définition du `Test`. 2. **`{{values.xxx}}` et `{{defaults.xxx}}` dans les assertions** — Les deux variables sont maintenant disponibles. `defaults` contient les valeurs par défaut du schéma `package.options` ; `values` fusionne ces défauts avec les `instance.options` du test — exactement ce que les scripts Rhai reçoivent à l'exécution. 3. **Surcharge de `context.cluster.ha`** — Nouveau champ `nodes` dans `VynilTestInstance`. En spécifiant `nodes: [master01, worker01]`, les objets Node sont injectés automatiquement dans la couche mock k8s. `build_context.rhai::run()` calcule alors `ha = nodes.len() > 1` de façon naturelle, sans modifier les scripts Rhai. Cinq tests unitaires couvrent les cas nominaux et les overrides.
xmortelette added the Kind/EnhancementKind/Bug
Priority
Medium
3
labels 2026-06-11 09:42:47 +02:00
Sign in to join this conversation.