# MinIO — Ephemeral object storage for integration tests # Namespace is substituted at runtime via envsubst # No persistence — uses emptyDir # Credentials: minioadmin/minioadmin (hardcoded for ephemeral sandbox) # Includes a Job that waits for MinIO readiness and creates the stonks-normalized bucket --- apiVersion: apps/v1 kind: Deployment metadata: name: minio namespace: ${NAMESPACE} labels: app: minio tier: infra app.kubernetes.io/part-of: stonks-oracle spec: replicas: 1 selector: matchLabels: app: minio template: metadata: labels: app: minio tier: infra spec: automountServiceAccountToken: false imagePullSecrets: - name: dockerhub-credentials securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 fsGroup: 1000 seccompProfile: type: RuntimeDefault containers: - name: minio image: minio/minio:latest imagePullPolicy: IfNotPresent args: ["server", "/data"] ports: - containerPort: 9000 protocol: TCP - containerPort: 9001 protocol: TCP env: - name: MINIO_ROOT_USER value: "minioadmin" - name: MINIO_ROOT_PASSWORD value: "minioadmin" securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] resources: requests: cpu: 100m memory: 256Mi limits: cpu: 500m memory: 512Mi readinessProbe: httpGet: path: /minio/health/ready port: 9000 initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 failureThreshold: 6 livenessProbe: httpGet: path: /minio/health/live port: 9000 initialDelaySeconds: 15 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3 volumeMounts: - name: data mountPath: /data volumes: - name: data emptyDir: sizeLimit: 1Gi --- apiVersion: v1 kind: Service metadata: name: minio namespace: ${NAMESPACE} labels: app: minio tier: infra app.kubernetes.io/part-of: stonks-oracle spec: selector: app: minio ports: - port: 9000 targetPort: 9000 protocol: TCP --- apiVersion: batch/v1 kind: Job metadata: name: minio-bucket-init namespace: ${NAMESPACE} labels: app: minio tier: infra app.kubernetes.io/part-of: stonks-oracle spec: backoffLimit: 4 template: metadata: labels: app: minio-bucket-init tier: infra spec: imagePullSecrets: - name: dockerhub-credentials automountServiceAccountToken: false securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 1000 seccompProfile: type: RuntimeDefault restartPolicy: OnFailure containers: - name: bucket-init image: registry.celestium.life/dockerhub-cache/library/python:3.12-slim imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] resources: requests: cpu: 50m memory: 64Mi limits: cpu: 250m memory: 128Mi env: - name: HTTP_PROXY value: "" - name: HTTPS_PROXY value: "" - name: http_proxy value: "" - name: https_proxy value: "" - name: NO_PROXY value: "*" - name: no_proxy value: "*" command: ["python", "-c"] args: - | import urllib.request, urllib.error, time # Disable all proxy usage in urllib no_proxy_handler = urllib.request.ProxyHandler({}) opener = urllib.request.build_opener(no_proxy_handler) urllib.request.install_opener(opener) endpoint = "http://minio:9000" max_wait = 60 # Wait for MinIO readiness print("Waiting for MinIO to be ready...") start = time.time() while time.time() - start < max_wait: try: r = urllib.request.urlopen(f"{endpoint}/minio/health/ready", timeout=3) if r.status == 200: print("MinIO is ready.") break except Exception: pass time.sleep(2) else: raise SystemExit("MinIO did not become ready within 60s") # Create bucket via S3 PUT request bucket = "stonks-normalized" req = urllib.request.Request(f"{endpoint}/{bucket}", method="PUT") try: urllib.request.urlopen(req, timeout=5) print(f"Bucket '{bucket}' created successfully.") except urllib.error.HTTPError as e: if e.code == 409: print(f"Bucket '{bucket}' already exists.") else: raise