Outil Python pour exporter/importer les configurations d'InterSystems API Manager
🛠️ Gestion des configurations d'InterSystems API Manager (IAM = Kong Gateway) en CI/CD
🔍 Contexte : configurations d'InterSystems IAM
Dans le cadre de l'intégration d'InterSystems IAM dans un environnement sécurisé et contrôlé, InterSystems IAM repose sur Kong Gateway pour gérer les API exposées. Kong agit comme une API Gateway moderne, capable de gérer l’authentification, la sécurité, la gestion du trafic, les plugins, et bien plus encore.
Cependant, maintenir une configuration cohérente de Kong (routes, services, plugins...) entre les différents environnements (développement, test, production) est un défi majeur. C’est ici que les outils comme deck et ce script Python prennent tout leur sens.
⚙️ Présentation de kong_config_tool.py
Cet outil permet de :
- Exporter la configuration actuelle d’une Kong Gateway dans un fichier YAML versionnable.
- Importer une configuration YAML dans une Kong Gateway (via
deck sync). - Automatiser la journalisation complète (logs, stdout/stderr) pour un suivi précis.
- S’intégrer facilement dans un pipeline CI/CD.
🎯 Objectifs et bénéfices
🔄 Synchronisation cohérente entre environnements
L’outil facilite la propagation de la configuration Kong entre les environnements. En exportant la configuration de dev, puis en l’importation dans staging ou prod, vous assurez une parité fonctionnelle.
🔐 Traçabilité et audits via logs
Grâce à l’option --log, toutes les opérations (y compris les commandes internes à deck) sont journalisées :
- Qui a exécuté quoi
- Quelle configuration a été appliquée
- Quelle a été la réponse de Kong (nombre de ressources créées, modifiées...)
🧪 Intégration dans des pipelines CI/CD
Dans GitLab CI, GitHub Actions ou Jenkins :
- L’étape d’export peut être lancée automatiquement après des modifications d’API.
- L’étape d’import permet de déployer automatiquement la config Kong à chaque merge ou release.
- Les fichiers YAML générés peuvent être versionnés dans Git.
🧰 Exemple typique de pipeline GitLab
stages:
- export
- deploy
export_kong:
stage: export
script:
- python3 kong_config_tool.py --export --log
artifacts:
paths:
- kong.yaml
deploy_kong:
stage: deploy
script:
- python3 kong_config_tool.py --import --log
🛡️ Sécurité et reproductibilité
InterSystems IRIS IAM étant souvent utilisé dans des environnements sensibles (santé, finance...), il est essentiel de :
- Éviter les erreurs manuelles via
deck sync - Garantir que chaque déploiement applique exactement la même configuration
- Disposer d’un journal clair pour les audits (via les fichiers
.log)
💡 Points forts de l’outil
| Fonction | Description |
|---|---|
--export |
Sauvegarde la config actuelle vers un fichier kong-<timestamp>.yaml |
--import |
Applique le contenu de kong.yaml dans le Gateway |
--log |
Active la journalisation complète (stdout, stderr, logs) |
| Symlink automatique | Le fichier kong.yaml est toujours un alias vers la dernière version exportée |
| Intégration facile | Aucune dépendance lourde, tout repose sur Python standard et deck |
📦 Conclusion
L’outil kong_config_tool.py est une brique essentielle pour industrialiser la gestion des configurations Kong dans le contexte d’InterSystems IAM. Il permet :
- Un meilleur contrôle de la configuration.
- Une meilleure traçabilité.
- Une intégration fluide dans les pipelines CI/CD.
- Une mise en conformité avec les exigences de sécurité.
🚀 Prochaines évolutions possibles
- Intégration native à GitOps (ArgoCD, FluxCD)
- Validation de configuration avec
deck diff - Notifications en cas d’erreurs (Slack, Teams)
Voici une présentation détaillée du code Python kong_config_tool.py, intégrée à l’article, pour expliquer son fonctionnement ligne par ligne, et comment il s’inscrit dans une démarche de CI/CD et d'administration de la configuration Kong avec InterSystems IAM.
🧬 Présentation du code Python
Le script kong_config_tool.py est un outil en ligne de commande Python conçu pour automatiser les exports et imports de configuration de la Kong Gateway via deck, tout en assurant une journalisation robuste.
📁 Structure générale
#!/usr/bin/env python3
import argparse
import subprocess
from datetime import datetime
from pathlib import Path
import sys
import logging
- Utilise uniquement des modules standards Python.
argparse: pour gérer les options en ligne de commande.subprocess: pour exécuterdeck.logging: pour un logging structuré (console + fichier).
🧱 Initialisation du logger
logger = logging.getLogger("kong_config_tool")
- Initialise un logger nommé, configurable selon qu’un fichier log est demandé ou non.
📝 setup_logging(log_file=None)
Fonction permettant :
- de créer des handlers vers console et/ou fichier.
- de rediriger
sys.stdoutetsys.stderrvers le fichier si--logest fourni.
🔎 Permet ainsi de capturer tout : logs Python, print(), erreurs, et aussi sortie de deck.
📤 export_kong_config()
deck_dir = Path.cwd()
output_file = deck_dir / f"kong-{timestamp}.yaml"
- Exécute
deck gateway dump -o ...pour exporter la configuration actuelle de Kong. - Capture
stdoutetstderrpour les injecter dans le log vialogger.debug(...). - Crée (ou met à jour) un symlink
kong.yamlqui pointe vers le fichier exporté — cela simplifie les imports ultérieurs. - En cas d’échec, affiche l’erreur dans les logs et arrête le script.
📥 import_kong_config()
- Vérifie la présence du fichier
kong.yaml(symlink ou vrai fichier). - Exécute
deck gateway sync kong.yaml. - Capture la sortie complète et la logge également.
- Gestion fine des erreurs via
CalledProcessError.
🔁 Cette logique est symétrique à l’export.
🚀 main()
Fonction d’entrée qui :
- Gère les arguments
--export,--import,--log. - Appelle les fonctions correspondantes.
python kong_config_tool.py --export --log
python kong_config_tool.py --import --log
💡 Si --log est omis, la sortie reste visible dans la console uniquement.
🧪 Exécution typique en pipeline CI/CD
Export
python kong_config_tool.py --export --log
Résultat :
kong-2025-07-18_12-34-56.yaml(contenu versionnable)kong.yaml(symlink utile pour l’import)kong_config_tool.log(journal pour audit)
Import
python kong_config_tool.py --import --log
Résultat :
- Application de la configuration sur un nouveau gateway (staging, prod, etc.)
- Fichier
kong_config_tool.ogpour retrouver ce qui a été fait
✅ Résumé des points du code
| Fonctionnalité | Implémentation |
|---|---|
| Interface CLI intuitive | argparse avec aide en ligne |
| Export propre | deck gateway dump + timestamp |
| Import contrôlé | deck gateway sync kong.yaml |
| Journalisation complète | logging + redirection stdout/stderr |
| Résilience | Gestion des erreurs via try/except |
| Intégration CI/CD ready | Interface simple, sans dépendance externe |
kong_config_tool.py
#!/usr/bin/env python3import argparse
import subprocess
from datetime import datetime
from pathlib import Path
import sys
import logging
logger = logging.getLogger("kong_config_tool")
defsetup_logging(log_file=None):
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter("[%(asctime)s] %(levelname)s: %(message)s", "%Y-%m-%d %H:%M:%S")
handlers = []
# Console handler
console_handler = logging.StreamHandler()
console_handler.setFormatter(formatter)
handlers.append(console_handler)
if log_file:
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(formatter)
handlers.append(file_handler)
# Redirect all stdout and stderr to the log file
log_file_handle = open(log_file, "a")
sys.stdout = log_file_handle
sys.stderr = log_file_handle
for handler in handlers:
logger.addHandler(handler)
defexport_kong_config():
deck_dir = Path.cwd()
current_date = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
output_file = deck_dir / f"kong-{current_date}.yaml"try:
logger.info(f"Exporting Kong config to: {output_file}")
result = subprocess.run(
["deck", "gateway", "dump", "-o", str(output_file)],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
# Log and print deck output
logger.debug(result.stdout)
logger.debug(result.stderr)
print(result.stdout)
print(result.stderr)
symlink_path = deck_dir / "kong.yaml"if symlink_path.exists() or symlink_path.is_symlink():
symlink_path.unlink()
symlink_path.symlink_to(output_file.name)
logger.info(f"Symlink created/updated: {symlink_path} -> {output_file.name}")
except subprocess.CalledProcessError as e:
logger.error(f"Export failed: {e}")
logger.error(e.stderr)
print(e.stderr)
sys.exit(1)
defimport_kong_config():
deck_file = Path.cwd() / "kong.yaml"ifnot deck_file.exists():
logger.error(f"Configuration file {deck_file} not found.")
sys.exit(1)
try:
logger.info("Syncing kong.yaml to gateway...")
result = subprocess.run(
["deck", "gateway", "sync", str(deck_file)],
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
# Log and print deck output
logger.debug(result.stdout)
logger.debug(result.stderr)
# print(result.stdout)# print(result.stderr)
logger.info("Sync completed successfully.")
except subprocess.CalledProcessError as e:
logger.error(f"Sync failed: {e}")
logger.error(e.stderr)
print(e.stderr)
sys.exit(1)
defmain():
parser = argparse.ArgumentParser(
description=(
"Tool to export or import Kong Gateway configuration using deck.\n\n""Exactly one of the options --export or --import is required.\n\n""Examples:\n"" python kong_config_tool.py --export --log\n"" python kong_config_tool.py --import --log\n\n""For help, run:\n"" python kong_config_tool.py --help"
),
formatter_class=argparse.RawTextHelpFormatter
)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("-e", "--export", dest="export_config", action="store_true",
help="Export Kong configuration to a timestamped YAML file and create/update kong.yaml symlink.")
group.add_argument("-i", "--import", dest="import_config", action="store_true",
help="Import (sync) Kong configuration from kong.yaml into Kong Gateway.")
parser.add_argument(
"--log",
dest="log_file",
nargs="?",
const="kong_config_tool.log",
help="Enable logging to a file. Use default 'kong_config_tool.log' if no path is given."
)
args = parser.parse_args()
setup_logging(args.log_file)
if args.export_config:
export_kong_config()
elif args.import_config:
import_kong_config()
if __name__ == "__main__":
main()