feat(apim-apps): first commit
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
import logging
|
||||
|
||||
from ._colors import _c
|
||||
from .client import AxwayClient
|
||||
from .models import Action, EnvConfig, Manifest, NormResult
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _applies_to(target_envs: list[str], env_name: str) -> bool:
|
||||
return not target_envs or env_name in target_envs
|
||||
|
||||
|
||||
def normalize_env(env: EnvConfig, manifest: Manifest, dry_run: bool) -> NormResult:
|
||||
result = NormResult()
|
||||
tag = f"[{env.name}]"
|
||||
|
||||
log.info(f"{tag} Connexion à {env.url} …")
|
||||
client = AxwayClient(env)
|
||||
|
||||
# ── 1. Organisations ──────────────────────────────────────────────────────
|
||||
try:
|
||||
existing_orgs = client.list_orgs()
|
||||
except Exception as e:
|
||||
result.errors.append(f"{tag} Impossible de lister les organisations : {e}")
|
||||
return result
|
||||
|
||||
for org_spec in manifest.organizations:
|
||||
if not _applies_to(org_spec.environments, env.name):
|
||||
continue
|
||||
|
||||
action = Action(
|
||||
kind="create_org",
|
||||
env_name=env.name,
|
||||
description=f"Créer organisation « {org_spec.name} »",
|
||||
detail={"org": org_spec.name},
|
||||
)
|
||||
|
||||
if org_spec.name in existing_orgs:
|
||||
log.debug(f"{tag} Org « {org_spec.name} » déjà présente — skip")
|
||||
result.actions_skipped.append(action)
|
||||
continue
|
||||
|
||||
log.info(_c("yellow", f"{tag} {'[DRY-RUN] ' if dry_run else ''}Création org « {org_spec.name} »"))
|
||||
if not dry_run:
|
||||
try:
|
||||
created = client.create_org(org_spec)
|
||||
existing_orgs[org_spec.name] = created
|
||||
log.info(_c("green", f"{tag} ✅ Org « {org_spec.name} » créée (id={created.get('id')})"))
|
||||
except Exception as e:
|
||||
msg = f"{tag} ❌ Échec création org « {org_spec.name} » : {e}"
|
||||
log.error(msg)
|
||||
result.errors.append(msg)
|
||||
continue
|
||||
else:
|
||||
# Placeholder so apps referencing this org are processed in dry-run
|
||||
existing_orgs[org_spec.name] = {"id": "", "name": org_spec.name}
|
||||
result.actions_done.append(action)
|
||||
|
||||
# ── 2. Applications ───────────────────────────────────────────────────────
|
||||
try:
|
||||
existing_apps = client.list_apps()
|
||||
except Exception as e:
|
||||
result.errors.append(f"{tag} Impossible de lister les applications : {e}")
|
||||
return result
|
||||
|
||||
for app_spec in manifest.applications:
|
||||
if not _applies_to(app_spec.environments, env.name):
|
||||
continue
|
||||
|
||||
key = (app_spec.org_name, app_spec.name)
|
||||
|
||||
action_app = Action(
|
||||
kind="create_app",
|
||||
env_name=env.name,
|
||||
description=f"Créer application « {app_spec.name} » dans org « {app_spec.org_name} »",
|
||||
detail={"org": app_spec.org_name, "app": app_spec.name},
|
||||
)
|
||||
|
||||
raw_org = existing_orgs.get(app_spec.org_name)
|
||||
if raw_org is None:
|
||||
msg = (
|
||||
f"{tag} ❌ Organisation « {app_spec.org_name} » introuvable dans l'API Manager "
|
||||
f"— application « {app_spec.name} » ignorée. "
|
||||
f"Créez l'organisation manuellement dans l'API Manager."
|
||||
)
|
||||
log.error(msg)
|
||||
result.errors.append(msg)
|
||||
continue
|
||||
|
||||
org_id = raw_org["id"]
|
||||
|
||||
if key not in existing_apps:
|
||||
log.info(_c("yellow", f"{tag} {'[DRY-RUN] ' if dry_run else ''}Création app « {app_spec.name} » (org={app_spec.org_name})"))
|
||||
if not dry_run:
|
||||
try:
|
||||
created_app = client.create_app(app_spec, org_id)
|
||||
existing_apps[key] = created_app
|
||||
log.info(_c("green", f"{tag} ✅ App « {app_spec.name} » créée (id={created_app.get('id')})"))
|
||||
except Exception as e:
|
||||
msg = f"{tag} ❌ Échec création app « {app_spec.name} » : {e}"
|
||||
log.error(msg)
|
||||
result.errors.append(msg)
|
||||
continue
|
||||
result.actions_done.append(action_app)
|
||||
else:
|
||||
result.actions_skipped.append(action_app)
|
||||
|
||||
# ── 3. Souscriptions aux APIs ─────────────────────────────────────────
|
||||
if not app_spec.apis:
|
||||
continue
|
||||
|
||||
raw_app = existing_apps.get(key)
|
||||
if raw_app is None:
|
||||
continue # app non créée (dry-run ou erreur)
|
||||
|
||||
app_id = raw_app.get("id", "")
|
||||
|
||||
try:
|
||||
granted = client.list_app_api_access(app_id)
|
||||
granted_ids = {a.get("apiId", a.get("id", "")) for a in granted}
|
||||
granted_names = {a.get("apiName", a.get("name", "")) for a in granted}
|
||||
except Exception as e:
|
||||
log.warning(f"{tag} Impossible de lire les accès API de « {app_spec.name} » : {e}")
|
||||
granted_ids = set()
|
||||
granted_names = set()
|
||||
|
||||
for api_access in app_spec.apis:
|
||||
action_api = Action(
|
||||
kind="grant_api",
|
||||
env_name=env.name,
|
||||
description=(
|
||||
f"Abonner « {app_spec.name} » à l'API « {api_access.api_name} »"
|
||||
+ (f" v{api_access.api_version}" if api_access.api_version else "")
|
||||
),
|
||||
detail={"app": app_spec.name, "api": api_access.api_name, "version": api_access.api_version},
|
||||
)
|
||||
|
||||
if api_access.api_name in granted_names:
|
||||
log.debug(f"{tag} API « {api_access.api_name} » déjà accordée à « {app_spec.name} » — skip")
|
||||
result.actions_skipped.append(action_api)
|
||||
continue
|
||||
|
||||
if dry_run:
|
||||
log.info(_c("yellow", f"{tag} [DRY-RUN] Abonnement « {app_spec.name} » → API « {api_access.api_name} »"))
|
||||
result.actions_done.append(action_api)
|
||||
continue
|
||||
|
||||
fe_api = client.find_frontend_api(api_access.api_name, api_access.api_version)
|
||||
if fe_api is None:
|
||||
msg = (
|
||||
f"{tag} ⚠️ API front-end « {api_access.api_name} » introuvable "
|
||||
f"— souscription de « {app_spec.name} » ignorée"
|
||||
)
|
||||
log.warning(msg)
|
||||
result.errors.append(msg)
|
||||
continue
|
||||
|
||||
api_id = fe_api["id"]
|
||||
if api_id in granted_ids:
|
||||
result.actions_skipped.append(action_api)
|
||||
continue
|
||||
|
||||
try:
|
||||
client.grant_api_access(app_id, api_id)
|
||||
log.info(_c("green", f"{tag} ✅ Accès API « {api_access.api_name} » accordé à « {app_spec.name} »"))
|
||||
result.actions_done.append(action_api)
|
||||
except Exception as e:
|
||||
msg = f"{tag} ❌ Échec souscription « {app_spec.name} » → « {api_access.api_name} » : {e}"
|
||||
log.error(msg)
|
||||
result.errors.append(msg)
|
||||
|
||||
return result
|
||||
Reference in New Issue
Block a user