test/e2e/src/core/e2e_tests.sh
#!/bin/bash
set -x

results_dir="${RESULTS_DIR:-/tmp/results}"

waitForResourcesReady() {
    ready=false
    max_retries=60
    sleep_seconds=10
    NAMESPACE=$1
    RESOURCETYPE=$2
	 RESOURCE=$3
    # if resource not specified, set to --all
    if [ -z $RESOURCE ]; then
       RESOURCE="--all"
    fi
    for i in $(seq 1 $max_retries)
    do
    if [[ ! $(kubectl wait --for=condition=Ready ${RESOURCETYPE} ${RESOURCE} --namespace ${NAMESPACE}) ]]; then
        echo "waiting for the resource:${RESOURCE} of the type:${RESOURCETYPE} in namespace:${NAMESPACE} to be ready state, iteration:${i}"
        sleep ${sleep_seconds}
    else
        echo "resource:${RESOURCE} of the type:${RESOURCETYPE} in namespace:${NAMESPACE} in ready state"
        ready=true
        break
    fi
    done

    echo "waitForResourcesReady state: $ready"
}


waitForArcK8sClusterCreated() {
    connectivityState=false
    max_retries=60
    sleep_seconds=10
    for i in $(seq 1 $max_retries)
    do
      echo "iteration: ${i}, clustername: ${CLUSTER_NAME}, resourcegroup: ${RESOURCE_GROUP}"
      clusterState=$(az connectedk8s show --name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --query connectivityStatus -o json)
      clusterState=$(echo $clusterState | tr -d '"' | tr -d '"\r\n')
      echo "cluster current state: ${clusterState}"
      if [ ! -z "$clusterState" ]; then
         if [[ ("${clusterState}" == "Connected") || ("${clusterState}" == "Connecting") ]]; then
            connectivityState=true
            break
         fi
      fi
      sleep ${sleep_seconds}
    done
    echo "Arc K8s cluster connectivityState: $connectivityState"
}

waitForCIExtensionInstalled() {
    provisioningState=false
    max_retries=60
    sleep_seconds=10
    for i in $(seq 1 $max_retries)
    do
      echo "iteration: ${i}, clustername: ${CLUSTER_NAME}, resourcegroup: ${RESOURCE_GROUP}"
      provisioningState=$(az k8s-extension show  --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP  --cluster-type connectedClusters --name azuremonitor-containers --query provisioningState -o json)
      provisioningState=$(echo $provisioningState | tr -d '"' | tr -d '"\r\n')
      echo "extension install state: ${provisioningState}"
      if [ ! -z "$provisioningState" ]; then
         if [ "${provisioningState}" == "Succeeded" ]; then
            provisioningState=true
            break
         fi
      fi
      sleep ${sleep_seconds}
    done
    echo "container insights extension provisioningState: $provisioningState"
}

validateCommonParameters() {
   if [ -z $TENANT_ID ]; then
	   echo "ERROR: parameter TENANT_ID is required." > ${results_dir}/error
	   python3 setup_failure_handler.py
   fi

   ## Look for WORKLOAD_CLIENT_ID
   if [[ -z "${WORKLOAD_CLIENT_ID}" ]]
   then
      if [ -z $CLIENT_ID ]; then
         echo "ERROR: parameter CLIENT_ID is required." > ${results_dir}/error
         python3 setup_failure_handler.py
      fi

      if [ -z $CLIENT_SECRET ]; then
         echo "ERROR: parameter CLIENT_SECRET is required." > ${results_dir}/error
         python3 setup_failure_handler.py
      fi
   fi
}

validateArcConfTestParameters() {
	if [ -z $SUBSCRIPTION_ID ]; then
	   echo "ERROR: parameter SUBSCRIPTION_ID is required." > ${results_dir}/error
	   python3 setup_failure_handler.py
	fi

	if [ -z $RESOURCE_GROUP ]]; then
		echo "ERROR: parameter RESOURCE_GROUP is required." > ${results_dir}/error
		python3 setup_failure_handler.py
	fi

	if [ -z $CLUSTER_NAME ]; then
		echo "ERROR: parameter CLUSTER_NAME is required." > ${results_dir}/error
		python3 setup_failure_handler.py
	fi
}

addArcConnectedK8sExtension() {
   echo "adding Arc K8s connectedk8s extension"
   az extension add --name connectedk8s 2> ${results_dir}/error || python3 setup_failure_handler.py
}

addArcK8sCLIExtension() {
   if [ ! -z "$K8S_EXTENSION_WHL_URL" ]; then
      echo "adding Arc K8s k8s-extension cli extension from whl file path ${K8S_EXTENSION_WHL_URL}"
      az extension add --source $K8S_EXTENSION_WHL_URL -y
   else
      echo "adding Arc K8s k8s-extension cli extension"
      az extension add --name k8s-extension
   fi
}

createArcCIExtension() {
	echo "creating extension type: Microsoft.AzureMonitor.Containers"
    basicparameters="--cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP --cluster-type connectedClusters --extension-type Microsoft.AzureMonitor.Containers --scope cluster --name azuremonitor-containers --auto-upgrade-minor-version false"
    if [ ! -z "$CI_ARC_RELEASE_TRAIN" ]; then
       basicparameters="$basicparameters  --release-train $CI_ARC_RELEASE_TRAIN"
    fi
    if [ ! -z "$CI_ARC_VERSION" ]; then
       basicparameters="$basicparameters  --version $CI_ARC_VERSION"
    fi

   if [ ! -z "$USE_AAD_AUTH" ]; then
     az k8s-extension create $basicparameters --configuration-settings amalogs.ISTEST=true amalogs.useAADAuth=$USE_AAD_AUTH
   else
     az k8s-extension create $basicparameters --configuration-settings amalogs.ISTEST=true
   fi
}

showArcCIExtension() {
  echo "arc ci extension status"
  az k8s-extension show  --cluster-name $CLUSTER_NAME --resource-group $RESOURCE_GROUP  --cluster-type connectedClusters --name azuremonitor-containers
}

deleteArcCIExtension() {
    az k8s-extension delete --name azuremonitor-containers \
    --cluster-type connectedClusters \
	--cluster-name $CLUSTER_NAME \
	--resource-group $RESOURCE_GROUP --yes
}

login_to_azure() {
   ## Federted Identity credentials authentication mechanism added.
	if [[ -v SYSTEM_ACCESSTOKEN && -n "$SYSTEM_ACCESSTOKEN" &&
	      -v SERVICE_CONNECTION_ID && -n "$SERVICE_CONNECTION_ID" &&
	      -v SYSTEM_OIDCREQUESTURI && -n "$SYSTEM_OIDCREQUESTURI" ]]; then
	
	  export OIDC_REQUEST_URL="${SYSTEM_OIDCREQUESTURI}?api-version=7.1&serviceConnectionId=${SERVICE_CONNECTION_ID}"
	  echo "OIDC_REQUEST_URL= $OIDC_REQUEST_URL"
	
	  FED_TOKEN=$(curl -s -H "Content-Length: 0" -H "Content-Type: application/json" -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" -X POST $OIDC_REQUEST_URL | jq -r '.oidcToken')
	  echo "FED_TOKEN= $FED_TOKEN"
	
	  echo "logging in using Federated Identity"
	  az login --service-principal -u $FED_CLIENT_ID  --tenant $TENANT_ID --allow-no-subscriptions --federated-token $FED_TOKEN 2> >(tee "${results_dir}/error" >&2) || python3 setup_failure_handler.py
	
	elif [[ -v BASE_64_CLIENT_CERTIFICATE && -n "$BASE_64_CLIENT_CERTIFICATE" ]]; then
	  BASE_64_CLIENT_CERTIFICATE=${BASE_64_CLIENT_CERTIFICATE#\"}   # Remove leading quote
	  BASE_64_CLIENT_CERTIFICATE=${BASE_64_CLIENT_CERTIFICATE%\"} # Remove trailing quote
	  echo "logging in using Certificate '${BASE_64_CLIENT_CERTIFICATE}'"
	  ## create base64 cert to pem
	  echo ${BASE_64_CLIENT_CERTIFICATE:0} | tr ' ' "\n" > base64_cert
	  # convert base64 to PEM
	  openssl base64 -d -in base64_cert -out clientcert.pem
	  # minutes=60
	  # seconds=$((minutes * 60))
	  # sleep $seconds
	  az login --service-principal --use-cert-sn-issuer -u $CLIENT_ID -p clientcert.pem --tenant $TENANT_ID 2> >(tee "${results_dir}/error" >&2) || python3 setup_failure_handler.py
	  
	elif [[ -z $WORKLOAD_CLIENT_ID ]]; then
      echo "logging in using service principal '${CLIENT_ID}'"
      az login --service-principal \
         -u ${CLIENT_ID} \
         -p ${CLIENT_SECRET} \
         --tenant ${TENANT_ID} 2> ${results_dir}/error || python3 setup_failure_handler.py
   else
      echo "logging in using managed identity '${WORKLOAD_CLIENT_ID}'"
      az login --identity \
         -u ${WORKLOAD_CLIENT_ID} 2> ${results_dir}/error || python3 setup_failure_handler.py
   fi
	
   echo "setting subscription: ${SUBSCRIPTION_ID} as default subscription"
	##
	az account set \
	  --subscription ${SUBSCRIPTION_ID} 2> >(tee "${results_dir}/error" >&2) || python3 setup_failure_handler.py
}


# saveResults prepares the results for handoff to the Sonobuoy worker.
# See: https://github.com/vmware-tanzu/sonobuoy/blob/master/docs/plugins.md
saveResults() {
    cd ${results_dir}

    # Sonobuoy worker expects a tar file.
	tar czf results.tar.gz *

	# Signal to the worker that we are done and where to find the results.
	printf ${results_dir}/results.tar.gz > ${results_dir}/done
}

# Ensure that we tell the Sonobuoy worker we are done regardless of results.
trap saveResults EXIT

# validate common params
validateCommonParameters

IS_ARC_K8S_ENV="true"
if [ -z $IS_NON_ARC_K8S_TEST_ENVIRONMENT ]; then
   echo "arc k8s environment"
else
  if [ "$IS_NON_ARC_K8S_TEST_ENVIRONMENT" = "true" ]; then
    IS_ARC_K8S_ENV="false"
	echo "non arc k8s environment"
  fi
fi

if [ "$IS_ARC_K8S_ENV" = "false" ]; then
   echo "skipping installing of ARC K8s container insights extension since the test environment is non-arc K8s"
else
   # validate params
   validateArcConfTestParameters

   # login to azure
   login_to_azure

   # add arc k8s connectedk8s extension
   addArcConnectedK8sExtension

   # wait for arc k8s pods to be ready state
   waitForResourcesReady azure-arc pods

   # wait for Arc K8s cluster to be created
   waitForArcK8sClusterCreated

   # add CLI extension
   addArcK8sCLIExtension

   # add ARC K8s container insights extension
   createArcCIExtension

   # show the ci extension status
   showArcCIExtension

   #wait for extension state to be installed
   waitForCIExtensionInstalled
fi

# The variable 'TEST_LIST' should be provided if we want to run specific tests. If not provided, all tests are run

NUM_PROCESS=$(pytest /e2etests/ --collect-only  -k "$TEST_NAME_LIST" -m "$TEST_MARKER_LIST" | grep "<Function\|<Class" -c)

export NUM_TESTS="$NUM_PROCESS"

pytest /e2etests/ --junitxml=/tmp/results/results.xml -d --tx "$NUM_PROCESS"*popen -k "$TEST_NAME_LIST" -m "$TEST_MARKER_LIST"

# cleanup extension resource
deleteArcCIExtension
