Some checks are pending
Bidi Control Character Guard / bidi-control-guard (push) Waiting to run
Circular Dependency Check / Check for new circular dependencies (push) Waiting to run
Citus Migration Smoke / Combined migrations on single-node Citus (push) Waiting to run
E2E Fresh Install Tests / fresh-install-e2e (push) Waiting to run
ext-v2 guardrails / Run ext-v2 guard and ESLint (push) Waiting to run
Integration Tests / Check for relevant changes (push) Waiting to run
Integration Tests / ${{ (github.event_name == 'schedule' || github.event.inputs.suite == 'full') && 'Full integration suite' || 'Tier-1 integration subset' }} (push) Blocked by required conditions
Mobile checks / Mobile lint + typecheck (push) Waiting to run
Mobile checks / Mobile unit tests (push) Waiting to run
Mobile checks / Mobile dependency audit (report) (push) Waiting to run
Mobile checks / Mobile reproducibility checks (push) Waiting to run
Secrets guard (env backups) / Ensure no tracked env backup files (push) Waiting to run
Temporal Readiness / fast-readiness (push) Waiting to run
Temporal Readiness / docker-parity (push) Waiting to run
TypeScript Type Check / Nx affected typecheck (push) Waiting to run
Unit Tests / Skipped-test budget (push) Waiting to run
Unit Tests / Nx affected unit tests (push) Waiting to run
Unit Tests / Server unit coverage (informational) (push) Waiting to run
Validate Tenant Management Schema / Check for relevant changes (push) Waiting to run
Validate Tenant Management Schema / Validate Tenant Management Schema (push) Blocked by required conditions
EE Workflows Build Guard / ee-workflows-build-guard (push) Waiting to run
Excluded: .git, node_modules, secrets/, compose.env, assemblyscript tgz Source: /opt/alga-psa on psa.joliet.tech
271 lines
7.2 KiB
Bash
Executable File
271 lines
7.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
KUBECONFIG_PATH="${KUBECONFIG:-}"
|
|
APPLIANCE_ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
|
|
STORAGE_MANIFEST="$APPLIANCE_ROOT/manifests/local-path-storage.yaml"
|
|
STORAGE_PATH="/var/mnt/alga-data/local-path-provisioner"
|
|
SMOKE_NAMESPACE="storage-smoke"
|
|
DRY_RUN=false
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage:
|
|
install-storage.sh --kubeconfig <path> [options]
|
|
|
|
Options:
|
|
--kubeconfig <path> Kubeconfig path
|
|
--dry-run Print the commands without mutating the cluster
|
|
--help Show this help
|
|
EOF
|
|
}
|
|
|
|
require_command() {
|
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
echo "Required command not found: $1" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
run_cmd() {
|
|
if $DRY_RUN; then
|
|
printf '+'
|
|
for arg in "$@"; do
|
|
printf ' %q' "$arg"
|
|
done
|
|
printf '\n'
|
|
return 0
|
|
fi
|
|
|
|
"$@"
|
|
}
|
|
|
|
kubectl_cmd() {
|
|
run_cmd kubectl --kubeconfig "$KUBECONFIG_PATH" "$@"
|
|
}
|
|
|
|
wait_for_rollout() {
|
|
if $DRY_RUN; then
|
|
echo "+ kubectl --kubeconfig $KUBECONFIG_PATH -n local-path-storage rollout status deployment/local-path-provisioner --timeout=5m"
|
|
return 0
|
|
fi
|
|
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" -n local-path-storage rollout status deployment/local-path-provisioner --timeout=5m
|
|
}
|
|
|
|
prepare_storage_path() {
|
|
local manifest
|
|
|
|
if $DRY_RUN; then
|
|
cat <<EOF
|
|
+ kubectl --kubeconfig $KUBECONFIG_PATH apply -f -
|
|
apiVersion: batch/v1
|
|
kind: Job
|
|
metadata:
|
|
name: local-path-storage-prepare
|
|
namespace: local-path-storage
|
|
EOF
|
|
return 0
|
|
fi
|
|
|
|
manifest="$(cat <<EOF
|
|
apiVersion: batch/v1
|
|
kind: Job
|
|
metadata:
|
|
name: local-path-storage-prepare
|
|
namespace: local-path-storage
|
|
spec:
|
|
ttlSecondsAfterFinished: 300
|
|
backoffLimit: 0
|
|
template:
|
|
spec:
|
|
restartPolicy: Never
|
|
containers:
|
|
- name: prepare
|
|
image: busybox:1.36
|
|
securityContext:
|
|
privileged: true
|
|
command:
|
|
- sh
|
|
- -ec
|
|
- |
|
|
mkdir -p /host${STORAGE_PATH}
|
|
chmod 0777 /host${STORAGE_PATH}
|
|
volumeMounts:
|
|
- name: host-root
|
|
mountPath: /host
|
|
volumes:
|
|
- name: host-root
|
|
hostPath:
|
|
path: /
|
|
type: Directory
|
|
EOF
|
|
)"
|
|
|
|
printf '%s\n' "$manifest" | kubectl --kubeconfig "$KUBECONFIG_PATH" apply -f -
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" -n local-path-storage wait --for=condition=complete --timeout=5m job/local-path-storage-prepare
|
|
}
|
|
|
|
reconcile_existing_storage_class() {
|
|
if $DRY_RUN; then
|
|
echo "+ inspect existing local-path StorageClass and delete it only when it is incompatible and unused"
|
|
return 0
|
|
fi
|
|
|
|
if ! kubectl --kubeconfig "$KUBECONFIG_PATH" get storageclass local-path >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
|
|
local reclaim_policy=""
|
|
reclaim_policy="$(kubectl --kubeconfig "$KUBECONFIG_PATH" get storageclass local-path -o jsonpath='{.reclaimPolicy}' 2>/dev/null || true)"
|
|
if [ "$reclaim_policy" = "Retain" ]; then
|
|
return 0
|
|
fi
|
|
|
|
local pv_count pvc_count
|
|
pv_count="$(kubectl --kubeconfig "$KUBECONFIG_PATH" get pv -o jsonpath='{range .items[?(@.spec.storageClassName=="local-path")]}x{end}' 2>/dev/null | wc -c | tr -d ' ')"
|
|
pvc_count="$(kubectl --kubeconfig "$KUBECONFIG_PATH" get pvc -A -o jsonpath='{range .items[?(@.spec.storageClassName=="local-path")]}x{end}' 2>/dev/null | wc -c | tr -d ' ')"
|
|
if [ "${pv_count:-0}" != "0" ] || [ "${pvc_count:-0}" != "0" ]; then
|
|
echo "Existing local-path StorageClass has reclaimPolicy=$reclaim_policy and is already in use; refusing to replace it automatically." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Replacing unused local-path StorageClass with appliance Retain policy."
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" delete storageclass local-path
|
|
}
|
|
|
|
run_smoke_test() {
|
|
local manifest
|
|
|
|
if $DRY_RUN; then
|
|
cat <<EOF
|
|
+ kubectl --kubeconfig $KUBECONFIG_PATH create namespace $SMOKE_NAMESPACE --dry-run=client -o yaml | kubectl apply -f -
|
|
+ kubectl --kubeconfig $KUBECONFIG_PATH label namespace $SMOKE_NAMESPACE pod-security.kubernetes.io/enforce=privileged pod-security.kubernetes.io/audit=privileged pod-security.kubernetes.io/warn=privileged --overwrite
|
|
+ kubectl --kubeconfig $KUBECONFIG_PATH apply -f -
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: storage-smoke-pvc
|
|
namespace: $SMOKE_NAMESPACE
|
|
---
|
|
apiVersion: batch/v1
|
|
kind: Job
|
|
metadata:
|
|
name: storage-smoke
|
|
namespace: $SMOKE_NAMESPACE
|
|
EOF
|
|
return 0
|
|
fi
|
|
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" create namespace "$SMOKE_NAMESPACE" --dry-run=client -o yaml | kubectl --kubeconfig "$KUBECONFIG_PATH" apply -f -
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" label namespace "$SMOKE_NAMESPACE" \
|
|
pod-security.kubernetes.io/enforce=privileged \
|
|
pod-security.kubernetes.io/audit=privileged \
|
|
pod-security.kubernetes.io/warn=privileged \
|
|
--overwrite
|
|
|
|
manifest="$(cat <<EOF
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: storage-smoke-pvc
|
|
namespace: $SMOKE_NAMESPACE
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
storageClassName: local-path
|
|
resources:
|
|
requests:
|
|
storage: 1Gi
|
|
---
|
|
apiVersion: batch/v1
|
|
kind: Job
|
|
metadata:
|
|
name: storage-smoke
|
|
namespace: $SMOKE_NAMESPACE
|
|
spec:
|
|
backoffLimit: 0
|
|
template:
|
|
spec:
|
|
restartPolicy: Never
|
|
containers:
|
|
- name: smoke
|
|
image: busybox:1.36
|
|
command:
|
|
- sh
|
|
- -c
|
|
- echo ok > /data/ready && cat /data/ready
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /data
|
|
volumes:
|
|
- name: data
|
|
persistentVolumeClaim:
|
|
claimName: storage-smoke-pvc
|
|
EOF
|
|
)"
|
|
|
|
printf '%s\n' "$manifest" | kubectl --kubeconfig "$KUBECONFIG_PATH" apply -f -
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" -n "$SMOKE_NAMESPACE" wait --for=condition=complete --timeout=5m job/storage-smoke
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" -n "$SMOKE_NAMESPACE" logs job/storage-smoke >/dev/null
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" delete namespace "$SMOKE_NAMESPACE" --ignore-not-found >/dev/null
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--kubeconfig)
|
|
KUBECONFIG_PATH="$2"
|
|
shift 2
|
|
;;
|
|
--dry-run)
|
|
DRY_RUN=true
|
|
shift
|
|
;;
|
|
--help|-h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown argument: $1" >&2
|
|
usage >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
require_command kubectl
|
|
|
|
if [ -z "$KUBECONFIG_PATH" ]; then
|
|
echo "Kubeconfig path is required via --kubeconfig or KUBECONFIG." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$KUBECONFIG_PATH" ] && ! $DRY_RUN; then
|
|
echo "Kubeconfig file not found: $KUBECONFIG_PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ ! -f "$STORAGE_MANIFEST" ]; then
|
|
echo "Storage manifest not found: $STORAGE_MANIFEST" >&2
|
|
exit 1
|
|
fi
|
|
|
|
reconcile_existing_storage_class
|
|
kubectl_cmd apply -f "$STORAGE_MANIFEST"
|
|
if $DRY_RUN; then
|
|
echo "+ kubectl --kubeconfig $KUBECONFIG_PATH create namespace msp --dry-run=client -o yaml | kubectl --kubeconfig $KUBECONFIG_PATH apply -f -"
|
|
else
|
|
kubectl --kubeconfig "$KUBECONFIG_PATH" create namespace msp --dry-run=client -o yaml | kubectl --kubeconfig "$KUBECONFIG_PATH" apply -f -
|
|
fi
|
|
kubectl_cmd label namespace msp \
|
|
pod-security.kubernetes.io/enforce=privileged \
|
|
pod-security.kubernetes.io/audit=privileged \
|
|
pod-security.kubernetes.io/warn=privileged \
|
|
--overwrite
|
|
|
|
prepare_storage_path
|
|
wait_for_rollout
|
|
run_smoke_test
|
|
|
|
echo "Storage prerequisites are ready."
|