#!/bin/bash
#
# THIS SCRIPT PROVIDES TARGETED GATHERING BASED ON NS, PLAN AND VM NAME
#
# NOTICE: THIS FILE IS NOT INCLUDED IN THE DEFAULT GATHER SCRIPT
#
# Can be executed by: oc adm must-gather --image quay.io/konveyor/forklift-must-gather:latest -- NS=foo PLAN=bar VM=baz MIGRATION_NS=openshift-migration /usr/bin/targeted
#

unset KUBECONFIG

object_collection_path="/must-gather"
mkdir -p ${object_collection_path}

#source pwait
#max_parallelism=10

# Set Forklift namespace
MIGRATION_NS=$1

# Resource list
dv_resources=()
plan_resources=()
vm_resources=()
present_vm_resources=()
target_ns=""
log_filter_query=""

# Parse provided parameters
if [ -z $NS ] && [ -z $PLAN ] && [ -z $VM ]; then
  echo "ERROR: Missing targeted gathering parameters. Use NS, PLAN and/or VM env variables."
  exit 1
fi

if [ ! -z $NS ]; then
  echo "Targeted gathering for Namespace: $NS"
  # Check if the NS exists (so it could used to get Plans/VMs later)
  if [ $(oc get namespace "$NS" 2>&1 | grep "not found" | wc -l) == "1" ]; then
    echo "ERROR: Specified NS doesn't exist, targeted gathering cannot continue. Set NS to an existing namespace."
    exit 1
  fi
  # Populate NS resources only if PLAN and VM parameters were not provided
  if [[ -z $PLAN && -z $VM ]]; then
    plans_data=$(/usr/bin/oc get plans -n $MIGRATION_NS -o json)
    plan_resources+=($(echo $plans_data | jq -r ".items[]|select(.spec.targetNamespace==\"$NS\")|.metadata.name"))
    vm_resources+=($(echo $plans_data | jq -r ".items[]|select(.spec.targetNamespace==\"$NS\")|.status.migration.vms[] .name"))
  fi
  target_ns=$NS
fi

if [ ! -z $PLAN ]; then
  echo "Targeted gathering for Plan: $PLAN"
  plan_data=$(/usr/bin/oc get plan $PLAN -n $MIGRATION_NS -o json)
  if [ ! -z "${plan_data}" ]; then
    plan_resources+=("$PLAN")
    vm_resources+=($(echo $plan_data | jq -r '.status.migration.vms[] .name'))
    target_ns=$(echo $plan_data | jq -r '.spec.targetNamespace')
  fi
fi

if [ ! -z $VM ]; then
  # VM ID (e.g. from migration plan) needs to be provided, since kubevirt VM name is not clearly translate-able to its migration id
  echo "Targeted gathering for VM: $VM"
  vm_resources+=("$VM")
  if [ -z "${target_ns}" ]; then
    # Try to identify a namespace for provided VM name
    vm_list=$(oc get virtualmachines -A | grep ${VM})
    if [ $(echo "$vm_list" | wc -l) == "1" ]; then
      target_ns=$(echo "$vm_list" | cut -f1 -d" ")
    else
      echo "ERROR: Mutiple VMs found for provided VM name. Use NS env variable together with VM env variable to specify the right one using its ID."
      echo "${vm_list}"
      exit 1
    fi
  fi
fi

# Start gathering of resources based on its type

function dump_resource {
  resource=$1
  ocobject=$2
  ocproject=$3
  echo "Dumping ${resource}: ${ocobject} from ${ocproject}"
  if [ -z "${ocproject}" ]|[ "${ocproject}" == "<none>" ]; then
    object_collection_path=/must-gather/cluster-scoped-resources/${resource}
    mkdir -p ${object_collection_path}
    /usr/bin/oc get ${resource} -o yaml ${ocobject} &> ${object_collection_path}/${ocobject}.yaml
  else
    object_collection_path=/must-gather/namespaces/${ocproject}/crs/${resource}
    mkdir -p ${object_collection_path}
    /usr/bin/oc get ${resource} -n ${ocproject} -o yaml ${ocobject} &> ${object_collection_path}/${ocobject}.yaml
  fi
}

if [ ! -z "${plan_resources}" ]; then
    echo "Gathering plans.."
    for plan_id in ${plan_resources[@]}; do
      log_filter_query="$log_filter_query|openshift-migration\/$plan_id"
      dump_resource "plan" $plan_id $MIGRATION_NS
    done
fi

if [ ! -z "${vm_resources}" ]; then
    echo "Gathering virtualmachines.."
    for target_vm_name in ${vm_resources[@]}; do
      # Check if the VM exists first
      if [ $(/usr/bin/oc get virtualmachine ${target_vm_name} -n ${target_ns} | grep ${target_vm_name} | wc -l) == "1" ]; then
        # Parse VM for related resources
        vm_data=$(/usr/bin/oc get virtualmachine ${target_vm_name} -n ${target_ns} -o json)

        # Gather VMs DataVolumes
        for dv_name in $(echo $vm_data | jq -r '.spec.template.spec.volumes[] .dataVolume.name'); do
          dump_resource "datavolume" $dv_name $target_ns

          # Store DV in list to allow importer pod logs gathering
          echo "${target_ns},${dv_name}" >> /tmp/dvs
        done

        target_vm_id=($(echo $vm_data | jq -r '.metadata.labels.vmID'))
        log_filter_query="$log_filter_query|$target_vm_name"
        dump_resource "virtualmachine" $target_vm_name $target_ns
        present_vm_resources+=("$target_vm_name")

        # Gather VM hook jobs if present
        for job_name in $(/usr/bin/oc get jobs --no-headers -n $MIGRATION_NS --selector vmID=$target_vm_id -o go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'); do
          dump_resource "job" $job_name $MIGRATION_NS
          job_pod_name=$(/usr/bin/oc get pods --no-headers -n $MIGRATION_NS --selector job-name=$job_name -o go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
          echo "${MIGRATION_NS},${job_pod_name}" >> /tmp/job_pods
        done

        # Store VM in list to allow virt-launcher pod logs gathering
        echo "${target_ns},${target_vm_name},${target_vm_id}" >> /tmp/target_vms
      else
        echo "VirtualMachine ${target_vm_name} doesn't exist in ${target_ns} namespace, skipping."
      fi
    done
fi

# Show message in case of empty result of requested/parsed resources
if [ -z $plan_resources ] && [ -z $vm_resources ] && [ -z $dv_resources ]; then
  echo "ERROR: No resources matching the criteria were found. Try adjust NS, PLAN or VM env variables."
  exit 1
fi

# Show message for zero valid VMs without Plan of resources actually existing in the cluster
if [ -z $plan_resources ] && [ -z $present_vm_resources ]; then
  echo "ERROR: No existing VMs were found in the cluster."
  exit 1
fi

# Store condition for logs filtering
echo "Condition for targeted logs filtering:"
echo "${log_filter_query:1}" | tee /tmp/targeted_logs_grep_query
