#!/bin/sh # Fake kubectl for hack/migration-59-vmi-hotplug-volumes.bats. It serves only # the calls migration 59 and lib/cozystack-version.sh make, and logs each one # to $FAKE_CMDLOG. # # The VMs live in $FAKE_STATE/vms.json and a JSON patch is applied to that # file, so a second run of the migration reads what the first one wrote. # # FAKE_CMDLOG file to append a one-line record of each call to # FAKE_STATE directory holding vms.json and vmis.json # FAKE_NO_KUBEVIRT non-empty => the VirtualMachine CRD is absent # FAKE_CRD_FAIL non-empty => reading the VirtualMachine CRD exits 1 # FAKE_LIST_FAIL non-empty => listing VMs exits 1 with this stderr # FAKE_VMI_LIST_FAIL non-empty => listing VMIs exits 1 with this stderr # FAKE_PATCH_FAIL non-empty => every patch exits 1 with this stderr set -u log() { [ -n "${FAKE_CMDLOG:-}" ] && printf '%s\n' "$*" >> "$FAKE_CMDLOG"; } log "KUBECTL $*" args="$*" arg_after() { k="$1"; shift; p=""; for a in "$@"; do [ "$p" = "$k" ] && { printf '%s' "$a"; return; }; p="$a"; done; } case "$args" in *"apply --filename -"*|*"apply -f -"*) manifest=$(cat) case "$manifest" in *"kind: ConfigMap"*) v=$(printf '%s\n' "$manifest" | sed -n 's/^ version: "\{0,1\}\([0-9]\{1,\}\)"\{0,1\}$/\1/p' | head -1) log "STAMP ${v:-unknown}" exit 0 ;; esac log "APPLY-UNKNOWN" printf 'fake kubectl: unmodelled apply\n' >&2 exit 1 ;; *"get crd virtualmachines.kubevirt.io"*) if [ -n "${FAKE_CRD_FAIL:-}" ]; then printf '%s\n' "$FAKE_CRD_FAIL" >&2; exit 1; fi [ -n "${FAKE_NO_KUBEVIRT:-}" ] || echo "customresourcedefinition.apiextensions.k8s.io/virtualmachines.kubevirt.io" exit 0 ;; *"get virtualmachines.kubevirt.io"*) if [ -n "${FAKE_LIST_FAIL:-}" ]; then printf '%s\n' "$FAKE_LIST_FAIL" >&2; exit 1; fi cat "$FAKE_STATE/vms.json" || exit 1 exit 0 ;; *"get virtualmachineinstances.kubevirt.io"*) if [ -n "${FAKE_VMI_LIST_FAIL:-}" ]; then printf '%s\n' "$FAKE_VMI_LIST_FAIL" >&2; exit 1; fi cat "$FAKE_STATE/vmis.json" || exit 1 exit 0 ;; *"patch virtualmachines.kubevirt.io"*) if [ -n "${FAKE_PATCH_FAIL:-}" ]; then printf '%s\n' "$FAKE_PATCH_FAIL" >&2; exit 1; fi ns=$(arg_after -n "$@") name=$(arg_after virtualmachines.kubevirt.io "$@") patch=$(arg_after -p "$@") # Refuse a stale resourceVersion the way the API server does, then apply # every add op and bump the resourceVersion. rv=$(jq -r --arg ns "$ns" --arg n "$name" \ '.items[] | select(.metadata.namespace == $ns and .metadata.name == $n) | .metadata.resourceVersion' \ "$FAKE_STATE/vms.json") want=$(printf '%s' "$patch" | jq -r '.[] | select(.op == "test" and .path == "/metadata/resourceVersion") | .value') if [ -z "$want" ] || [ "$want" != "$rv" ]; then printf 'Error from server (Conflict): test failed\n' >&2 exit 1 fi jq --arg ns "$ns" --arg n "$name" --argjson p "$patch" ' .items |= map( if .metadata.namespace == $ns and .metadata.name == $n then reduce ($p[] | select(.op == "add")) as $op (.; setpath($op.path | ltrimstr("/") | split("/"); $op.value)) | .metadata.resourceVersion = ((.metadata.resourceVersion | tonumber) + 1 | tostring) else . end)' "$FAKE_STATE/vms.json" > "$FAKE_STATE/vms.json.new" mv "$FAKE_STATE/vms.json.new" "$FAKE_STATE/vms.json" vols=$(jq -r --arg ns "$ns" --arg n "$name" \ '.items[] | select(.metadata.namespace == $ns and .metadata.name == $n) | [.spec.template.spec.volumes[].name] | join(",")' \ "$FAKE_STATE/vms.json") disks=$(jq -r --arg ns "$ns" --arg n "$name" \ '.items[] | select(.metadata.namespace == $ns and .metadata.name == $n) | [.spec.template.spec.domain.devices.disks[].name] | join(",")' \ "$FAKE_STATE/vms.json") log "PATCH-VM $ns/$name volumes=$vols disks=$disks" exit 0 ;; esac log "UNHANDLED $args" printf 'fake kubectl: unmodelled call: %s\n' "$args" >&2 exit 1