#!/bin/bash
BASE_COLLECTION_PATH="must-gather"
NETWORK_LOG_PATH=${OUT:-"${BASE_COLLECTION_PATH}/network_logs"}

mkdir -p "${NETWORK_LOG_PATH}"/

function gather_multus_data { 
  #Should we store this on a per namespace basis?
  oc get net-attach-def -o yaml --all-namespaces > "${NETWORK_LOG_PATH}"/net_attach_def 2>&1 & PIDS+=($!)

  oc describe ippools.whereabouts.cni.cncf.io -A > "${NETWORK_LOG_PATH}"/ippools 2>&1 & PIDS+=($!)

  oc describe overlappingrangeipreservations.whereabouts.cni.cncf.io -A > "${NETWORK_LOG_PATH}"/overlappingrangeipreservations  2>&1 & PIDS+=($!)

  oc get multi-networkpolicy -o yaml --all-namespaces > "${NETWORK_LOG_PATH}"/multi_networkpolicy 2>&1 & PIDS+=($!)
}

function gather_ovn_kubernetes_data {
  echo "INFO: Gathering ovn-kubernetes master data"
  OVNKUBE_MASTER_PODS=($(oc -n openshift-ovn-kubernetes get pods -l app=ovnkube-master -o=jsonpath='{.items[*].metadata.name}'))
  # collect only leader dbs to reduce result size
  for DB in "n" "s"; do
    if [ "$DB" = "n" ]; then
      DB_NAME="OVN_Northbound"
      CONTAINER="nbdb"
    else
      DB_NAME="OVN_Southbound"
      CONTAINER="sbdb"
    fi
    i=0
    PODS_AMOUNT=${#OVNKUBE_MASTER_PODS[@]}
    # try 2 cycles in case leader has changed during first pass
    while (( i < 2 * PODS_AMOUNT )) ; do
      OVNKUBE_MASTER_POD=${OVNKUBE_MASTER_PODS[$(( i % PODS_AMOUNT ))]}
      # find leader to copy db
      RAFT_ROLE=$(oc exec -n openshift-ovn-kubernetes "${OVNKUBE_MASTER_POD}" -c "${CONTAINER}" -- bash -c \
        "ovn-appctl -t /var/run/ovn/ovn${DB}b_db.ctl cluster/status ${DB_NAME} 2>&1 | grep \"^Role\"")
      if echo "${RAFT_ROLE}" | grep -q -i leader; then
        oc cp openshift-ovn-kubernetes/"${OVNKUBE_MASTER_POD}":/etc/ovn/ovn"${DB}"b_db.db -c "${CONTAINER}" \
         "${NETWORK_LOG_PATH}/leader_${DB}bdb" 2>&1
        gzip "${NETWORK_LOG_PATH}/leader_${DB}bdb" 2>&1 & PIDS+=($!)

        oc exec -n openshift-ovn-kubernetes "${OVNKUBE_MASTER_POD}" -c "${CONTAINER}" -- bash -c \
          "ovn-appctl -t /var/run/ovn/ovn${DB}b_db.ctl cluster/status ${DB_NAME}" > \
          "${NETWORK_LOG_PATH}/leader_ovn${DB}b_status" & PIDS+=($!)
        break
      fi
      ((i++))
    done
  done

  oc adm top pods -n openshift-ovn-kubernetes --containers > "${NETWORK_LOG_PATH}"/ovn_kubernetes_top_pods & PIDS+=($!)
}

function gather_kuryr_data {
  echo "INFO: Gathering kuryr data"
  CONTROLLER_POD=$(oc -n openshift-kuryr get pods --no-headers -o custom-columns=":metadata.name" -l app=kuryr-controller)
  oc -n openshift-kuryr exec "${CONTROLLER_POD}" -- bash -c \
  'kuryr-gather-openstack-data --config-dir /etc/kuryr' > "${NETWORK_LOG_PATH}"/get_openstack_data &
  PIDS+=($!)
  oc get pods -A -o wide --show-labels > "${NETWORK_LOG_PATH}"/get_pods & PIDS+=($!)
  oc get kuryrnetworks -A -o yaml > "${NETWORK_LOG_PATH}"/get_kuryrnetworks & PIDS+=($!)
  oc get kuryrnetworkpolicy -A -o yaml > "${NETWORK_LOG_PATH}"/get_kuryrnetworkpolicy & PIDS+=($!)
  oc get kuryrport -A -o yaml > "${NETWORK_LOG_PATH}"/get_kuryrport & PIDS+=($!)
  oc get kuryrloadbalancer -A -o yaml > "${NETWORK_LOG_PATH}"/get_kuryrloadbalancer & PIDS+=($!)
  oc get svc -A > "${NETWORK_LOG_PATH}"/get_svc & PIDS+=($!)
}

function gather_scale_data {
  touch "${NETWORK_LOG_PATH}"/cluster_scale
  echo services amount: $(oc get svc -A | wc -l) >> "${NETWORK_LOG_PATH}"/cluster_scale & PIDS+=($!)
  echo endpoints amount: $(oc get ep -A | wc -l) >> "${NETWORK_LOG_PATH}"/cluster_scale & PIDS+=($!)
  echo pods amount: $(oc get pods -A | wc -l) >> "${NETWORK_LOG_PATH}"/cluster_scale & PIDS+=($!)
}

PIDS=()
NETWORK_TYPE=$(oc get network.config.openshift.io -o=jsonpath='{.items[0].spec.networkType}' | tr '[:upper:]' '[:lower:]')

gather_multus_data
gather_scale_data

if [[ "${NETWORK_TYPE}" == "kuryr" ]]; then
    gather_kuryr_data
elif [[ "${NETWORK_TYPE}" == "ovnkubernetes" ]]; then
    gather_ovn_kubernetes_data
fi

echo "INFO: Waiting for network log collection to complete ..."
wait "${PIDS[@]}"
echo "INFO: Network log collection complete."

# force disk flush to ensure that all data gathered is accessible in the copy container
sync
