Client Delphi pour l'API Kubernetes depuis OpenAPI

Chaque cluster Kubernetes décrit sa propre API, et sgcOpenAPI transforme cette description en une unité Pascal que vous appelez depuis Delphi. C'est la plus grande des spécifications publiques présentées sur ces pages, et la seule où le choix du document source change vraiment le résultat, donc cette page indique à partir de quel endpoint générer et quelles sont les deux limites connues.

Kubernetes + sgcOpenAPI

Tout ce qui suit a été mesuré en lançant le générateur sur les spécifications Kubernetes puis en compilant le résultat, rien n'est estimé.

Générez à partir de ceci

Les documents OpenAPI 3 par groupe sous /openapi/v3, un par un. C'est la voie qui produit un client correct.

Pas à partir de ceci

Le document agrégé /openapi/v2. C'est du Swagger 2.0, il se convertit et il génère, mais deux choses en sortent fausses. Les deux sont décrites plus bas.

Authentification

Générez avec -a 2 et définissez Authentication.Token.BearerToken, ce qui envoie le token du ServiceAccount en Authorization: Bearer.

URL de base

Kubernetes ne déclare aucun hôte de serveur, donc passez -u https://cluster:6443 à la génération ou appelez SetBaseURL à l'exécution.

/openapi/v3 est un index, pas un document

C'est la première chose à comprendre. Un cluster ne sert pas un seul fichier OpenAPI 3. /openapi/v3 retourne une liste de chemins de groupes, et chaque groupe et version est un document séparé à sa propre URL.

# un document par groupe et version d'API, 65 dans un cluster standard
> sgcOpenAPI.exe -i "https://10.0.0.1:6443/openapi/v3/api/v1" \
      -o "k8s_core_v1.pas" -a 2 -u "https://10.0.0.1:6443"

File successfully created k8s_core_v1.pas

> sgcOpenAPI.exe -i "https://10.0.0.1:6443/openapi/v3/apis/apps/v1" \
      -o "k8s_apps_v1.pas" -a 2 -u "https://10.0.0.1:6443"

File successfully created k8s_apps_v1.pas

Généré de cette façon, le groupe core donne 113 chemins, 248 méthodes et 293 classes de modèle dans une unité de 42 705 lignes, et le groupe apps donne 38 chemins, 77 méthodes et 180 classes de modèle en 17 061 lignes. Les deux compilent sans erreur sur RAD Studio 12 pour Win32, avec rien d'autre sur le chemin des bibliothèques que le dossier Source de sgcOpenAPI. Une unité par groupe est aussi plus facile à vivre qu'une seule unité énorme, et vous ne générez que les groupes que vous appelez vraiment.

Les mêmes documents sont publiés dans le dépôt Kubernetes sous api/openapi-spec/v3/, vous pouvez donc générer à partir d'un fichier versionné plutôt que depuis un cluster en fonctionnement, et garder le résultat sous contrôle de version.

Lister les pods d'un namespace

Kubernetes écrit déjà ses operation ids sous forme d'identifiants valides, donc la méthode générée garde le nom de la spécification.

uses
  k8s_core_v1;   // l'unité que vous venez de générer

procedure TfrmK8s.btnPodsClick(Sender: TObject);
var
  oResponse: TsgcOpenAPI_listCoreV1NamespacedPod_Response;
  oPod: TsgcOpenAPI_io_k8s_api_core_v1_Pod_Class;
begin
  GetOpenAPIClient.Authentication.Token.BearerToken := vToken;
  GetOpenAPIClient.SetBaseURL('https://10.0.0.1:6443');

  // aNamespace, aPretty, puis les paramètres dans l'ordre déclaré
  oResponse := GetOpenAPIClient.listCoreV1NamespacedPod('production',
    '', oapiBoolNull, '', '', 'app=api,tier=backend');
  try
    if oResponse.IsSuccessful then
      for oPod in oResponse.Successful.Items do
        memoLog.Lines.Add(Format('%-30s %s %s',
          [oPod.Metadata.Name, oPod.Status.Phase, oPod.Status.HostIP]))
    else
      memoLog.Lines.Add(IntToStr(oResponse.ResponseCode) + ' ' +
        oResponse.ResponseError);
  finally
    oResponse.Free;
  end;
end;

Les classes de modèle portent les noms Kubernetes complets, donc un pod est TsgcOpenAPI_io_k8s_api_core_v1_Pod_Class avec Metadata, Spec et Status, et la liste est TsgcOpenAPI_io_k8s_api_core_v1_PodList_Class avec un Items typé. Un paramètre de requête booléen que Kubernetes déclare optionnel devient un TsgcOpenAPIBoolean, dont la valeur oapiBoolNull signifie que le paramètre est omis de l'URL au lieu d'être envoyé à false.

Scaler un deployment

Là où Kubernetes décrit un corps de requête avec un schéma nommé, ce qu'il fait la plupart du temps, la méthode générée prend la classe typée plutôt qu'une chaîne.

uses
  k8s_apps_v1;

var
  oRead: TsgcOpenAPI_readAppsV1NamespacedDeploymentScale_Response;
  oWrite: TsgcOpenAPI_replaceAppsV1NamespacedDeploymentScale_Response;
begin
  oRead := GetOpenAPIClient.readAppsV1NamespacedDeploymentScale(
    'api', 'production');
  try
    if not oRead.IsSuccessful then
      raise Exception.Create(oRead.ResponseError);

    oRead.Successful.Spec.Replicas := 5;

    oWrite := GetOpenAPIClient.replaceAppsV1NamespacedDeploymentScale(
      'api', 'production', oRead.Successful);
    try
      memoLog.Lines.Add(IntToStr(oWrite.ResponseCode));
    finally
      oWrite.Free;
    end;
  finally
    oRead.Free;
  end;
end;

Sur l'ensemble de la surface Kubernetes le partage est presque égal, à peu près la moitié des corps de requête arrivent sous forme de classe typée comme TsgcOpenAPI_io_k8s_api_autoscaling_v1_Scale_Class et à peu près la moitié sous forme de chaîne, selon que le document nomme ou non le schéma.

Ce que contiennent les unités générées

L'unité reflète le document que vous lui indiquez, donc la couverture est exactement le groupe et la version que vous avez générés.

Workloads

apis/apps/v1 pour les Deployments, StatefulSets, DaemonSets et ReplicaSets. apis/batch/v1 pour les Jobs et les CronJobs. api/v1 pour les Pods et les ReplicationControllers.

Services et réseau

api/v1 pour les Services, Endpoints, ConfigMaps et Secrets. apis/networking.k8s.io/v1 pour Ingress et NetworkPolicy. apis/discovery.k8s.io/v1 pour les EndpointSlices.

Stockage, RBAC et policy

apis/storage.k8s.io/v1, apis/rbac.authorization.k8s.io/v1, apis/policy/v1 et apis/admissionregistration.k8s.io/v1, chacun son propre document et chacun sa propre unité.

Ressources personnalisées

Un cluster où des CRD sont installées les sert à leurs propres chemins de groupe, donc l'index de /openapi/v3 les liste à côté des groupes intégrés et elles se génèrent de la même façon.

Chaque modèle en classe

ObjectMeta, PodSpec, PodStatus, Container, les types de condition, les types de liste. Le seul groupe core en produit 293.

La documentation de la spec

Les descriptions de champ de Kubernetes sont reportées en commentaires Pascal au-dessus de chaque méthode et de chaque propriété, ce qui explique en grande partie la longueur des unités.

Ce que nous avons trouvé à l'usage

Deux d'entre elles sont propres au document Swagger 2.0 agrégé, et ce sont elles qui font que cette page vous dit de générer par groupe.

Les paramètres au niveau du chemin sont perdus dans le document v2

Kubernetes déclare namespace et pretty une seule fois sur le path item et les référence avec un $ref. Générés depuis /openapi/v2, ces deux paramètres n'atteignent jamais la méthode, donc listCoreV1NamespacedPod arrive sans argument aNamespace et l'URL garde son marqueur {namespace}. Généré depuis le document /openapi/v3 du même groupe, l'argument est bien là. Utilisez les documents v3.

Le groupe CRD ne compile pas

apis/apiextensions.k8s.io/v1 décrit JSONSchemaProps.enum comme un tableau d'un schéma qui ne déclare aucun type, donc le générateur émet TArray<> et le compilateur le rejette. Cela fait deux lignes dans l'unité. Ignorez ce groupe, ou générez le document agrégé en passant aussi ces 14 opérations à -x et -p, ce qui retire la classe et l'unité entière compile alors.

Le document agrégé est énorme

602 chemins, 1 202 méthodes et une unité d'environ 197 000 lignes et 13 Mo. Il se lit et se génère en moins d'une seconde, mais l'éditeur de l'IDE est lent avec un fichier de cette taille. Les unités par groupe n'en sont qu'une fraction, 42 705 lignes pour le groupe core et 17 061 pour apps.

L'autorité de certification du cluster est à votre charge

La plupart des clusters utilisent une CA auto-signée, donc la poignée de main TLS échoue tant que vous n'avez pas dit quoi approuver. Le client généré expose OnSSLVerifyPeer, OnSSLGetHandler et OnSSLAfterCreateHandler, c'est là que vous installez le bundle de CA du cluster tiré de votre kubeconfig.

Les watches ne sont pas des énumérables

watch=true et un log de conteneur avec follow=true sont des réponses chunked de longue durée. La méthode générée est une requête ordinaire qui rend la main quand la réponse se termine, donc un watch en direct est quelque chose que vous construisez sur TsgcHTTP1Client plutôt que quelque chose que le client généré diffuse pour vous.

Les tokens de ServiceAccount liés expirent

Ils sont limités dans le temps depuis Kubernetes 1.21. Relisez /var/run/secrets/kubernetes.io/serviceaccount/token depuis l'intérieur du cluster, ou appelez l'API TokenRequest depuis l'extérieur, et réaffectez Authentication.Token.BearerToken. Le client garde ce que vous lui avez donné en dernier.

Depuis le blog

Parseur OpenAPI Delphi

Comment le lecteur gère les spécifications réelles, et ce qu'il consigne dans Warnings quand il ne peut pas honorer quelque chose.

Lire le billet →

Client OpenAPI + parseur

Le billet compagnon qui présente le client généré et le lecteur sur lequel il repose.

Lire le billet →

sgcOpenAPI 2026.6

Notes de release de la version actuelle, avec les options du générateur et les changements du lecteur.

Lire le billet →
Meilleur rapport qualité-prix : All-AccessTous les produits eSeGeCe, Support Premium inclus, à partir de €1,059/an.
Voir les tarifs All-Access

Pilotez Kubernetes depuis Delphi aujourd'hui

sgcOpenAPI livre le lecteur, le générateur de code, le serveur OpenAPI et des SDK préconçus pour Amazon, Azure, Google et Microsoft. Un produit, trois niveaux, au prix par poste plutôt que par fonctionnalité.