911e42996b
- GitHub Actions: login with secrets.HARBOR_USERNAME + HARBOR_PASSWORD - deploy.sh step 7: creates stonks-oracle project, robot account, tag retention - All API calls are idempotent (safe to re-run)
192 lines
7.8 KiB
Bash
Executable File
192 lines
7.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# deploy.sh — Deploy Harbor container registry to Kubernetes
|
|
# Run from gremlin-1: bash ~/sources/kube/harbor/deploy.sh
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
echo "=== Harbor Container Registry Deploy ==="
|
|
echo ""
|
|
|
|
# -------------------------------------------------------
|
|
# 1. Create namespace
|
|
# -------------------------------------------------------
|
|
echo "--- Step 1: Creating namespace ---"
|
|
kubectl create namespace harbor-service --dry-run=client -o yaml | kubectl apply -f -
|
|
echo " ✓ harbor-service namespace ready"
|
|
echo ""
|
|
|
|
# -------------------------------------------------------
|
|
# 2. Proxy CA cert (for Squid SSL bump)
|
|
# -------------------------------------------------------
|
|
echo "--- Step 2: Proxy CA cert ---"
|
|
CA_CERT_PATH="/tmp/harbor-home.crt"
|
|
if curl -sf http://192.168.42.1/home.crt -o "$CA_CERT_PATH" 2>/dev/null; then
|
|
if ! kubectl get configmap proxy-ca-cert -n harbor-service > /dev/null 2>&1; then
|
|
kubectl create configmap proxy-ca-cert --from-file=ca.crt="$CA_CERT_PATH" -n harbor-service
|
|
echo " ✓ proxy-ca-cert created"
|
|
else
|
|
echo " ✓ proxy-ca-cert already exists"
|
|
fi
|
|
else
|
|
echo " ⚠ Could not fetch CA cert (non-fatal)"
|
|
fi
|
|
echo ""
|
|
|
|
# -------------------------------------------------------
|
|
# 3. Create NFS directories (requires root for mount)
|
|
# -------------------------------------------------------
|
|
echo "--- Step 3: Ensuring NFS directories ---"
|
|
if [ "$(id -u)" -eq 0 ]; then
|
|
mkdir -p /tmp/harbor-nfs-init
|
|
mount -t nfs 192.168.42.8:/volume1/Kubernetes/harbor /tmp/harbor-nfs-init 2>/dev/null || true
|
|
mkdir -p /tmp/harbor-nfs-init/data/registry
|
|
mkdir -p /tmp/harbor-nfs-init/data/redis
|
|
mkdir -p /tmp/harbor-nfs-init/data/jobservice
|
|
mkdir -p /tmp/harbor-nfs-init/data/trivy
|
|
umount /tmp/harbor-nfs-init 2>/dev/null || true
|
|
rmdir /tmp/harbor-nfs-init 2>/dev/null || true
|
|
echo " ✓ NFS directories ready"
|
|
else
|
|
echo " ⚠ Not root — skipping NFS dir creation (dirs may already exist)"
|
|
fi
|
|
echo ""
|
|
|
|
# -------------------------------------------------------
|
|
# 4. Apply PVs and PVCs
|
|
# -------------------------------------------------------
|
|
echo "--- Step 4: Applying PVs and PVCs ---"
|
|
kubectl apply -f "$SCRIPT_DIR/../pvs/harbor-pv.yaml"
|
|
kubectl apply -f "$SCRIPT_DIR/pvcs.yaml"
|
|
echo " ✓ PVs and PVCs applied"
|
|
echo ""
|
|
|
|
# -------------------------------------------------------
|
|
# 5. Remove old plain Docker Registry ingress
|
|
# -------------------------------------------------------
|
|
echo "--- Step 5: Checking old registry ingress ---"
|
|
if kubectl get ingress registry-ingress -n git-server > /dev/null 2>&1; then
|
|
echo " Removing old registry ingress from git-server namespace..."
|
|
kubectl delete ingress registry-ingress -n git-server
|
|
echo " ✓ Old registry ingress removed"
|
|
else
|
|
echo " ✓ No old registry ingress found"
|
|
fi
|
|
echo ""
|
|
|
|
# -------------------------------------------------------
|
|
# 6. Install/upgrade Harbor via Helm
|
|
# -------------------------------------------------------
|
|
echo "--- Step 6: Installing Harbor ---"
|
|
helm repo add harbor https://helm.goharbor.io 2>/dev/null || true
|
|
helm repo update harbor 2>/dev/null || true
|
|
|
|
HARBOR_EXISTS=$(helm list -n harbor-service -q 2>/dev/null | grep -c harbor || true)
|
|
if [ "${HARBOR_EXISTS:-0}" -gt 0 ]; then
|
|
echo " Harbor already installed — upgrading..."
|
|
else
|
|
echo " Fresh Harbor install..."
|
|
fi
|
|
|
|
helm upgrade --install harbor harbor/harbor \
|
|
--namespace harbor-service \
|
|
--values "$SCRIPT_DIR/values.yaml" \
|
|
--timeout 10m \
|
|
--wait
|
|
|
|
echo ""
|
|
echo " Waiting for Harbor core to be ready..."
|
|
kubectl wait --for=condition=ready pod -l app=harbor,component=core -n harbor-service --timeout=180s || true
|
|
echo ""
|
|
|
|
# -------------------------------------------------------
|
|
# 7. Configure Harbor via API (idempotent)
|
|
# -------------------------------------------------------
|
|
echo "--- Step 7: Configuring Harbor project and robot account ---"
|
|
HARBOR_API="https://registry.celestium.life/api/v2.0"
|
|
HARBOR_AUTH="admin:St0nks0racl3!"
|
|
|
|
# Create stonks-oracle project if it doesn't exist
|
|
if curl -sf -u "$HARBOR_AUTH" "$HARBOR_API/projects?name=stonks-oracle" | python3 -c "import sys,json; sys.exit(0 if json.load(sys.stdin) else 1)" 2>/dev/null; then
|
|
echo " ✓ Project stonks-oracle already exists"
|
|
else
|
|
curl -sf -X POST -u "$HARBOR_AUTH" \
|
|
-H "Content-Type: application/json" \
|
|
"$HARBOR_API/projects" \
|
|
-d '{"project_name":"stonks-oracle","public":true,"metadata":{"auto_scan":"true","severity":"high"},"storage_limit":-1}'
|
|
echo " ✓ Project stonks-oracle created (public, auto-scan enabled)"
|
|
fi
|
|
|
|
# Create CI robot account if it doesn't exist
|
|
EXISTING_ROBOT=$(curl -sf -u "$HARBOR_AUTH" "$HARBOR_API/robots" 2>/dev/null | python3 -c "
|
|
import sys, json
|
|
robots = json.load(sys.stdin)
|
|
for r in robots:
|
|
if 'ci-push' in r.get('name', ''):
|
|
print(r['name'])
|
|
break
|
|
" 2>/dev/null || true)
|
|
|
|
if [ -n "$EXISTING_ROBOT" ]; then
|
|
echo " ✓ Robot account already exists: $EXISTING_ROBOT"
|
|
else
|
|
ROBOT_RESP=$(curl -sf -X POST -u "$HARBOR_AUTH" \
|
|
-H "Content-Type: application/json" \
|
|
"$HARBOR_API/robots" \
|
|
-d '{
|
|
"name":"ci-push",
|
|
"description":"CI/CD pipeline push account",
|
|
"duration":-1,
|
|
"level":"project",
|
|
"permissions":[{
|
|
"namespace":"stonks-oracle",
|
|
"kind":"project",
|
|
"access":[
|
|
{"resource":"repository","action":"push"},
|
|
{"resource":"repository","action":"pull"},
|
|
{"resource":"tag","action":"create"},
|
|
{"resource":"tag","action":"list"},
|
|
{"resource":"artifact","action":"read"}
|
|
]
|
|
}]
|
|
}')
|
|
ROBOT_NAME=$(echo "$ROBOT_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['name'])")
|
|
ROBOT_SECRET=$(echo "$ROBOT_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['secret'])")
|
|
echo " ✓ Robot account created"
|
|
echo " Username: $ROBOT_NAME"
|
|
echo " Secret: $ROBOT_SECRET"
|
|
echo " ⚠ Save these — add as HARBOR_USERNAME and HARBOR_PASSWORD in your CI secrets"
|
|
fi
|
|
|
|
# Set tag retention policy (idempotent — check if one exists first)
|
|
PROJECT_ID=$(curl -sf -u "$HARBOR_AUTH" "$HARBOR_API/projects?name=stonks-oracle" | python3 -c "import sys,json; print(json.load(sys.stdin)[0]['project_id'])" 2>/dev/null || true)
|
|
if [ -n "$PROJECT_ID" ]; then
|
|
EXISTING_RETENTION=$(curl -sf -u "$HARBOR_AUTH" "$HARBOR_API/retentions" 2>/dev/null || true)
|
|
if echo "$EXISTING_RETENTION" | python3 -c "import sys,json; d=json.load(sys.stdin); sys.exit(0 if isinstance(d,list) and len(d)>0 else 1)" 2>/dev/null; then
|
|
echo " ✓ Tag retention policy already exists"
|
|
else
|
|
curl -sf -X POST -u "$HARBOR_AUTH" \
|
|
-H "Content-Type: application/json" \
|
|
"$HARBOR_API/retentions" \
|
|
-d "{
|
|
\"algorithm\":\"or\",
|
|
\"scope\":{\"level\":\"project\",\"ref\":$PROJECT_ID},
|
|
\"trigger\":{\"kind\":\"Schedule\",\"settings\":{\"cron\":\"0 0 0 * * *\"}},
|
|
\"rules\":[
|
|
{\"disabled\":false,\"action\":\"retain\",\"scope_selectors\":{\"repository\":[{\"kind\":\"doublestar\",\"decoration\":\"repoMatches\",\"pattern\":\"**\"}]},\"tag_selectors\":[{\"kind\":\"doublestar\",\"decoration\":\"matches\",\"pattern\":\"latest\"}],\"params\":{}},
|
|
{\"disabled\":false,\"action\":\"retain\",\"scope_selectors\":{\"repository\":[{\"kind\":\"doublestar\",\"decoration\":\"repoMatches\",\"pattern\":\"**\"}]},\"tag_selectors\":[{\"kind\":\"doublestar\",\"decoration\":\"matches\",\"pattern\":\"**\"}],\"params\":{\"latestPushedK\":10}}
|
|
]
|
|
}" 2>/dev/null && echo " ✓ Tag retention policy created (keep latest + last 10 tags, daily)" || echo " ⚠ Could not create retention policy (non-fatal)"
|
|
fi
|
|
fi
|
|
echo ""
|
|
|
|
echo "=== Harbor Deploy Complete ==="
|
|
echo ""
|
|
echo " URL: https://registry.celestium.life"
|
|
echo " Login: admin / St0nks0racl3!"
|
|
echo ""
|
|
echo " Pods:"
|
|
kubectl get pods -n harbor-service
|