# Namespace, image ref, and storage class confirmed against this cluster
# (microk8s, 2026-09-04). Image is pushed to Nexus for a durable, off-node
# copy (docker push localhost:30892/... — see README), but the Deployment
# below pulls it from the *node's local containerd image store* instead of
# over the network: kubelet's image pulls run in the host network namespace,
# which uses this node's public DNS resolver, not cluster CoreDNS, so
# `nexus-service.nexus.svc.cluster.local` is NOT resolvable for a plain pull
# (only for in-cluster builders like Kaniko, whose *build* pod runs in pod
# netns). The `microk8s-hostpath` PVC below also pins every pod to whichever
# node created it (`ai-workstation`, confirmed via the PV's nodeAffinity), so
# a single local `ctr image import` of the pushed tar is enough — see
# vote-service/README.md for the import command. `imagePullPolicy: Never`
# enforces that: no accidental network pull attempt, no ImagePullBackOff.
# `ai-for-dummies` did not exist yet as a namespace, so it is created below,
# matching the one-namespace-per-app pattern every other small app in this
# cluster uses (judge0, minio, pragent, …). No storageClassName set:
# microk8s's `hostpath-storage` addon is the default.
apiVersion: v1
kind: Namespace
metadata:
  name: ai-for-dummies
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ai-for-dummies-vote
  namespace: ai-for-dummies
  labels:
    app: ai-for-dummies-vote
spec:
  replicas: 1 # single replica: the store is one JSON file on one PVC, not a shared DB
  selector:
    matchLabels:
      app: ai-for-dummies-vote
  strategy:
    type: Recreate # avoid two pods writing the same PVC-backed file at once
  template:
    metadata:
      labels:
        app: ai-for-dummies-vote
    spec:
      # Pinned to `kubernets`: the image is imported straight into that node's
      # containerd store (see README) and `microk8s-hostpath` PVs carry a
      # nodeAffinity for whichever node first binds them, so scheduling and
      # storage must agree on one node. `kubernets` is the control-plane node
      # that hosts the rest of this cluster's workloads.
      nodeSelector:
        kubernetes.io/hostname: kubernets
      securityContext:
        fsGroup: 65532 # matches distroless "nonroot" uid/gid; without it the PVC mounts root-owned and the container can't write votes.json
      containers:
        - name: vote-service
          image: localhost:30892/ai-for-dummies-vote-service:latest
          imagePullPolicy: Never # image is side-loaded via `ctr image import`; never fetch over the network
          ports:
            - containerPort: 8080
          env:
            - name: PORT
              value: "8080"
            - name: VOTE_DB_PATH
              value: /data/votes.json
            - name: ALLOWED_ORIGIN
              value: https://netcracker.pages.marcospaulo.dev.br
          resources:
            requests: { cpu: 10m, memory: 16Mi }
            limits: { cpu: 100m, memory: 64Mi }
          readinessProbe:
            httpGet: { path: /healthz, port: 8080 }
            initialDelaySeconds: 2
          livenessProbe:
            httpGet: { path: /healthz, port: 8080 }
            initialDelaySeconds: 5
          volumeMounts:
            - name: data
              mountPath: /data
          securityContext:
            runAsNonRoot: true
            readOnlyRootFilesystem: true
            allowPrivilegeEscalation: false
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: ai-for-dummies-vote-data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ai-for-dummies-vote-data
  namespace: ai-for-dummies
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 100Mi
---
apiVersion: v1
kind: Service
metadata:
  name: ai-for-dummies-vote
  namespace: ai-for-dummies
spec:
  selector:
    app: ai-for-dummies-vote
  ports:
    - port: 80
      targetPort: 8080
