# services/harbor/bootstrap-jobs/cassandra-registry-ensure-job.yaml
# One-off repair/audit job for the Cassandra Harbor migration.
# Keep suspended unless the Harbor project or robot scopes need to be recreated.
apiVersion: batch/v1
kind: Job
metadata:
  name: cassandra-registry-ensure-1
  namespace: harbor
spec:
  suspend: true
  backoffLimit: 1
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/agent-pre-populate-only: "true"
        vault.hashicorp.com/role: "harbor"
        vault.hashicorp.com/agent-inject-secret-harbor-admin.sh: "kv/data/atlas/harbor/harbor-core"
        vault.hashicorp.com/agent-inject-template-harbor-admin.sh: |
          {{- with secret "kv/data/atlas/harbor/harbor-core" }}
          export HARBOR_ADMIN_PASSWORD="{{ .Data.data.harbor_admin_password }}"
          {{- end }}
    spec:
      restartPolicy: Never
      serviceAccountName: harbor-vault-sync
      containers:
        - name: ensure
          image: python:3.11-alpine
          command: ["python", "-c"]
          args:
            - |
              import base64
              import json
              import os
              import urllib.error
              import urllib.request

              secret_path = "/vault/secrets/harbor-admin.sh"
              env = {}
              with open(secret_path, "r", encoding="utf-8") as handle:
                  for line in handle:
                      line = line.strip()
                      if not line.startswith("export "):
                          continue
                      key, value = line[len("export ") :].split("=", 1)
                      env[key] = value.strip('"')

              password = env["HARBOR_ADMIN_PASSWORD"]
              api = os.environ.get(
                  "HARBOR_API",
                  "http://harbor-core.harbor.svc.cluster.local/api/v2.0",
              ).rstrip("/")
              auth = base64.b64encode(f"admin:{password}".encode("utf-8")).decode("ascii")

              def request(method, path, payload=None, ok=(200,)):
                  data = None
                  headers = {"Authorization": f"Basic {auth}"}
                  if payload is not None:
                      data = json.dumps(payload).encode("utf-8")
                      headers["Content-Type"] = "application/json"
                  req = urllib.request.Request(
                      f"{api}{path}",
                      data=data,
                      method=method,
                      headers=headers,
                  )
                  try:
                      with urllib.request.urlopen(req, timeout=30) as response:
                          body = response.read()
                          if response.status not in ok:
                              raise RuntimeError(f"{method} {path} returned {response.status}")
                          if not body:
                              return None
                          return json.loads(body.decode("utf-8"))
                  except urllib.error.HTTPError as exc:
                      detail = exc.read().decode("utf-8", errors="replace")
                      if exc.code in ok:
                          return None
                      raise RuntimeError(f"{method} {path} returned {exc.code}: {detail}") from exc

              projects = request("GET", "/projects?name=cassandra")
              if not projects:
                  request(
                      "POST",
                      "/projects",
                      {
                          "project_name": "cassandra",
                          "metadata": {
                              "public": "false",
                              "auto_scan": "false",
                              "enable_content_trust": "false",
                              "prevent_vul": "false",
                              "reuse_sys_cve_allowlist": "true",
                          },
                      },
                      ok=(201, 409),
                  )

              def ensure_permission(robot_name, access, description=None):
                  robots = request("GET", "/robots?page_size=100")
                  matches = [robot for robot in robots if robot.get("name") == robot_name]
                  if not matches:
                      raise RuntimeError(f"Harbor robot {robot_name} not found")
                  robot = request("GET", f"/robots/{matches[0]['id']}")
                  permissions = list(robot.get("permissions") or [])
                  if not any(
                      item.get("kind") == "project" and item.get("namespace") == "cassandra"
                      for item in permissions
                  ):
                      permissions.append(
                          {"kind": "project", "namespace": "cassandra", "access": access}
                      )
                  payload = {
                      "name": robot["name"],
                      "level": robot["level"],
                      "disable": bool(robot.get("disable", False)),
                      "duration": int(robot.get("duration", -1)),
                      "permissions": permissions,
                  }
                  if description:
                      payload["description"] = description
                  elif robot.get("description"):
                      payload["description"] = robot["description"]
                  request("PUT", f"/robots/{robot['id']}", payload, ok=(200,))

              ensure_permission(
                  "robot$pull-atlas",
                  [{"resource": "repository", "action": "pull"}],
              )
              ensure_permission(
                  "robot$jenkins-pipelines",
                  [
                      {"resource": "repository", "action": "pull"},
                      {"resource": "repository", "action": "push"},
                  ],
                  "Jenkins image push robot for bstein, veles, and cassandra pipelines",
              )
              print("Cassandra Harbor project and robot scopes are present")
