{
  "repo": "tidbcloud/core-svc",
  "binary": "graceful-shutdown-tidb-webhook",
  "binary_path": "portal/cmd/graceful-shutdown-tidb-webhook/main.go",
  "dependencies": {
    "WebhookLifecycle.ParseFlags": {
      "infrastructure": {},
      "services": []
    },
    "WebhookLifecycle.BuildRestConfig": {
      "infrastructure": {
        "filesystem": {
          "conditions": [
            "Only when --kubeconfig is set"
          ],
          "operations": [
            {
              "operation": "READ",
              "trigger": "Load the external kubeconfig used to build the rest.Config",
              "conditions": [
                "Only when kubeConfig != \"\""
              ],
              "implementation": "clientcmd.BuildConfigFromFlags(\"\", kubeConfig)"
            }
          ]
        }
      },
      "services": []
    },
    "WebhookLifecycle.CreateClients": {
      "infrastructure": {
        "kubernetes_api": {
          "conditions": [
            "Always after BuildRestConfig succeeds"
          ],
          "operations": [
            {
              "operation": "CREATE_CLIENT",
              "trigger": "Create the Kubernetes core clientset and TiDB Operator clientset used by the webhook handler",
              "conditions": [
                "Always before the HTTPS server starts"
              ],
              "implementation": "kubernetes.NewForConfig(cfg); versioned.NewForConfig(cfg)"
            }
          ]
        }
      },
      "services": []
    },
    "WebhookLifecycle.StartTLSServer": {
      "infrastructure": {
        "filesystem": {
          "conditions": [
            "TLS secret mounted at /run/secrets/tls"
          ],
          "operations": [
            {
              "operation": "READ",
              "trigger": "Load the TLS certificate and key used by the webhook listener",
              "conditions": [
                "Always before ListenAndServeTLS"
              ],
              "implementation": "filepath.Join(tlsDir, corev1.TLSCertKey); filepath.Join(tlsDir, corev1.TLSPrivateKeyKey)"
            }
          ]
        },
        "http_server": {
          "conditions": [
            "Kubernetes clients initialized successfully"
          ],
          "operations": [
            {
              "operation": "LISTEN_AND_SERVE_TLS",
              "trigger": "Serve the admission webhook on port 8443",
              "conditions": [
                "Always after mux.Handle(\"/validate\", admitFuncHandler(admitDeleteTiDBPods))"
              ],
              "implementation": "server.ListenAndServeTLS(certPath, keyPath)"
            }
          ]
        }
      },
      "services": []
    },
    "HTTP POST /validate": {
      "infrastructure": {
        "kubernetes_api": {
          "conditions": [
            "request.Resource == pods",
            "request namespace is not a Kubernetes-owned namespace",
            "pod carries the graceful shutdown annotation",
            "pod phase is Running",
            "health-checker sidecar is Ready",
            "pod is managed by TiDB Operator and labeled as a TiDB pod"
          ],
          "operations": [
            {
              "operation": "GET",
              "trigger": "Confirm the referenced TiDBCluster still exists before blocking deletion",
              "conditions": [
                "Only when the pod is a TiDB cluster pod and has the instance label"
              ],
              "implementation": "operatorCli.PingcapV1alpha1().TidbClusters(namespace).Get(tcName, metav1.GetOptions{})"
            },
            {
              "operation": "UPDATE",
              "trigger": "Persist the delete-pod request timestamp annotation after the first health-checker down call",
              "conditions": [
                "Only when AnnDeletePodRequestTime is absent"
              ],
              "implementation": "kubeCli.CoreV1().Pods(namespace).Update(pod)"
            }
          ]
        }
      },
      "services": [
        {
          "name": "core-svc/health-checker",
          "target_interface": "HTTP GET /down",
          "operation_type": "http_get",
          "conditions": [
            "Only when AnnDeletePodRequestTime is absent",
            "Only after the pod passed all TiDB graceful-shutdown prechecks"
          ],
          "operations": [
            {
              "operation": "GET",
              "trigger": "Ask the pod-local health-checker sidecar to turn itself unhealthy before refusing the deletion once",
              "conditions": [
                "Only on the first delete request for the pod"
              ],
              "implementation": "httputil.GetBodyOK(client, tidbPodHealthCheckerDownURL(name, tcName, namespace))"
            }
          ]
        }
      ]
    }
  }
}
