#!/usr/bin/env bash

# bash options
set -o errexit
set -o nounset
set -o pipefail
set -o xtrace

# check var
[[ -z "${WIKI_LINK}" ]] && (echo "WIKI_LINK is empty"; exit 1)
[[ -z "${TENANT_ID}" ]] && (echo "TENANT_ID is empty"; exit 1)
[[ -z "${AZCLI_ALT_SUBSCRIPTION_ID}" ]] && (echo "AZCLI_ALT_SUBSCRIPTION_ID is empty"; exit 1)
[[ -z "${AZCLI_ALT_CLIENT_ID}" ]] && (echo "AZCLI_ALT_CLIENT_ID is empty"; exit 1)
[[ -z "${AZCLI_ALT_CLIENT_SECRET}" ]] && (echo "AZCLI_ALT_CLIENT_SECRET is empty"; exit 1)
[[ -z "${IGNORE_EXIT_CODE}" ]] && (echo "IGNORE_EXIT_CODE is empty")
[[ -z "${TEST_MODE}" ]] && (echo "TEST_MODE is empty"; exit 1)
[[ -z "${PARALLELISM}" ]] && (echo "PARALLELISM is empty")
[[ -z "${RERUNS}" ]] && (echo "RERUNS is empty")
[[ -z "${NON_BOXED}" ]] && (echo "NON_BOXED is empty")
[[ -z "${LOG_LEVEL}" ]] && (echo "LOG_LEVEL is empty")
[[ -z "${CAPTURE}" ]] && (echo "CAPTURE is empty")
[[ -z "${NO_EXIT_FIRST}" ]] && (echo "NO_EXIT_FIRST is empty")
[[ -z "${LAST_FAILED}" ]] && (echo "LAST_FAILED is empty")
[[ -z "${EXT_TEST_MATRIX}" ]] && (echo "EXT_TEST_MATRIX is empty")
[[ -z "${EXT_TEST_FILTER}" ]] && (echo "EXT_TEST_FILTER is empty")
[[ -z "${EXT_TEST_COVERAGE}" ]] && (echo "EXT_TEST_COVERAGE is empty")
[[ -z "${BACKWARD_COMPATIBILITY_TEST}" ]] && (echo "BACKWARD_COMPATIBILITY_TEST is empty")
[[ -z "${CLI_TEST_MATRIX}" ]] && (echo "CLI_TEST_MATRIX is empty")
[[ -z "${CLI_TEST_FILTER}" ]] && (echo "CLI_TEST_FILTER is empty")
[[ -z "${CLI_TEST_COVERAGE}" ]] && (echo "CLI_TEST_COVERAGE is empty")
[[ -z "${ENABLE_SELECTION}" ]] && (echo "ENABLE_SELECTION is empty")
[[ -z "${SELECTION_MODE}" ]] && (echo "SELECTION_MODE is empty")
[[ -z "${SELECTION_COUNT}" ]] && (echo "SELECTION_COUNT is empty")
[[ -z "${UNFIX_RANDOM_SEED}" ]] && (echo "UNFIX_RANDOM_SEED is empty")

# activate virtualenv
source azEnv/bin/activate

# setup aks-preview
./scripts/setup_venv.sh setup-akspreview

# login before the recording test to avoid the newly added test case does not include a corresponding
# recording file and fall back to live mode, otherwise it will prompt `az login`.
az login --service-principal -u "${AZCLI_ALT_CLIENT_ID}" -p "${AZCLI_ALT_CLIENT_SECRET}" -t "${TENANT_ID}"
az account set -s "${AZCLI_ALT_SUBSCRIPTION_ID}"
az account show

if [[ -z ${BACKWARD_COMPATIBILITY_TEST} || ${BACKWARD_COMPATIBILITY_TEST} != "only" ]]; then
    # prepare running options
    # pytest options
    pytest_options="-e --report-path ./reports"
    # parallel
    if [[ -n ${PARALLELISM} ]]; then
        pytest_options+=" -j ${PARALLELISM}"
    else
        pytest_options+=" -s"
    fi
    # reruns
    if [[ -n ${RERUNS} ]]; then
        pytest_options+=" --reruns ${RERUNS}"
    fi
    # non boxed
    if [[ -n ${NON_BOXED} ]]; then
        pytest_options+=" --non-boxed"
    fi
    # log level
    if [[ -n ${LOG_LEVEL} ]]; then
        pytest_options+=" --log-level ${LOG_LEVEL}"
    fi
    # capture
    if [[ -n ${CAPTURE} ]]; then
        pytest_options+=" --capture ${CAPTURE}"
    fi
    # no exit first
    if [[ -n ${NO_EXIT_FIRST} ]]; then
        pytest_options+=" --no-exitfirst"
    fi
    # last failed
    if [[ -n ${LAST_FAILED} ]]; then
        pytest_options+=" --last-failed"
    fi

    # filter options
    filter_options=""
    # ext matrix
    if [[ -n ${EXT_TEST_MATRIX} ]]; then
        filter_options+=" -em ./configs/${EXT_TEST_MATRIX}"
    fi
    # ext extra filter
    if [[ -n ${EXT_TEST_FILTER} ]]; then
        filter_options+=" -ef ${EXT_TEST_FILTER}"
    fi
    # ext extra coverage
    if [[ -n ${EXT_TEST_COVERAGE} ]]; then
        filter_options+=" -ec ${EXT_TEST_COVERAGE}"
    fi

    # case selection
    selection_options=""
    # enable selection
    if [[ -n ${ENABLE_SELECTION} ]]; then
        selection_options+=" --enable-selection"
    fi
    # selection mode
    if [[ -n ${SELECTION_MODE} ]]; then
        selection_options+=" --selection-mode ${SELECTION_MODE}"
    fi
    # selection count
    if [[ -n ${SELECTION_COUNT} ]]; then
        selection_options+=" --selection-count ${SELECTION_COUNT}"
    fi
    # unfix random seed
    if [[ -n ${UNFIX_RANDOM_SEED} ]]; then
        selection_options+=" --unfix-random-seed"
    fi

    # recording test
    if [[ ${TEST_MODE} == "recording" || ${TEST_MODE} == "all" ]]; then
        echo "Test in recording mode!"
        coverage_options=" -ec test_aks_commands.AzureKubernetesServiceScenarioTest"
        recording_options="${pytest_options}${coverage_options}${selection_options}"
        recording_options+=" --json-report-file=ext_recording_report.json"
        recording_options+=" --xml-file=ext_recording_result.xml"
        echo "Recording test options: ${recording_options}"
        test_result=0
        azaks ${recording_options} || test_result=$?
        if [[ ${test_result} -ne 0 ]]; then
            echo "Recording test failed!"
            echo "Please refer to this wiki (${WIKI_LINK}) for troubleshooting guidelines."
            if [[ -z ${IGNORE_EXIT_CODE} ]]; then
                exit ${test_result}
            fi
        else
            echo -e "Recording test passed!\n\n"
        fi
    fi

    # live test
    if [[ ${TEST_MODE} == "live" || ${TEST_MODE} == "all" ]]; then
        echo "Test in live mode!"
        live_options="${pytest_options}${filter_options}${selection_options}"
        live_options+=" -l --json-report-file=ext_live_report.json"
        live_options+=" --xml-file=ext_live_result.xml"
        echo "Live test options: ${live_options}"
        test_result=0
        azaks ${live_options} || test_result=$?
        if [[ ${test_result} -ne 0 ]]; then
            echo "Live test failed!"
            echo "Please refer to this wiki (${WIKI_LINK}) for troubleshooting guidelines."
            if [[ -z ${IGNORE_EXIT_CODE} ]]; then
                exit ${test_result}
            fi
        else
            echo -e "Live test passed!\n\n"
        fi
    fi

    # live-replay test
    if [[ ${TEST_MODE} == "live" || ${TEST_MODE} == "all" ]]; then
        echo "Test in live-replay mode!"
        live_replay_options="${pytest_options}${filter_options}${selection_options}"
        live_replay_options+=" --json-report-file=ext_live_replay_report.json"
        live_replay_options+=" --xml-file=ext_live_replay_result.xml"
        echo "Live-replay test options: ${live_replay_options}"
        test_result=0
        azaks ${live_replay_options} || test_result=$?
        if [[ ${test_result} -ne 0 ]]; then
            echo "Live-replay test failed!"
            echo "Please refer to this wiki (${WIKI_LINK}) for troubleshooting guidelines."
            if [[ -z ${IGNORE_EXIT_CODE} ]]; then
                exit ${test_result}
            fi
        else
            echo -e "Live-replay test passed!\n\n"
        fi
    fi
fi

if [[ -n ${BACKWARD_COMPATIBILITY_TEST} ]]; then
    # prepare running options
    # pytest options
    pytest_options="-c --report-path ./reports"
    # parallel
    if [[ -n ${PARALLELISM} ]]; then
        pytest_options+=" -j ${PARALLELISM}"
    else
        pytest_options+=" -s"
    fi
    # reruns
    if [[ -n ${RERUNS} ]]; then
        pytest_options+=" --reruns ${RERUNS}"
    fi
    # non boxed
    if [[ -n ${NON_BOXED} ]]; then
        pytest_options+=" --non-boxed"
    fi
    # log level
    if [[ -n ${LOG_LEVEL} ]]; then
        pytest_options+=" --log-level ${LOG_LEVEL}"
    fi
    # capture
    if [[ -n ${CAPTURE} ]]; then
        pytest_options+=" --capture ${CAPTURE}"
    fi
    # no exit first
    if [[ -n ${NO_EXIT_FIRST} ]]; then
        pytest_options+=" --no-exitfirst"
    fi
    # last failed
    if [[ -n ${LAST_FAILED} ]]; then
        pytest_options+=" --last-failed"
    fi

    # filter options
    filter_options=""
    # cli matrix
    if [[ -n ${CLI_TEST_MATRIX} ]]; then
        filter_options+=" -cm ./configs/${CLI_TEST_MATRIX}"
    fi
    # cli extra filter
    if [[ -n ${CLI_TEST_FILTER} ]]; then
        filter_options+=" -cf ${CLI_TEST_FILTER}"
    fi
    # cli extra coverage
    if [[ -n ${CLI_TEST_COVERAGE} ]]; then
        filter_options+=" -cc ${CLI_TEST_COVERAGE}"
    fi

    # case selection
    selection_options=""
    # enable selection
    if [[ -n ${ENABLE_SELECTION} ]]; then
        selection_options+=" --enable-selection"
    fi
    # selection mode
    if [[ -n ${SELECTION_MODE} ]]; then
        selection_options+=" --selection-mode ${SELECTION_MODE}"
    fi
    # selection count
    if [[ -n ${SELECTION_COUNT} ]]; then
        selection_options+=" --selection-count ${SELECTION_COUNT}"
    fi
    # unfix random seed
    if [[ -n ${UNFIX_RANDOM_SEED} ]]; then
        selection_options+=" --unfix-random-seed"
    fi

    # live test
    if [[ ${TEST_MODE} == "live" || ${TEST_MODE} == "all" ]]; then
        echo "Backward Compatibility Test in live mode!"
        live_options="${pytest_options}${filter_options}${selection_options}"
        live_options+=" -l --json-report-file=bc_live_report.json"
        live_options+=" --xml-file=bc_live_result.xml"
        echo "Live test options: ${live_options}"
        test_result=0
        azaks ${live_options} || test_result=$?
        if [[ ${test_result} -ne 0 ]]; then
            echo "Backward Compatibility Live test failed!"
            echo "Please refer to this wiki (${WIKI_LINK}) for troubleshooting guidelines."
            if [[ -z ${IGNORE_EXIT_CODE} ]]; then
                exit ${test_result}
            fi
        else
            echo -e "Backward Compatibility Live test passed!\n\n"
        fi
    fi

    # live-replay test
    if [[ ${TEST_MODE} == "live" || ${TEST_MODE} == "all" ]]; then
        echo "Backward Compatibility Test in live-replay mode!"
        live_replay_options="${pytest_options}${filter_options}${selection_options}"
        live_replay_options+=" --json-report-file=bc_live_replay_report.json"
        live_replay_options+=" --xml-file=bc_live_replay_result.xml"
        echo "Live-replay test options: ${live_replay_options}"
        test_result=0
        azaks ${live_replay_options} || test_result=$?
        if [[ ${test_result} -ne 0 ]]; then
            echo "Backward Compatibility Live-replay test failed!"
            echo "Please refer to this wiki (${WIKI_LINK}) for troubleshooting guidelines."
            if [[ -z ${IGNORE_EXIT_CODE} ]]; then
                exit ${test_result}
            fi
        else
            echo -e "Backward Compatibility Live-replay test passed!\n\n"
        fi
    fi
fi


#!/usr/bin/env bash

# bash options
set -o errexit
set -o nounset
set -o pipefail
set -o xtrace

# check var
# take the first arg as test mode
mode=${1:-"cli"}
[[ -z "${WIKI_LINK}" ]] && (echo "WIKI_LINK is empty"; exit 1)
[[ -z "${ACS_BASE_DIR}" ]] && (echo "ACS_BASE_DIR is empty"; exit 1)
[[ -z "${AKS_PREVIEW_BASE_DIR}" ]] && (echo "AKS_PREVIEW_BASE_DIR is empty"; exit 1)
[[ -z "${IGNORE_EXIT_CODE}" ]] && (echo "IGNORE_EXIT_CODE is empty")
[[ -z "${CLI_COVERAGE_CONFIG}" ]] && (echo "CLI_COVERAGE_CONFIG is empty")
[[ -z "${EXT_COVERAGE_CONFIG}" ]] && (echo "EXT_COVERAGE_CONFIG is empty")

# activate virtualenv
source azEnv/bin/activate

# config aks-preview
source ./scripts/setup_venv.sh
removeAKSPreview
if [[ ${mode} == "ext" ]]; then
    setupAKSPreview
    igniteAKSPreview
fi

# check mode
if [[ ${mode} == "cli" ]]; then
    UT_BASE_DIR=${ACS_BASE_DIR}
elif [[ ${mode} == "ext" ]]; then
    UT_BASE_DIR=${AKS_PREVIEW_BASE_DIR}
else
    echo "Unsupported coverage mode, please choose \"cli\" or \"ext\""
    exit 1
fi

# unit test & coverage report
pushd ${UT_BASE_DIR}

# clean existing coverage report
(coverage combine || true) && (coverage erase || true)

# perform unit test with module 'unittest'
test_result=0
coverage run --source=. --omit=*/vendored_sdks/*,*/tests/* -m pytest tests/latest/ || test_result=$?

# generate coverage report
coverage combine || true
coverage report -m
coverage json -o coverage.json
popd

# copy coverage report
mkdir -p reports/ && cp ${UT_BASE_DIR}/coverage.json reports/

# prepare running options
# unit test result
options="--unit-test-result ${test_result} --coverage-report ${UT_BASE_DIR}/coverage.json"
# ignore exit code
if [[ -n ${IGNORE_EXIT_CODE} ]]; then
    options+=" --ignore-exit-code"
fi
if [[ ${mode} == "cli" && -n ${CLI_COVERAGE_CONFIG} ]]; then
    options+=" --coverage-config ./configs/${CLI_COVERAGE_CONFIG}"
fi
if [[ ${mode} == "ext" && -n ${EXT_COVERAGE_CONFIG} ]]; then
    options+=" --coverage-config ./configs/${EXT_COVERAGE_CONFIG}"
fi

combined_result=0
azaks-cov ${options} || combined_result=$?
echo "Please refer to this wiki (${WIKI_LINK}) for troubleshooting guidelines."
exit ${combined_result}


#!/usr/bin/env bash

# bash options
set -o errexit
set -o nounset
set -o pipefail
set -o xtrace

# check var
# azure devops
[[ -z "${BUILD_REASON}" ]] && (echo "BUILD_REASON is empty")
[[ -z "${SYSTEM_PULLREQUEST_TARGETBRANCH}" ]] && (echo "SYSTEM_PULLREQUEST_TARGETBRANCH is empty")

# client id, secret and tenant id of sp 'azcli-aks-live-test' (from variable group "azcli-aks-tool")
[[ -z "${AZCLI_ALT_CLIENT_ID}" ]] && (echo "AZCLI_ALT_CLIENT_ID is empty"; exit 1)
[[ -z "${AZCLI_ALT_SUBSCRIPTION_ID}" ]] && (echo "AZCLI_ALT_SUBSCRIPTION_ID is empty"; exit 1)
[[ -z "${TENANT_ID}" ]] && (echo "TENANT_ID is empty"; exit 1)

# basic ubuntu image with python3 pre-installed, hosted on some container registry (from variable group "azcli-aks-tool")
[[ -z "${IMAGE_PREFIX}" ]] && (echo "IMAGE_PREFIX is empty"; exit 1)
[[ -z "${IMAGE_NAME}" ]] && (echo "IMAGE_NAME is empty"; exit 1)
[[ -z "${IMAGE_TAG}" ]] && (echo "IMAGE_TAG is empty"; exit 1)

# specify the version of python3
[[ -z "${PYTHON_VERSION}" ]] && (echo "PYTHON_VERSION is empty"; exit 1)

# tsg/wiki link
[[ -z "${WIKI_LINK}" ]] && (echo "WIKI_LINK is empty"; exit 1)

# pytest options
[[ -z "${PARALLELISM}" ]] && (echo "PARALLELISM is empty")
[[ -z "${RERUNS}" ]] && (echo "RERUNS is empty")
[[ -z "${NON_BOXED}" ]] && (echo "NON_BOXED is empty")
[[ -z "${LOG_LEVEL}" ]] && (echo "LOG_LEVEL is empty")
[[ -z "${CAPTURE}" ]] && (echo "CAPTURE is empty")
[[ -z "${NO_EXIT_FIRST}" ]] && (echo "NO_EXIT_FIRST is empty")
[[ -z "${LAST_FAILED}" ]] && (echo "LAST_FAILED is empty")

# custom
[[ -z "${IGNORE_EXIT_CODE}" ]] && (echo "IGNORE_EXIT_CODE is empty")
[[ -z "${TEST_LOCATION}" ]] && (echo "TEST_LOCATION is empty"; exit 1)
[[ -z "${COVERAGE}" ]] && (echo "COVERAGE is empty"; exit 1)
[[ -z "${TEST_MODE}" ]] && (echo "TEST_MODE is empty"; exit 1)
[[ -z "${CLI_TEST_MATRIX}" ]] && (echo "CLI_TEST_MATRIX is empty")
[[ -z "${CLI_TEST_FILTER}" ]] && (echo "CLI_TEST_FILTER is empty")
[[ -z "${CLI_TEST_COVERAGE}" ]] && (echo "CLI_TEST_COVERAGE is empty")
[[ -z "${EXT_TEST_MATRIX}" ]] && (echo "EXT_TEST_MATRIX is empty")
[[ -z "${EXT_TEST_FILTER}" ]] && (echo "EXT_TEST_FILTER is empty")
[[ -z "${EXT_TEST_COVERAGE}" ]] && (echo "EXT_TEST_COVERAGE is empty")
[[ -z "${ENABLE_SELECTION}" ]] && (echo "ENABLE_SELECTION is empty")
[[ -z "${SELECTION_MODE}" ]] && (echo "SELECTION_MODE is empty")
[[ -z "${SELECTION_COUNT}" ]] && (echo "SELECTION_COUNT is empty")
[[ -z "${UNFIX_RANDOM_SEED}" ]] && (echo "UNFIX_RANDOM_SEED is empty")
[[ -z "${CLI_COVERAGE_CONFIG}" ]] && (echo "CLI_COVERAGE_CONFIG is empty")
[[ -z "${EXT_COVERAGE_CONFIG}" ]] && (echo "EXT_COVERAGE_CONFIG is empty")
[[ -z "${CLI_REPO}" ]] && (echo "CLI_REPO is empty"; exit 1)
[[ -z "${CLI_BRANCH}" ]] && (echo "CLI_BRANCH is empty"; exit 1)
[[ -z "${EXT_REPO}" ]] && (echo "EXT_REPO is empty"; exit 1)
[[ -z "${EXT_BRANCH}" ]] && (echo "EXT_BRANCH is empty"; exit 1)
[[ -z "${BACKWARD_COMPATIBILITY_TEST}" ]] && (echo "BACKWARD_COMPATIBILITY_TEST is empty")

# base directories for acs, aks-preview and live test
[[ -z "${ACS_BASE_DIR}" ]] && (echo "ACS_BASE_DIR is empty"; exit 1)
[[ -z "${AKS_PREVIEW_BASE_DIR}" ]] && (echo "AKS_PREVIEW_BASE_DIR is empty"; exit 1)
[[ -z "${LIVE_TEST_BASE_DIR}" ]] && (echo "LIVE_TEST_BASE_DIR is empty"; exit 1)

# clear
cat /dev/null > env.list

# azure devops
echo "BUILD_REASON=${BUILD_REASON}" >> env.list
echo "SYSTEM_PULLREQUEST_TARGETBRANCH=${SYSTEM_PULLREQUEST_TARGETBRANCH}" >> env.list

# tenant, sub, client
echo "TENANT_ID=${TENANT_ID}" >> env.list
echo "AZCLI_ALT_SUBSCRIPTION_ID=${AZCLI_ALT_SUBSCRIPTION_ID}" >> env.list
echo "AZCLI_ALT_CLIENT_ID=${AZCLI_ALT_CLIENT_ID}" >> env.list

# image
echo "IMAGE_PREFIX=${IMAGE_PREFIX}" >> env.list
echo "IMAGE_NAME=${IMAGE_NAME}" >> env.list
echo "IMAGE_TAG=${IMAGE_TAG}" >> env.list

# python version
echo "PYTHON_VERSION=${PYTHON_VERSION}" >> env.list

# tsg/wiki link
echo "WIKI_LINK=${WIKI_LINK}" >> env.list

# pytest options
echo "PARALLELISM=${PARALLELISM}" >> env.list
echo "RERUNS=${RERUNS}" >> env.list
echo "NON_BOXED=${NON_BOXED}" >> env.list
echo "LOG_LEVEL=${LOG_LEVEL}" >> env.list
echo "CAPTURE=${CAPTURE}" >> env.list
echo "NO_EXIT_FIRST=${NO_EXIT_FIRST}" >> env.list
echo "LAST_FAILED=${LAST_FAILED}" >> env.list

# custom - azdev env
echo "AZURE_CLI_TEST_DEV_SP_NAME=${AZCLI_ALT_CLIENT_ID}" >> env.list
echo "AZURE_CLI_TEST_DEV_RESOURCE_GROUP_LOCATION=${TEST_LOCATION}" >> env.list

# custom - az-aks-tool
echo "IGNORE_EXIT_CODE=${IGNORE_EXIT_CODE}" >> env.list
# live test
echo "COVERAGE=${COVERAGE}" >> env.list
echo "TEST_MODE=${TEST_MODE}" >> env.list
echo "CLI_TEST_MATRIX=${CLI_TEST_MATRIX}" >> env.list
echo "CLI_TEST_FILTER=${CLI_TEST_FILTER}" >> env.list
echo "CLI_TEST_COVERAGE=${CLI_TEST_COVERAGE}" >> env.list
echo "EXT_TEST_MATRIX=${EXT_TEST_MATRIX}" >> env.list
echo "EXT_TEST_FILTER=${EXT_TEST_FILTER}" >> env.list
echo "EXT_TEST_COVERAGE=${EXT_TEST_COVERAGE}" >> env.list
echo "ENABLE_SELECTION=${ENABLE_SELECTION}" >> env.list
echo "SELECTION_MODE=${SELECTION_MODE}" >> env.list
echo "SELECTION_COUNT=${SELECTION_COUNT}" >> env.list
echo "UNFIX_RANDOM_SEED=${UNFIX_RANDOM_SEED}" >> env.list
# unit test
echo "CLI_COVERAGE_CONFIG=${CLI_COVERAGE_CONFIG}" >> env.list
echo "EXT_COVERAGE_CONFIG=${EXT_COVERAGE_CONFIG}" >> env.list

# custom - repo
echo "CLI_REPO=${CLI_REPO}" >> env.list
echo "CLI_BRANCH=${CLI_BRANCH}" >> env.list
echo "EXT_REPO=${EXT_REPO}" >> env.list
echo "EXT_BRANCH=${EXT_BRANCH}" >> env.list

# custom - backward compatibility
echo "BACKWARD_COMPATIBILITY_TEST=${BACKWARD_COMPATIBILITY_TEST}" >> env.list

# base directories
echo "ACS_BASE_DIR=${ACS_BASE_DIR}" >> env.list
echo "AKS_PREVIEW_BASE_DIR=${AKS_PREVIEW_BASE_DIR}" >> env.list
echo "LIVE_TEST_BASE_DIR=${LIVE_TEST_BASE_DIR}" >> env.list


#! /bin/sh
if [ -z "$AzureWebJobsScriptRoot" ]; then
    cd /home/site/wwwroot
else
    cd "$AzureWebJobsScriptRoot"
fi

echo '{'
echo '"hostJson":'
if [ -f "host.json" ]; then
    cat host.json
else
    echo '{ }'
fi

echo ','

echo '"functionsJson": {'

for d in */; do
    d=$(echo $d | tr -d '/')
    if [ -f "${d}/function.json" ]; then
        echo "\"${d}\": "
        cat "${d}/function.json"
        echo ','
    fi
done
echo '}'
echo '}'


#!/bin/bash
setlog () {
	export logpath=/var/log/vmrepair
	export logfile=vmrepair.log
	mkdir -p ${logpath}
	echo "`date` Initiating vmrepair mount script" >> ${logpath}/${logfile}
}

trapper () {
	trap 'catch $? $LINENO' ERR
	catch () {
		echo "`date` Trapped error code $1 on line $2" >> ${logpath}/${logfile}
	}
}

duplication_validation () {
	trapper
	#/boot/efi duplication validation
	echo "`date` Validating boot/efi" >> ${logpath}/${logfile}
	efi_cnt=`lsblk | grep -i "/boot/efi" | wc -l`
	if [ "${efi_cnt}" -eq 2 ]
	then
		        umount /boot/efi >> ${logpath}/${logfile}
		fi
}

locatebekvol () {
	trapper
	echo "`date` Locating BEK volume" >> ${logpath}/${logfile}
	export bekdisk=`lsblk -l -o LABEL,NAME| grep BEK | awk '{print $NF}'`
	if [ -z ${bekdisk} ]
	then
		echo "`date` No BEK disk found, cannot continue" >> ${logpath}/${logfile}
		exit
	else
		echo "`date` the BEK Volume is ${bekdisk}" >> ${logpath}/${logfile}
		export bekdisk=/dev/${bekdisk}
	fi
}

mountbekvol () {
	trapper
	echo "`date` Mounting BEK volume" >> ${logpath}/${logfile}
	export bekmountpath=/mnt/azure_bek_disk/
	mkdir -p ${bekmountpath}
	mount ${bekdisk} ${bekmountpath}
	echo "`date` BEK Volume ${bekdisk} mounted on ${bekmountpath}"  >> ${logpath}/${logfile}
}

get_data_disk () {
	trapper
	echo "`date` Getting data disk" >> ${logpath}/${logfile} 2>&1
	export data_disk=`ls -la /dev/disk/azure/scsi1/lun0 | awk -F/ '{print "/dev/"$NF}'`
	if [ -z ${data_disk} ]
	then
		echo "`date` OS disk attached as data disk was not found, cannot continue" >> ${logpath}/${logfile}
		exit
	else
		echo "`date` The data disk is ${data_disk}" >> ${logpath}/${logfile}
	fi
}

create_mountpoints () {
	trapper
	echo "`date` Creating mountpoints" >> ${logpath}/${logfile}
	mkdir /{investigateboot,investigateroot}
}

rename_local_lvm () {
	trapper
	echo "`date` Renaming Local VG" >> ${logpath}/${logfile}
	vgrename -y ${local_vg_list} rescuevg
}

check_local_lvm () {
	trapper
echo "`date` Checking Local LVM" >> ${logpath}/${logfile}
export local_vg_list=`vgs --noheadings -o vg_name| tr -d '   '` >> ${logpath}/${logfile}
local_vg_number=`vgs --noheadings -o vg_name | wc -l` >> ${logpath}/${logfile}
if [ ${local_vg_number} -eq 1 ]
        then
                echo "`date` 1 VG found, renaming it" >> ${logpath}/${logfile}
                rename_local_lvm
        else
                echo "`date` VGs found different than 1, we found ${local_vg_number}" >> ${logpath}/${logfile}
fi
}

data_os_lvm_check () {
	trapper
	echo "`date` Looking for LVM on the data disk" >> ${logpath}/${logfile}
	export lvm_part=`fdisk -l ${data_disk} 2>&1 | grep -i lvm | awk '{print $1}'` >> ${logpath}/${logfile}
	echo ${lvm_part} >> ${logpath}/${logfile}
	if [ -z ${lvm_part} ]
	then
		#Updaing the below command to use lsblk instead of fdisk for accounting for different distros
		#export root_part=`fdisk -l ${data_disk} 2>&1 | grep ^/ |awk '$4 > 60000000{print $1}'` >> ${logpath}/${logfile}
		export root_part=`lsblk ${data_disk} -l -n -p -b 2>&1 | grep -w -v ${data_disk} |awk '$4 > 600000000{print $1}'` >> ${logpath}/${logfile}
		echo "`date` LVM not found on the data disk" >> ${logpath}/${logfile}
		echo "`date` The OS partition on the data drive is ${root_part}" >> ${logpath}/${logfile}
	else
		#adding a check to see if the returned value is just the partition number or partition full path.
		if grep -q ${data_disk} <<< ${lvm_part}
		then
			export root_part=${lvm_part} >> ${logpath}/${logfile}
		else
			export root_part=${data_disk}${lvm_part} >> ${logpath}/${logfile}
		fi
		echo "`date` LVM found on the data disk" >> ${logpath}/${logfile}
		echo "`date` The OS partition on the data drive is ${root_part}" >> ${logpath}/${logfile}
	fi
}

locate_mount_data_boot () {
	trapper
	echo "`date` Locating the partitions on the data drive" >> ${logpath}/${logfile}
	#export data_parts=`fdisk -l ${data_disk} 2>&1 | grep ^/  | awk '{print $1}'` >> ${logpath}/${logfile}
	#The below is updated to use lsblk, as fdisk output is diffferent between distros while the lsblk command is the same.
	export data_parts=`lsblk ${data_disk} -l -o name -n -p | grep -v -w ${data_disk}` >> ${logpath}/${logfile}
	echo "`date` Your data partitions are: ${data_parts}" >> ${logpath}/${logfile}

	#create mountpoints for all the data parts
	echo "`date` Creating mountpoints for all partitions on the data drive" >> ${logpath}/${logfile}
	for dpart in ${data_parts} ; do echo "`date` Creating mountpoint for ${dpart}" >> ${logpath}/${logfile} ; mkdir -p /tmp${dpart} >> ${logpath}/${logfile} ; done

	#mount all partitions
	echo "`date` Mounting all partitions on the data drive" >> ${logpath}/${logfile}
	for part in ${data_parts} ; do echo "`date` Mounting ${part} on /tmp/${part}" >> ${logpath}/${logfile} ; mount ${part} /tmp${part} >> ${logpath}/${logfile} 2>&1 ; done
	echo "`date`Locating luksheader" >> ${logpath}/${logfile}
	export luksheaderpath=`find /tmp -name osluksheader` >> ${logpath}/${logfile}
	echo "`date` The luksheader part is ${luksheaderpath}" >> ${logpath}/${logfile}
	export boot_part=`df -h $luksheaderpath | grep ^/ |awk '{print $1}'` >> ${logpath}/${logfile}
	echo "`date` The boot partition on the data disk is ${boot_part}" >> ${logpath}/${logfile}
}

mount_cmd () {
	trapper
	echo "`date` Determine mount command" >> ${logpath}/${logfile}
	mount_cmd=`mount -o nouuid 2> /dev/null` >> ${logpath}/${logfile} 2>&1
	if [ $? -gt 0 ]
	then
		        export mount_cmd="mount"
		else
			        export mount_cmd="mount -o nouuid"
			fi
}

mount_lvm () {
	trapper
	echo "`date` Mounting LVM structures found on ${root_part}" >> ${logpath}/${logfile}
	#adding below lines to make sure that volume groups are activated before trying to mount.
	vgs >>  ${logpath}/${logfile}
	vgchange -ay rootvg >> ${logpath}/${logfile}
	${mount_cmd} /dev/rootvg/rootlv /investigateroot >> ${logpath}/${logfile}
	${mount_cmd} /dev/rootvg/varlv /investigateroot/var/ >> ${logpath}/${logfile}
	${mount_cmd} /dev/rootvg/homelv /investigateroot/home >> ${logpath}/${logfile}
	${mount_cmd} /dev/rootvg/usrlv /investigateroot/usr >> ${logpath}/${logfile}
	${mount_cmd} /dev/rootvg/tmplv /investigateroot/tmp >> ${logpath}/${logfile}
	lsblk -f >> ${logpath}/${logfile}
}

unlock_root () {
	trapper
	echo "`date` unlocking root with command: cryptsetup luksOpen --key-file /mnt/azure_bek_disk/LinuxPassPhraseFileName --header /investigateboot/luks/osluksheader ${root_part} osencrypt" >> ${logpath}/${logfile}
	cryptsetup luksOpen --key-file /mnt/azure_bek_disk/LinuxPassPhraseFileName --header /investigateboot/luks/osluksheader ${root_part} osencrypt >> ${logpath}/${logfile}
}

verify_root_unlock () {
	trapper
	echo "`date` Verifying osencrypt unlock" >> ${logpath}/${logfile}
	lsblk -f  | grep osencrypt >> ${logpath}/${logfile}
	if [ $? -gt 0 ]
	then
		        echo "`date` device osencrypt was not found" >> ${logpath}/${logfile}
			        exit
			else
				        echo "`date` device osencrypt found" >> ${logpath}/${logfile}
				fi
}

mount_encrypted () {
	trapper
	echo "`date` Mounting root" >> ${logpath}/${logfile}
	if [ -z ${lvm_part} ]
	then
		echo "`date` Mounting /dev/mapper/osencrypt on /investigateroot" >> ${logpath}/${logfile}
		${mount_cmd} /dev/mapper/osencrypt /investigateroot >> ${logpath}/${logfile}
	else
		        sleep 5
			        mount_lvm
			fi
}

mount_boot () {
	trapper
	echo "`date` Unmounting the boot partition ${boot_part} on the data drive from the temp mount" >> ${logpath}/${logfile}
	umount -l ${boot_part} >> ${logpath}/${logfile}
	echo "`date` Mounting the boot partition ${boot_part} on /investigateboot" >> ${logpath}/${logfile}
	${mount_cmd} ${boot_part} /investigateboot/ >> ${logpath}/${logfile}
}

remount_boot () {
	trapper
	echo "`date` Unmounting the boot partition ${boot_part} on the data drive from the temp mount" >> ${logpath}/${logfile}
	umount -l ${boot_part} >> ${logpath}/${logfile}
	echo "`date` Mounting the boot partition ${boot_part} on /investigateroot/boot" >> ${logpath}/${logfile}
	${mount_cmd} ${boot_part} /investigateroot/boot >> ${logpath}/${logfile}
}
install_required_packages()
{
	echo "`date` Checking about the required packages and instal the misssing ones" >> ${logpath}/${logfile}
	echo "`date` Checking the distro of the recovery VM .." >> ${logpath}/${logfile}
	output=`which apt`
	if [ $? -eq 0 ]
	then
		echo "`date` This is ubuntu VM" >> ${logpath}/${logfile}
		apt-get install -y cryptsetup lvm2 >> ${logpath}/${logfile}
	else
		output=`which zypper`
		if [ $? -eq 0 ]
		then
			echo "`date` This is a sles VM" >> ${logpath}/${logfile}
			zypper --non-interactive --no-refresh install cryptsetup lvm2
		else
			echo "`date` This a yum based distro"  >> ${logpath}/${logfile}
			yum install -y cryptsetup lvm2
		fi
	fi
}

setlog
install_required_packages
duplication_validation
create_mountpoints
locatebekvol
mountbekvol
get_data_disk
check_local_lvm
data_os_lvm_check
mount_cmd
locate_mount_data_boot
mount_boot
unlock_root
verify_root_unlock
mount_encrypted
remount_boot


# Work around for Run-Command Shell Script behavior. Have to use 'ls' call to check if we pulled GitHub already.
if [ $(ls | wc -l) -eq 3 ]; then
	# Try, && added to each line to stop on fail and continue to catch block
	{
		curDate=$(date +%Y%m%d%H%M%S) &&
		dirname="repair-files-$curDate" &&
		mkdir $dirname &&
		cd $dirname &&
		logFileName="logs-$curDate.txt" &&
		logFile="$(pwd)/$line$logFileName" &&
		# Log Start
		echo "[Log-Start  $(date "+%m/%d/%Y %T")]" >> $logFile &&
		curl -s -S -L -o repair-script-library.tar.gz https://github.com/Azure/repair-script-library/tarball/master/ &&
		mkdir repair-script-library &&
		tar -xf repair-script-library.tar.gz -C repair-script-library &&
		cd repair-script-library &&
		reponame=$(ls) &&
		cd $reponame &&
		# Normal GitHub script scenario
		if [ "$1" != "no-op" ]; then
			chmod u+x $1 &&
			command_string="$*" &&
			bash -e  $command_string >> $logFile
		else # Custom script scenario
			# Call the same script but it will only run the appended custom scripts
			bash -e $0 >> $logFile
		fi &&

		# Add status string to log file
		echo "status string: $?" &&
		if [ $? -eq 0 ]; then
			echo "[STATUS]::SUCCESS" >> $logFile
		else
			echo "[STATUS]::ERROR" >> $logFile
		fi
	} || { # Catch
		errorMessage=$(cat /dev/stderr)
		echo "[Error $(date "+%m/%d/%Y %T")]$errorMessage" >> $logFile
	}
	# Finally
	echo "[Log-End $(date "+%m/%d/%Y %T")]$logFile" >> $logFile
	echo $(cat $logFile)
	# Exit and don't run appended scripts from run-command
	exit
fi


azp="/home/pi/bin"       #Path to Azure CLI binaries. Change if you didn't install at the default location
echo -n "Please type the Shared Key:"
read sharedKey

echo $sharedKey

#Retrieve local network information
activeInterface=$(ip route get 8.8.8.8 | awk '{print $5; exit}')
activeSubnet=$(ip route | grep $activeInterface | grep kernel | awk '{print $1; exit}')
leftip=$(ip route | grep $activeInterface | grep kernel | awk '{print $9; exit}')
localGatewayIpAddress=$(curl ifconfig.me) # enternal network address if behind a NAT

resGroup="GWS2SRasp"        # Resource group name
location='Central US'   # AZR Region to deploy the gateway
vpnType='RouteBased'
localGatewayName='home'
localAddressPrefix=$activeSubnet
virtualNetworkName='azureVNet'
azureVNetAddressPrefix="10.3.0.0/16"
subnetName='Subnet1'
subnetPrefix='10.3.0.0/24'
gatewaySubnetPrefix="10.3.254.0/29"
gatewayName="azrGateway"
gatewaySku="Basic"
connectName="AzureToHome"
vmName="pingTest"
vmSize="Standard_A1"
adminUserName="ubuntu"

# Hack to randomize the storage account name
storageAccountName=$(cat /proc/sys/kernel/random/uuid | md5sum)
storageAccountName="${storageAccountName:1:23}"

storageAccountType="Standard_LRS"

#Parameters to deploy the Azure site to site ARM template
params="{\"vpnType\":{\"value\":\"$vpnType\"},\"localGatewayName\":{\"value\":\"$localGatewayName\"},\"adminUsername\":{\"value\":\"$adminUserName\"},\"localGatewayIpAddress\":{\"value\":\"$localGatewayIpAddress\"},\"localAddressPrefix\":{\"value\":\"$localAddressPrefix\"},\"azureVNetAddressPrefix\":{\"value\":\"$azureVNetAddressPrefix\"},\"subnetPrefix\":{\"value\":\"$subnetPrefix\"},\"gatewaySubnetPrefix\":{\"value\":\"$gatewaySubnetPrefix\"},\"newStorageAccountName\":{\"value\":\"$storageAccountName\"},\"sharedKey\":{\"value\":\"$sharedKey\"}}"

echo "Please follow the instructions to login"
echo "If the script is run over a SSH connection, you can open the browser locally"
$azp/az login

$azp/az group create --name "$resGroup" --location "$location"
res=$?

$azp/az group deployment create \
    --name ExampleDeployment \
    --resource-group "$resGroup" \
    --template-uri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-site-to-site-vpn/azuredeploy.json" \
    --parameters $params
res=$(( $res + $? ))

#Get the IP Address from the create AZR VPN Gateway
# jq is used to parse the json results
id=$($azp/az network  vnet-gateway list --resource-group $resGroup | jq -r '.[].ipConfigurations[].publicIpAddress.id')
res=$(( $res + $? ))
ip=$($azp/az network public-ip list --resource-group $resGroup | jq -r '.[] | select(.id=="'$id'") | .ipAddress')
res=$(( $res + $? ))
rightSubnet=$($azp/az network vnet list --resource-group $resGroup | jq -r ".[].addressSpace.addressPrefixes[0]")
res=$(( $res + $? ))

if [ $res -ne 0 ]
then
    echo "Something went wrong... exiting"
    exit $res
else
    echo "Everything went well... Configuring strongSwan"
fi

secret="'$sharedKey'"
echo $ip

swann="conn home-to-azure
        closeaction=restart
        dpdaction=restart
        ike=aes256-sha1-modp1024
        esp=aes256-sha1
        reauth=no
        keyexchange=ike
        mobike=no
        ikelifetime=28800s
        keylife=3600s
        keyingtries=%forever
        authby=secret
        left=$leftip            # local instance ip (strongswan)
        leftsubnet=$activeSubnet
        leftid=$leftip         # local instance ip (strongswan)
        right=$ip
        rightid=$ip      # vpn gateway ip (azure)
        rightsubnet=$rightSubnet      # private ip segment (azure)
        auto=route"

sudo -s -- <<EOF
	echo "$swann" >> /etc/ipsec.conf
EOF

#ip secrets
ipscr="$leftip $ip : PSK $secret"
sudo -s -- <<EOF
	echo "$ipscr" >> /etc/ipsec.secrets
EOF

echo Restarting IPSec...
sudo ipsec restart


#/bin/bash

echo "installing prerequisites..."
echo "...prerequisites to azure cli"
sudo apt-get update
sudo apt-get install -y libssl-dev libffi-dev python-dev build-essential

echo "...jq"
sudo apt-get install jq

echo "...strongswann"
sudo apt-get install strongswan

echo "... Azure command line"
curl -L https://aka.ms/InstallAzureCli | bash


#!/usr/bin/env bash

# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

set -e

# PyLint does not yet support Python 3.6 https://github.com/PyCQA/pylint/issues/1241
if [ "$TRAVIS_PYTHON_VERSION" != "3.6" ]; then
    python -m unittest discover -s test
    python -m linter.run "$@"

else
    python -m unittest discover -s test -p 'test_*.py'
fi

python license-check/verify.py


function replace-tokens () {
    envsubst < /cnab/app/values.yaml.template > /cnab/app/values.yaml
    cat /cnab/app/values.yaml && echo \n\n
}

"$@"


function create-aks {
    if [[ -z $(az aks show --name $1 --resource-group $2 2> /dev/null) ]]
    then
        az aks create \
        --name $1 \
        --resource-group $2 \
        --kubernetes-version $3 \
        --node-vm-size $4 \
        --node-count $5 \
        --service-principal $6 \
        --client-secret $7 \
        --location $8 \
        --vm-set-type $9 \
        --generate-ssh-keys
    else
        echo "AKS cluster already exists in specified resource group with specified name"
    fi
}

function delete-aks {
    az aks delete --name $1 --resource-group $2 --yes
}

"$@"


function create-AAD-app-registration {
    az ad app create --display-name "$1" --identifier-uris "http://$1" --password "$2" --reply-url "https://$3/oauth2/callback"
    AAD_CLIENT_ID=$(az ad app list --display-name $1 --query "[0].appId" -o tsv)
    az ad app permission add --id $AAD_CLIENT_ID --api 00000002-0000-0000-c000-000000000000 --api-permissions 311a71cc-e848-46a1-bdf8-97ff7156d8e6=Scope
}

function replace-tokens {
    export AAD_CLIENT_ID=$(az ad app list --display-name $1 --query "[0].appId" -o tsv)
    export COOKIE_SECRET=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo;)
    envsubst < oauth2-proxy-azure.yaml > manifest.yaml
    cat manifest.yaml && echo \n\n
}

function create-namespace {
    manifest="{\"apiVersion\": \"v1\", \"kind\": \"Namespace\", \"metadata\": { \"name\": \"$1\" }}"
    echo $manifest | kubectl apply -f -
}

function create-oauth2-secret {
    kubectl create secret generic oauth2-secrets --namespace $1 --from-literal=clientSecret=$2
}

function delete-namespace {
    kubectl delete namespace $1
}

"$@"


#!/bin/bash

function configure-dns-name {
    NAMESPACE=$1
    INSTALLATION_NAME=$2
    DNS_NAME=$3

    RETRIES=0
    while [ -z $IP ]; do
        if [[ $RETRIES -gt 100 ]]; then
            echo "Exceeded number of retries for getting external IP address."
            exit 1
        fi

        IP=$(kubectl get service -l app=nginx-ingress,release=$INSTALLATION_NAME --namespace $NAMESPACE -o=jsonpath='{.items[0].status.loadBalancer.ingress[*].ip}')

        if [[ -z $IP ]]; then
            echo "External IP address not ready yet. Trying again in 5 seconds."
            sleep 5
            RETRIES=$((RETRIES + 1))
        else
            echo "Found external IP address."
        fi
    done

    DNSNAME=$DNS_NAME
    PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv)
    az network public-ip update --ids $PUBLICIPID --dns-name $DNSNAME
    FQDN=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[dnsSettings.fqdn]" --output tsv)
    echo $FQDN > FQDN
}

function add-jetstack-helm-repo {
    helm repo add jetstack https://charts.jetstack.io
}

function run-cert-manage-pre-reqs {
    kubectl apply -f https://raw.githubusercontent.com/jetstack/cert-manager/release-0.8/deploy/manifests/00-crds.yaml
    kubectl create namespace $1
    kubectl label namespace $1 certmanager.k8s.io/disable-validation=true
}

function replace-tokens {
    envsubst < /cnab/app/cluster-issuer-$1.yaml > /cnab/app/cluster-issuer.yaml
}

function delete-certmanager-namespace {
    kubectl delete namespace $1
}

"$@"


#!/bin/bash

function generate-keyfile-from-cred() {
    # to avoid accidents when testing this script locally, don't clobber an existing key file
    if [[ -f '/root/.ssh/id_rsa' ]]; then
        echo "Keyfile already exists - skipping"
    else
        mkdir /root/.ssh
        echo $SSH_PRIVATE_KEY_BASE64 | base64 --decode - >/root/.ssh/id_rsa
        chmod 600 /root/.ssh/id_rsa
    fi
}
function run-ansible() {
    ANSIBLE_CMD="ansible-playbook -i ./ansible/environments/$ENVIRONMENT $2 ansible/$1"
    echo "ansible cmd: $ANSIBLE_CMD"
    $ANSIBLE_CMD
}

function install() {
    generate-keyfile-from-cred
    run-ansible "install.yml" "-e admin_public_key_base64=$ADMIN_PUBLIC_KEY_BASE64"
}
function uninstall() {
    run-ansible "uninstall.yml"
}
function upgrade() {
    generate-keyfile-from-cred
    run-ansible "install.yml" "-e skip_provision=true"
}

ACTION=$1
ENVIRONMENT=$2
# The public key will contain a space to base64 encode it to make life easier passing it around
ADMIN_PUBLIC_KEY_BASE64=$(echo $3 | base64 --wrap=0)

"$@"


function create-kubernetes-namespace() {
    manifest="{\"apiVersion\": \"v1\", \"kind\": \"Namespace\", \"metadata\": { \"name\": \"$1\" }}"
    echo $manifest | kubectl apply -f -
}

function delete-kubernetes-namespace() {
    kubectl delete namespace $1
}

"$@"


function replace-tokens {
    envsubst < /cnab/app/values.yaml.template > /cnab/app/values.yaml
    cat /cnab/app/values.yaml && echo \n\n
}

"$@"


#!/usr/bin/env bash

install-kubeflow() {
    export KF_NAME=$1
    export BASE_DIR=/kubeflow
    export KF_DIR=${BASE_DIR}/${KF_NAME}
    export CONFIG_URI=$2
    mkdir -p ${KF_DIR}
    cd ${KF_DIR}
    kfctl apply -V -f ${CONFIG_URI}
}

uninstall-kubeflow() {
    export KF_NAME=$1
    export BASE_DIR=/kubeflow
    export KF_DIR=${BASE_DIR}/${KF_NAME}
    export CONFIG_URI=$2
    mkdir -p ${KF_DIR}
    cd ${KF_DIR}
    kfctl delete -f ${CONFIG_URI}
}

# Call the requested function and pass the arguments as-is
"$@"


#!/bin/bash

function configure-dns-name {
    NAMESPACE=$1
    INSTALLATION_NAME=$2
    DNS_NAME=$3

    RETRIES=0
    while [ -z $IP ]; do
        if [[ $RETRIES -gt 100 ]]; then
            echo "Exceeded number of retries for getting external IP address."
            exit 1
        fi

        IP=$(kubectl get service -l app.kubernetes.io/component=controller,app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/instance=$INSTALLATION_NAME --namespace $NAMESPACE -o=jsonpath='{.items[0].status.loadBalancer.ingress[*].ip}')

        if [[ -z $IP ]]; then
            echo "External IP address not ready yet. Trying again in 5 seconds."
            sleep 5
            RETRIES=$((RETRIES + 1))
        else
            echo "Found external IP address."
        fi
    done

    DNSNAME=$DNS_NAME
    PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv)
    az network public-ip update --ids $PUBLICIPID --dns-name $DNSNAME
    FQDN=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[dnsSettings.fqdn]" --output tsv)
    echo $FQDN > FQDN
}

function add-helm-repos {
    helm repo add jetstack https://charts.jetstack.io
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo add stable https://kubernetes-charts.storage.googleapis.com/
    helm repo update
}

function create-cert-manager-namespace {
    kubectl create namespace $1
    kubectl label namespace $1 certmanager.k8s.io/disable-validation=true
}

function replace-tokens {
    envsubst < /cnab/app/cluster-issuer-$1.yaml > /cnab/app/cluster-issuer.yaml
    cat /cnab/app/cluster-issuer.yaml
}

function delete-certmanager-namespace {
    kubectl delete namespace $1
}

"$@"


function replace-tokens {
    export INGRESS_HOST=$2
    export CERT_MANAGER_ISSUER=$3

    if [[ $MATTERMOST_LICENSE == '' ]]
    then
        export MATTERMOST_LICENSE='nolicense' # Set to a value, otherwise the Helm template isn't happy
    fi

    envsubst < /cnab/app/mattermost-$1-values.yaml > /cnab/app/mattermost-values.yaml
    cat /cnab/app/mattermost-values.yaml
}

"$@"


#!/bin/bash

master_host=$1
master_port=$2
master_username=$3
workers_host=$4
workers_port=$5
workers_username=$6

function disableContainerFeatures {
    username=$1
    port=$2
    host=$3

    # Enable container features and reboot
    ssh -o StrictHostKeyChecking=no -o ProxyCommand="ssh -o StrictHostKeyChecking=no -W %h:%p $master_username@$master_host -p $master_port" $username@$host -p $port /bin/bash << EOF
sudo sed -i 's/ cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory//g' /boot/cmdline.txt
EOF
}

# Update master node

disableContainerFeatures $master_username $master_port $master_host

# Update worker nodes

IFS=',' read -r -a hosts <<< "$workers_host"
IFS=',' read -r -a ports <<< "$workers_port"
IFS=',' read -r -a usernames <<< "$workers_username"

for index in "${!hosts[@]}"
do
    disableContainerFeatures ${usernames[index]} ${ports[index]} ${hosts[index]}
done


#!/bin/bash

master_host=$1
master_port=$2
master_username=$3
workers_host=$4
workers_port=$5
workers_username=$6

function enableContainerFeatures {
    username=$1
    port=$2
    host=$3

    # Enable container features and reboot
    ssh -o StrictHostKeyChecking=no -o ProxyCommand="ssh -o StrictHostKeyChecking=no -W %h:%p $master_username@$master_host -p $master_port" $username@$host -p $port /bin/bash << EOF
sudo sed -i '$ s/$/ cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory/' /boot/cmdline.txt
sudo reboot
EOF
}

function waitForSsh {
    username=$1
    port=$2
    host=$3

    ssh -o StrictHostKeyChecking=no -o ProxyCommand="ssh -o StrictHostKeyChecking=no -W %h:%p $master_username@$master_host -p $master_port" $username@$host -p $port echo
    while test $? -gt 0
    do
        echo "Waiting for reboot on $host:$port..."
        sleep 5
        ssh -o StrictHostKeyChecking=no -o ProxyCommand="ssh -o StrictHostKeyChecking=no -W %h:%p $master_username@$master_host -p $master_port" $username@$host -p $port echo
    done

    echo "Node at $host started"
}

# Update master node

enableContainerFeatures $master_username $master_port $master_host

# Update worker nodes

IFS=',' read -r -a hosts <<< "$workers_host"
IFS=',' read -r -a ports <<< "$workers_port"
IFS=',' read -r -a usernames <<< "$workers_username"

for index in "${!hosts[@]}"
do
    enableContainerFeatures ${usernames[index]} ${ports[index]} ${hosts[index]}
done

# Wait for nodes to start up again

waitForSsh $master_username $master_port $master_host

for index in "${!hosts[@]}"
do
    waitForSsh ${usernames[index]} ${ports[index]} ${hosts[index]}
done


#!/bin/bash

master_host=$1
master_port=$2
master_username=$3
master_kubernetes_host=$4
master_kubernetes_port=$5

ssh -o StrictHostKeyChecking=no $master_username@$master_host -p $master_port /bin/bash << EOF
sudo cp /etc/rancher/k3s/k3s.yaml /tmp/config
sudo chmod 777 /tmp/config
EOF

mkdir ~/.kube
scp -P $master_port $master_username@$master_host:/tmp/config ~/.kube

ssh -o StrictHostKeyChecking=no $master_username@$master_host -p $master_port /bin/bash << EOF
sudo rm /tmp/config
EOF

kubectl config set-cluster default --server=https://$master_kubernetes_host:$master_kubernetes_port
kubectl config use-context default
kubectl config view


#!/bin/bash

master_internal_IP=$1
master_host=$2
master_port=$3
master_username=$4
workers_host=$5
workers_port=$6
workers_username=$7

# Install master

ssh -o StrictHostKeyChecking=no $master_username@$master_host -p $master_port /bin/bash << EOF
curl -sfL https://get.k3s.io | sh -

systemctl is-active --quiet k3s
while test $? -gt 0
do
    echo "Waiting for k3s service to start..."
    sleep 5
    systemctl is-active --quiet k3s
done
echo "k3s service is active"
EOF

token=$(ssh -o StrictHostKeyChecking=no $master_username@$master_host -p $master_port /bin/bash << EOF
sudo cat /var/lib/rancher/k3s/server/node-token
EOF
)

echo "Join token is: $token"

# Install workers

IFS=',' read -r -a hosts <<< "$workers_host"
IFS=',' read -r -a ports <<< "$workers_port"
IFS=',' read -r -a usernames <<< "$workers_username"

for index in "${!hosts[@]}"
do
    username=${usernames[index]}
    port=${ports[index]}
    host=${hosts[index]}

    echo "Installing worker node at $username@$host:$port"

    ssh -o StrictHostKeyChecking=no -o ProxyCommand="ssh -o StrictHostKeyChecking=no -W %h:%p $master_username@$master_host -p $master_port" $username@$host -p $port /bin/bash << EOF
export K3S_URL="https://${master_internal_IP}:6443"
export K3S_TOKEN="${token}"
curl -sfL https://get.k3s.io | sh -
EOF
done


kubectl create serviceaccount tiller --namespace kube-system --dry-run=true -o yaml | kubectl apply -f -
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller --dry-run=true -o yaml | kubectl apply -f -
helm init --tiller-image=jessestuart/tiller --service-account tiller --upgrade


#!/bin/bash

master_host=$1
master_port=$2
master_username=$3
workers_host=$4
workers_port=$5
workers_username=$6

# Uninstall master

ssh -o StrictHostKeyChecking=no $master_username@$master_host -p $master_port /bin/bash << EOF
/usr/local/bin/k3s-killall.sh
/usr/local/bin/k3s-uninstall.sh
EOF

# Uninstall workers

IFS=',' read -r -a hosts <<< "$workers_host"
IFS=',' read -r -a ports <<< "$workers_port"
IFS=',' read -r -a usernames <<< "$workers_username"

for index in "${!hosts[@]}"
do
    username=${usernames[index]}
    port=${ports[index]}
    host=${hosts[index]}

    echo "Uninstalling worker node at $username@$host:$port"

    ssh -o StrictHostKeyChecking=no -o ProxyCommand="ssh -o StrictHostKeyChecking=no -W %h:%p $master_username@$master_host -p $master_port" $username@$host -p $port /bin/bash << EOF
/usr/local/bin/k3s-killall.sh
/usr/local/bin/k3s-agent-uninstall.sh
EOF
done


function create-aks {
    if [[ -z $(az aks show --name $1 --resource-group $2 2> /dev/null) ]]
    then
        az aks create \
        --name $1 \
        --resource-group $2 \
        --kubernetes-version $3 \
        --node-count $4 \
        --service-principal $5 \
        --client-secret $6 \
        --location $7 \
        --generate-ssh-keys
    else
        echo "AKS cluster already exists in specified resource group with specified name"
    fi
}

function wait-for-sql-custom-resource {
    crd=''
    while [[ -z $crd ]]
        do crd=$(kubectl get crd --field-selector=metadata.name=sqlservers.mssql.microsoft.com --ignore-not-found=true)
        echo 'Waiting for sql server CRD to be created'
        sleep 30
    done
}

function output-primary-ip-address {
    PRIMARY_IP=''
    while [[ -z $PRIMARY_IP ]]
        do PRIMARY_IP=$(kubectl get svc/ag1-primary -n ag1 -o=jsonpath='{.status.loadBalancer.ingress[0].ip}' --ignore-not-found=true)
        echo 'Waiting for primary AG IP Address'
        sleep 30
    done
    echo Connect to SQL Primary: sqlcmd -S ${PRIMARY_IP} -U sa
}

function delete-resource-group {
    az group delete --name $1 --yes
}

"$@"


# NOTE: you may not be able to unzip logs.zip in Linux since it was compressed in Windows
set -e
dateString=`date -I` # like 2022-09-24
filepath=logs_$dateString
mkdir $filepath

echo "gathering logs and writing to $filepath/"

kubectl get pod -A -o wide --show-labels > $filepath/allpods.out
kubectl get netpol -A -o yaml > $filepath/all-netpol-yamls.out
kubectl describe netpol -A > $filepath/all-netpol-descriptions.out

npmPods=()
nodes=()
for npmPodOrNode in `kubectl get pod -n kube-system -owide --output=custom-columns='Name:.metadata.name,Node:spec.nodeName' | grep "npm-win"`; do
    # for loop will go over each item (npm pod, then its node, then the next npm pod, then its node, ...)
    set +e
    echo $npmPodOrNode | grep -q azure-npm-win-
    if [ $? -eq 0 ]; then
        npmPods+=($npmPodOrNode)
    else
        nodes+=($npmPodOrNode)
    fi
done
set -e

echo "npm pods: ${npmPods[@]}"
echo "nodes of npm pods: ${nodes[@]}"

for i in $(seq 1 ${#npmPods[*]}); do
    j=$((i-1))
    npmPod=${npmPods[$j]}
    node=${nodes[$j]}

    echo "gathering logs. npm pod: $npmPod. node: $node"
    kubectl logs -n kube-system $npmPod > $filepath/logs_$npmPod.out

    ips=()
    for ip in `kubectl get pod -A -owide --output=custom-columns='IP:.status.podIP,Node:spec.nodeName' | grep $node | grep -oP "\d+\.\d+\.\d+\.\d+"`; do
        ips+=($ip)
    done
    echo "node $node has IPs: ${ips[@]}"

    echo "copying ps1 file into $npmPod"
    kubectl cp ./pod_exec.ps1 kube-system/"$npmPod":execw.ps1

    echo "executing ps1 file on $npmPod"
    kubectl exec -it -n kube-system $npmPod -- powershell.exe -Command  .\\execw.ps1 "'${ips[@]}'"

    echo "copying logs.zip from $npmPod. NOTE: this will be a windows-based compressed archive (probably need windows to expand it)"
    kubectl cp kube-system/"$npmPod":npm-exec-logs.zip $filepath/npm-exec-logs_$node.zip
done

echo "finished gathering all logs. written to $filepath/"


#!/bin/bash

CERTS_STAGING_DIR=.
SAN_CNF_FILE=san.cnf
CERTIFICATE_VALIDITY_DAYS=3650
CERT_SUBJ="/C=US/ST=Washington/L=Redmond/O=Microsoft/OU=Azure/CN=azure-npm.kube-system.svc.cluster.local"

# Check if openssl is installed
if ! command -v openssl &> /dev/null
then
  echo "openssl could not be found"
  exit
fi

# Check if SAN_CNF_FILE exists
if [ ! -f "$SAN_CNF_FILE" ]
then
  echo "SAN_CNF_FILE does not exist"
  exit
fi

if [ ! -d "$CERTS_STAGING_DIR" ]
then
  echo "Creating $CERTS_STAGING_DIR"
  mkdir -p $CERTS_STAGING_DIR
fi

# Generate the ca certificate and key
openssl req -x509 -newkey rsa:4096 -days $CERTIFICATE_VALIDITY_DAYS -nodes -keyout $CERTS_STAGING_DIR/ca.key -out $CERTS_STAGING_DIR/ca.crt -subj $CERT_SUBJ

# Create a certificate signing request for the server
openssl req -newkey rsa:4096 -nodes -keyout $CERTS_STAGING_DIR/tls.key -out $CERTS_STAGING_DIR/server-req.pem -config $SAN_CNF_FILE -extensions v3_req -subj $CERT_SUBJ

# Sign the server certificate with the CA
openssl x509 -req -in $CERTS_STAGING_DIR/server-req.pem -CA $CERTS_STAGING_DIR/ca.crt -CAkey $CERTS_STAGING_DIR/ca.key -CAcreateserial -out $CERTS_STAGING_DIR/tls.crt --days $CERTIFICATE_VALIDITY_DAYS --extfile $SAN_CNF_FILE --extensions v3_req

# Remove the secret CA key and signing request
rm -rf $CERTS_STAGING_DIR/ca.key $CERTS_STAGING_DIR/server-req.pem


#!/bin/bash

# Delete a docker container with network namespace cleaned up by the Azure CNI plugin.
# Example usage: ./docker-run.sh ubuntu default

if [ $# -ne 2 ]; then
	echo "usage: docker-run.sh <container-name> <namespace>"
	exit 1
fi

pid=$(docker inspect -f '{{ .State.Pid }}' $1)
netnspath=/proc/$pid/ns/net
contid=$(docker inspect -f '{{ .Id }}' $1)
export CNI_CONTAINERID=$contid

netns=netnspath
export CNI_PATH='/opt/cni/bin'
export CNI_COMMAND='DEL'
export PATH=$CNI_PATH:$PATH
export CNI_NETNS=$netns
args=$(printf "K8S_POD_NAMESPACE=%s;K8S_POD_NAME=%s" $2 $1)
export CNI_ARGS=$args
export CNI_IFNAME='eth0'

config=$(jq '.plugins[0]' /etc/cni/net.d/10-azure.conflist)
name=$(jq -r '.name' /etc/cni/net.d/10-azure.conflist)
config=$(echo $config | jq --arg name $name '. + {name: $name}')
cniVersion=$(jq -r '.cniVersion' /etc/cni/net.d/10-azure.conflist)
config=$(echo $config | jq --arg cniVersion $cniVersion '. + {cniVersion: $cniVersion}')

res=$(echo $config | azure-vnet)

if [ $? -ne 0 ]; then
	errmsg=$(echo $res | jq -r '.msg')
	if [ -z "$errmsg" ]; then
		errmsg=$res
	fi
	echo "${name} : error executing $CNI_COMMAND: $errmsg"
	exit 1
elif [[ ${DEBUG} -gt 0 ]]; then
	echo ${res} | jq -r .
fi

docker rm -f $1


#!/bin/bash

# Run a docker container with network namespace set up by the Azure CNI plugin.
# Example usage: ./docker-run.sh ubuntu default sushantsharma/ubuntu-s5

if [ $# -ne 3 ]; then
	echo "usage: docker-run.sh <container-name> <namespace> <image>"
	exit 1
fi

contid=$(docker run -d --name $1 --net=none $3 /bin/sleep 10000000)
export CNI_CONTAINERID=$contid
pid=$(docker inspect -f '{{ .State.Pid }}' $contid)
netns=/proc/$pid/ns/net

export CNI_PATH='/opt/cni/bin'
export CNI_COMMAND='ADD'
export PATH=$CNI_PATH:$PATH
export CNI_NETNS=$netns
args=$(printf "K8S_POD_NAMESPACE=%s;K8S_POD_NAME=%s" $2 $1)
export CNI_ARGS=$args
export CNI_IFNAME='eth0'

config=$(jq '.plugins[0]' /etc/cni/net.d/10-azure.conflist)
name=$(jq -r '.name' /etc/cni/net.d/10-azure.conflist)
config=$(echo $config | jq --arg name $name '. + {name: $name}')
cniVersion=$(jq -r '.cniVersion' /etc/cni/net.d/10-azure.conflist)
config=$(echo $config | jq --arg cniVersion $cniVersion '. + {cniVersion: $cniVersion}')

res=$(echo $config | azure-vnet)

if [ $? -ne 0 ]; then
	errmsg=$(echo $res | jq -r '.msg')
	if [ -z "$errmsg" ]; then
		errmsg=$res
	fi
	echo "${name} : error executing $CNI_COMMAND: $errmsg"
	exit 1
elif [[ ${DEBUG} -gt 0 ]]; then
	echo ${res} | jq -r .
fi


#!/usr/bin/env bash

# Installs azure-vnet CNI plugins on a Linux node.

# Arguments.
PLUGIN_VERSION=$1
CNI_VERSION=$2
CNI_BIN_DIR=/opt/cni/bin
CNI_NETCONF_DIR=/etc/cni/net.d

function usage
{
    printf "Installs azure-vnet CNI plugins.\n"
    printf "Usage: install-cni-plugin version [cniVersion]\n"
}

if [ "$PLUGIN_VERSION" = "" ]; then
    usage
    exit 1
fi

if [ "$CNI_VERSION" = "" ]; then
    CNI_VERSION=v0.4.0
fi

# Create CNI directories.
printf "Creating CNI directories.\n"
mkdir -p $CNI_BIN_DIR
mkdir -p $CNI_NETCONF_DIR

# Install ebtables.
if [ ! -e /sbin/ebtables ]
then
    printf "Installing ebtables package..."
    apt-get update
    apt-get install -y ebtables
    printf "done.\n"
else
    echo "Package ebtables is already installed."
fi
/sbin/ebtables --list > /dev/null

# Install azure-vnet CNI plugins.
printf "Installing azure-vnet CNI plugin for multitenancy version $PLUGIN_VERSION to $CNI_BIN_DIR..."
/usr/bin/curl -sSL https://github.com/Azure/azure-container-networking/releases/download/$PLUGIN_VERSION/azure-vnet-cni-multitenancy-linux-amd64-$PLUGIN_VERSION.tgz > $CNI_BIN_DIR/azure-vnet.tgz
tar -xzf $CNI_BIN_DIR/azure-vnet.tgz -C $CNI_BIN_DIR
printf "done.\n"

# Install azure-vnet CNI network configuration file.
printf "Installing azure-vnet CNI network configuration file to $CNI_NETCONF_DIR..."
mv $CNI_BIN_DIR/*.conflist $CNI_NETCONF_DIR
printf "done.\n"

# Install loopback plugin.
printf "Installing loopback CNI plugin version $CNI_VERSION to $CNI_BIN_DIR..."
/usr/bin/curl -sSL https://github.com/containernetworking/cni/releases/download/$CNI_VERSION/cni-amd64-$CNI_VERSION.tgz > $CNI_BIN_DIR/cni.tgz
tar -xzf $CNI_BIN_DIR/cni.tgz -C $CNI_BIN_DIR ./loopback
printf "done.\n"

# Cleanup.
rm $CNI_BIN_DIR/*.tgz
chown root:root $CNI_BIN_DIR/*

printf "azure-vnet CNI plugin is successfully installed.\n"


#!/usr/bin/env bash

# Installs azure-vnet CNI plugins on a Linux node.

# Arguments.
PLUGIN_VERSION=$1
CNI_VERSION=$2
CNI_BIN_DIR=/opt/cni/bin
CNI_NETCONF_DIR=/etc/cni/net.d

function usage
{
    printf "Installs azure-vnet CNI plugins.\n"
    printf "See https://github.com/Azure/azure-container-networking/releases for versions\n"
    printf "Usage: install-cni-plugin version [pluginVersion]\n"
}

if [ "$PLUGIN_VERSION" = "" ]; then
    usage
    exit 1
fi

if [ "$CNI_VERSION" = "" ]; then
    CNI_VERSION=v1.1.1
fi

# Create CNI directories.
printf "Creating CNI directories.\n"
mkdir -p $CNI_BIN_DIR
mkdir -p $CNI_NETCONF_DIR

# Install ebtables.
if [ ! -e /sbin/ebtables ]
then
    printf "Installing ebtables package..."
    apt-get update
    apt-get install -y ebtables
    printf "done.\n"
else
    echo "Package ebtables is already installed."
fi
/sbin/ebtables --list > /dev/null

# Install azure-vnet CNI plugins.
printf "Installing azure-vnet CNI plugin version $PLUGIN_VERSION to $CNI_BIN_DIR..."
/usr/bin/curl -sSL https://github.com/Azure/azure-container-networking/releases/download/$PLUGIN_VERSION/azure-vnet-cni-linux-amd64-$PLUGIN_VERSION.tgz > $CNI_BIN_DIR/azure-vnet.tgz
tar -xzf $CNI_BIN_DIR/azure-vnet.tgz -C $CNI_BIN_DIR
printf "done.\n"

# Install azure-vnet CNI network configuration file.
printf "Installing azure-vnet CNI network configuration file to $CNI_NETCONF_DIR..."
mv $CNI_BIN_DIR/*.conflist $CNI_NETCONF_DIR
printf "done.\n"

# Install loopback plugin.
printf "Installing loopback CNI plugin version $CNI_VERSION to $CNI_BIN_DIR..."
/usr/bin/curl -sSL https://github.com/containernetworking/plugins/releases/download/$CNI_VERSION/cni-plugins-linux-amd64-$CNI_VERSION.tgz > $CNI_BIN_DIR/cni.tgz
tar -xzf $CNI_BIN_DIR/cni.tgz -C $CNI_BIN_DIR ./loopback
printf "done.\n"

# Cleanup.
rm $CNI_BIN_DIR/*.tgz
chown root:root $CNI_BIN_DIR/*

printf "azure-vnet CNI plugin is successfully installed.\n"


#!/usr/bin/env bash

PROTOBUFF_VERSION=3.19.1
PB_REL="https://github.com/protocolbuffers/protobuf/releases"
PROTOC_ZIP_NAME=protoc-${PROTOBUFF_VERSION}-linux-x86_64.zip
PROTOC_INSTALL_PATH=$HOME/.local

# install unzip on linux if not installed
if [[ "$OSTYPE" == "linux-gnu" ]]; then
	if ! type "unzip" > /dev/null; then
		sudo apt-get install unzip
	fi
fi

# install protoc and protoc-gen-go
if [ ! -f ${PROTOC_INSTALL_PATH}/bin/protoc ]; then
    echo "Installing protobuf compiler"
		curl -LO ${PB_REL}/download/v${PROTOBUFF_VERSION}/${PROTOC_ZIP_NAME}
		echo "Unzipping protoc"
		unzip -o ${PROTOC_ZIP_NAME} -d ${PROTOC_INSTALL_PATH}
		chmod +x ${PROTOC_INSTALL_PATH}/bin/protoc
		export PATH=${PROTOC_INSTALL_PATH}/bin:$PATH
		echo "Removing protoc zip"
		rm ${PROTOC_ZIP_NAME}
else
	echo "Protobuf compiler already installed at ${PROTOC_INSTALL_PATH}/bin/protoc"
	echo "Add protoc to your PATH if you want to use it from anywhere else using the following command:"
	export PATH=${PROTOC_INSTALL_PATH}/bin:$PATH
fi

# install protoc-gen-go
if [ ! -f ${GOPATH}/bin/protoc-gen-go ]; then
	echo "Installing protoc-gen-go"
	go install github.com/golang/protobuf/protoc-gen-go@v1.26
else
	echo "protoc-gen-go already installed at ${GOPATH}/bin/protoc-gen-go"
fi

# install protoc-gen-go-grpc
if [ ! -f ${GOPATH}/bin/protoc-gen-go-grpc ]; then
	echo "Installing protoc-gen-go-grpc"
	go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1
else
	echo "protoc-gen-go-grpc already installed at ${GOPATH}/bin/protoc-gen-go-grpc"
fi


#!/bin/bash

export MAJOR=0
export MINOR=0
export PATCH=0
export FULL_TAG="v0.0.0"

function create_release () {
    parse_git_tag

    if increment_git_tag
    then
        FULL_TAG="v${MAJOR}.${MINOR}.${PATCH}"
        set_git_tag
    else
        echo "local git tag unchanged"
    fi
}

function get_git_tag () {

    return echo "v${MAJOR}${MINOR}${PATCH}"
}

function set_git_tag () {
    read -p "Set git tag to $FULL_TAG? [y/N] " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$  ]]
    then
        git tag $FULL_TAG
        echo "git tag set to $FULL_TAG"

        push_git_tag
    fi

    return
}

function push_git_tag {
    remote=$(git rev-parse --abbrev-ref --symbolic-full-name @{u} | cut -f1 -d"/")

    read -p "Push git tag to remote $remote? [y/N] " -n 1
    echo
    if [[ $REPLY =~ ^[Yy]$  ]]
    then
        git push $remote $FULL_TAG
    fi
}

function increment_git_tag () {
    read -p "Does this release contain incompatible API changes? [y/N] " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$  ]]
    then
        MAJOR=$((MAJOR+1))
        MINOR=0
        PATCH=0
        return
    fi

    read -p "Does this release contain added functionality that's backwards compatible? [y/N] " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$  ]]
    then
        MINOR=$((MINOR+1))
        PATCH=0
        return
    fi

    read -p "Does this release only contain backwards compatible bug fixes [y/N] " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$  ]]
    then
        PATCH=$((PATCH+1))
        return
    fi

    false
}

function parse_git_tag () {
    FULL_TAG=$(git describe --tags --abbrev=0)
    echo Current git tag: $FULL_TAG
    echo "--------"
    tagArr=(${FULL_TAG//./ })
    MAJOR=${tagArr[0]:1}
    MINOR=${tagArr[1]}
    PATCH=${tagArr[2]}
}

create_release


# this is required so that if a step fails, following steps are not run
set -o errexit

log() {
	local msg=$1
	echo "$(date -R): $msg"
}

# Installs NPM + a long-running Pod and does the following tests:
# 1.1. Check if HNS rehydration of endpoints works (filename: rehydration.failed)
# 1.2. Check VFP is in sync with HNS (filename: vfp-state-prior.success)
# 2. Run Cyclonus (filename: cyclonus.success)
# 3. Check VFP is in sync with HNS (filename: vfp-state-after-cyclonus.success)
# 4. Run Conformance (filename: conformance.success)
# 5. Check VFP is in sync with HNS (filename: vfp-state-after-conformance.success)
# 6. Run scale + connectivity test (filename: scale-connectivity.success)
# 7. Check VFP is in sync with HNS (filename: vfp-state-after-scale.success)
#
# NOTE: each step also has a .ran file that is created if the step is run.
#
# There is also:
# - A npm-e2e.ran file that indicates that the npm e2e was run at all
# - A npm-e2e.success that indicates that all steps succeeded
npm_e2e () {
    local kubeconfigFile=$1
    if [ -z "$kubeconfigFile" ]; then
        log "ERROR: kubeconfigFile not set. can't run NPM e2e"
        return 1
    fi

    test -f $kubeconfigFile || {
        log "ERROR: kubeconfigFile $kubeconfigFile not found. can't run NPM e2e"
        return 1
    }

    log "setting up npm e2e test"
    anyStepFailed=false

    # make sure there are no previous results
    log "cleaning up previous npm e2e results..."
    rm *.log *.ran *.success *.failed || true
    rm -rf npm-hns-state/ || true

    echo "" > npm-e2e.ran

    install_npm

    log "sleeping 8m for NPM to bootup, then verifying VFP tags after bootup..."
    sleep 8m
    verify_vfp_tags_using_npm vfp-state-prior || anyStepFailed=true

    ## NPM cyclonus
    run_npm_cyclonus && echo "" > cyclonus.success || anyStepFailed=true

    log "sleeping 5m to allow VFP to update tags after cyclonus..."
    sleep 5m
    log "verifying VFP tags after cyclonus..."
    verify_vfp_tags_using_npm vfp-state-after-cyclonus || anyStepFailed=true
    log "deleting cyclonus pods..."
    kubectl delete ns x y z || true

    ## NPM conformance
    run_npm_conformance && echo "" > conformance.success || anyStepFailed=true

    log "sleeping 5m to allow VFP to update tags after conformance..."
    sleep 5m
    log "verifying VFP tags after conformance..."
    verify_vfp_tags_using_npm vfp-state-after-conformance || anyStepFailed=true
    log "deleting NPM conformance namespaces if they were leftover from a failure..."
    kubectl delete ns -l pod-security.kubernetes.io/enforce=baseline || true

    ## NPM scale
    run_npm_scale $kubeconfigFile && echo "" > scale-connectivity.success ||  anyStepFailed=true
    log "sleeping 5m to allow VFP to update tags after scale test..."
    sleep 5m
    log "verifying VFP tags after scale test..."
    verify_vfp_tags_using_npm vfp-state-after-scale || anyStepFailed=true

    if [[ $anyStepFailed == false ]]; then
    	echo "" > npm-e2e.success
    fi
}

install_npm () {
    ## disable Calico NetPol
    log "running helm uninstall on calico (this will remove the tigera-operator and prevent reconciling of the calico-node ClusterRole)..."
    helm uninstall calico -n tigera-operator
    kubectl delete ns tigera-operator
    log "disabling Calico NetworkPolicy functionality by removing NetPol permission from calico-node ClusterRole..."
    kubectl get clusterrole calico-node -o yaml > original-clusterrole.yaml
    cat original-clusterrole.yaml | perl -0777 -i.original -pe 's/- apiGroups:\n  - networking.k8s.io\n  resources:\n  - networkpolicies\n  verbs:\n  - watch\n  - list\n//' > new-clusterrole.yaml
    originalLineCount=`cat original-clusterrole.yaml | wc -l`
    newLineCount=`cat new-clusterrole.yaml | wc -l`
    if [ $originalLineCount != $(($newLineCount + 7)) ]; then
        # NOTE: this check will only work the first time this script is run, since the original-clusterrole.yaml will be modified
        log "ERROR: unable to run NPM e2e. unexpected line count difference between original and new calico-node clusterrole. original: $originalLineCount, new: $newLineCount"
        return 1
    fi
    kubectl rollout restart ds -n calico-system calico-node-windows

    ## disable scheduling for all but one node for NPM tests, since intra-node connectivity is broken after disabling Calico NetPol
    kubectl get node -o wide | grep "Windows Server 2022 Datacenter" | awk '{print $1}' | tail -n +2 | xargs kubectl cordon
    kubectl get node -o wide | grep "Windows Server 2022 Datacenter" | grep -v SchedulingDisabled | awk '{print $1}' | xargs -n 1 -I {} kubectl label node {} scale-test=true connectivity-test=true

    # sleep for some time to let Calico CNI restart
    sleep 3m

    ## install Azure NPM
    log "installing Azure NPM..."
    npmURL=https://raw.githubusercontent.com/Azure/azure-container-networking/0ea4e9ac3d287f7abb15a34a88beb87697fbbcdd/npm/examples/windows/azure-npm-capz.yaml #https://raw.githubusercontent.com/Azure/azure-container-networking/master/npm/examples/windows/azure-npm-capz.yaml
    kubectl apply -f $npmURL

    # verify VFP tags after NPM boots up
    # seems like the initial NPM Pods are always deleted and new ones are created (within the first minute of being applied it seems)
    # sleep for some time to avoid running kubectl wait on pods that get deleted
    log "waiting for NPM to start running..."
    sleep 3m
    kubectl wait --for=condition=Ready pod -l k8s-app=azure-npm -n kube-system --timeout=15m

    ## set registry keys for NPM fixes
    log "updating registry keys and restarting HNS for NPM fixes..."
    npmNode=`kubectl get node -owide | grep "Windows Server 2022 Datacenter" | grep -v SchedulingDisabled | grep -v kwok-node | awk '{print $1}' | tail -n 1` || true
    if [[ -z $npmNode ]]; then
        log "ERROR: unable to find uncordoned node for NPM"
        return 1
    fi
    npmPod=`kubectl get pod -n kube-system -o wide | grep azure-npm-win | grep $npmNode | grep Running | awk '{print $1}'` || true
    if [[ -z "$npmPod" ]]; then
        log "ERROR: unable to find running azure-npm-win pod on node $npmNode"
        kubectl get pod -n kube-system -o wide
        kubectl logs -n kube-system -l k8s-app=azure-npm
        return 1
    fi
    cmd="reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\hns\State /v HnsAclUpdateChange /t REG_DWORD /d 1 /f"
    cmd="$cmd ; reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\hns\State /v HnsAclUpdateChange"
    cmd="$cmd ; reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\hns\State /v HnsNpmRefresh /t REG_DWORD /d 1 /f"
    cmd="$cmd ; reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\hns\State /v HnsNpmRefresh"
    cmd="$cmd ; Restart-Service HNS"
    cmd="$cmd ; sleep 10"
    cmd="$cmd ; Restart-Computer"
    kubectl exec -n kube-system $npmPod -- powershell.exe "$cmd"
    log "sleeping 3m to let HNS restart..."
    sleep 3m

    ## install long-running pod and restart HNS again (must install after restarting HNS because of a fix in rehydrating Endpoints in one of the registry keys)
    log "creating long-runner pod to ensure there's an endpoint for verifying VFP tags..."
    kubectl create ns npm-e2e-longrunner
    kubectl apply -f https://raw.githubusercontent.com/Azure/azure-container-networking/master/npm/examples/windows/long-running-pod-for-capz.yaml
    sleep 10s
    log "making sure long-runner is running"
    kubectl wait --for=condition=Ready pod -l app=long-runner -n npm-e2e-longrunner --timeout=15m

    log "restarting HNS again to make sure Endpoints rehydrate correctly"
    kubectl exec -n kube-system $npmPod -- powershell.exe "Restart-Service HNS"

    log "sleeping 3m to let HNS restart..."
    sleep 3m

    log "making sure NPM and long-runner are running..."
    kubectl wait --for=condition=Ready pod -l k8s-app=azure-npm -n kube-system --timeout=15m
    kubectl wait --for=condition=Ready pod -l app=long-runner -n npm-e2e-longrunner --timeout=15m
}

verify_vfp_tags_using_npm () {
    local ranFilename=$1
    if [[ -z $ranFilename ]]; then
        log "ERROR: need a filename passed as an argument to verify_vfp_tags_using_npm"
        return 1
    fi

    log "verifying VFP tags are equal to HNS SetPolicies..."
    npmNode=`kubectl get node -owide | grep "Windows Server 2022 Datacenter" | grep -v SchedulingDisabled | grep -v kwok-node | awk '{print $1}' | tail -n 1` || true
    if [[ -z $npmNode ]]; then
        log "ERROR: unable to find uncordoned node for NPM"
        return 1
    fi
    npmPod=`kubectl get pod -n kube-system -o wide | grep azure-npm-win | grep $npmNode | grep Running | awk '{print $1}'` || true
    if [[ -z "$npmPod" ]]; then
        log "ERROR: unable to find running azure-npm-win pod on node $npmNode"
        kubectl get pod -n kube-system -o wide
        kubectl logs -n kube-system -l k8s-app=azure-npm
        return 1
    fi

    onNodeIPs=() ; for ip in `kubectl get pod -owide -A  | grep $npmNode | grep -oP "\d+\.\d+\.\d+\.\d+" | sort | uniq`; do onNodeIPs+=($ip); done
    matchString="" ; for ip in ${onNodeIPs[@]}; do matchString+=" \"${ip}\""; done
    matchString=`echo $matchString | tr ' ' ','`
    log "using matchString: $matchString"
    ipsetCount=`kubectl exec -n kube-system $npmPod -- powershell.exe "(Get-HNSNetwork | ? Name -Like Calico).Policies | convertto-json  > setpols.txt ; (type .\setpols.txt | select-string '\"PolicyType\":  \"IPSET\"').count" | tr -d '\r'`
    log "HNS IPSET count: $ipsetCount"
    kubectl exec -n kube-system $npmPod -- powershell.exe 'echo "attempting to delete previous results if they exist" ; Remove-Item -path vfptags -recurse ; mkdir vfptags'
    kubectl exec -n kube-system $npmPod -- powershell.exe '$endpoints = (Get-HnsEndpoint | ? IPAddress -In '"$matchString"').Id ; foreach ($port in $endpoints) { vfpctrl /port $port /list-tag > vfptags\$port.txt ; (type vfptags\$port.txt | select-string -context 2 "TAG :").count }' > vfp-tag-counts.txt

    hadEndpoints=false
    hadFailure=false
    for count in `cat vfp-tag-counts.txt | xargs -n 1 echo`; do
        hadEndpoints=true
        count=`echo $count | tr -d '\r'`
        log "VFP tag count: $count"
        if [[ $count != $ipsetCount ]]; then
            log "WARNING: VFP tag count $count does not match HNS IPSET count $ipsetCount"
            hadFailure=true
        fi
    done

    echo "" > rehydration.ran
    if [[ $hadEndpoints == false ]]; then
        log "ERROR: no Endpoints found in HNS for node IPs $matchString on node $npmNode. Rehydration of Endpoints likely failed"
	echo "" > rehydration.failed
        return 1
    fi

    echo "" > $ranFilename.ran
    if [[ $hadFailure == true ]]; then
        log "ERROR: VFP tags are inconsistent with HNS SetPolicies"
        capture_npm_hns_state
        return 1
    fi

    echo "" > $ranFilename.success
}

# results in a file called npm-hns-state.zip
capture_npm_hns_state () {
    if [[ -f npm-hns-state.zip ]]; then
        log "WARNING: not capturing NPM HNS state since state was previously captured"
        return 0
    fi

    log "capturing NPM HNS state..."
    kubectl get pod -owide -A
    mkdir npm-hns-state
    cd npm-hns-state
    curl -LO https://raw.githubusercontent.com/Azure/azure-container-networking/master/debug/windows/npm/win-debug.sh
    chmod u+x ./win-debug.sh
    curl -LO https://raw.githubusercontent.com/Azure/azure-container-networking/master/debug/windows/npm/pod_exec.ps1
    ./win-debug.sh
    cd ..
    zip -9qr npm-hns-state.zip npm-hns-state
    # to unzip:
    # unzip npm-hns-state.zip -d npm-hns-state
}

# currently takes ~3 hours to run
# e.g. 19:37:05 to 22:32:44 and 19:16:18 to 22:29:13
run_npm_conformance () {
    ## install NPM e2e binary
    log "ensuring NPM e2e binary is installed"
    rc=0; test -f npm-e2e.test || rc=$?
    if [[ $rc == 0 ]]; then
        log "NPM e2e binary found, skipping install"
    else
        log "NPM e2e binary not found, installing..."
        test -d npm-kubernetes/ && rm -rf npm-kubernetes/ || true
        mkdir npm-kubernetes
        cd npm-kubernetes
        # NOTE: if this is not downloaded every run, then probably need to sleep before the VFP tag verification
        git clone https://github.com/huntergregory/kubernetes.git --depth=1 --branch=quit-on-failure
        cd kubernetes
        make WHAT=test/e2e/e2e.test
        cd ../..
        mv npm-kubernetes/kubernetes/_output/local/bin/linux/amd64/e2e.test ./npm-e2e.test
        rm -rf npm-kubernetes/
    fi

    log "beginning npm conformance test..."

    toRun="NetworkPolicy"

    nomatch1="should enforce policy based on PodSelector or NamespaceSelector"
    nomatch2="should enforce policy based on NamespaceSelector with MatchExpressions using default ns label"
    nomatch3="should enforce policy based on PodSelector and NamespaceSelector"
    nomatch4="should enforce policy based on Multiple PodSelectors and NamespaceSelectors"
    cidrExcept1="should ensure an IP overlapping both IPBlock.CIDR and IPBlock.Except is allowed"
    cidrExcept2="should enforce except clause while egress access to server in CIDR block"
    namedPorts="named port"
    wrongK8sVersion="Netpol API"
    toSkip="\[LinuxOnly\]|$nomatch1|$nomatch2|$nomatch3|$nomatch4|$cidrExcept1|$cidrExcept2|$namedPorts|$wrongK8sVersion|SCTP"

    # to debug with one test case, uncomment this
    # toRun="NetworkPolicy API should support creating NetworkPolicy API operations"

    echo "" > conformance.ran
    KUBERNETES_SERVICE_PORT=443 ./npm-e2e.test \
        --provider=skeleton \
        --ginkgo.noColor \
        --ginkgo.focus="$toRun" \
        --ginkgo.skip="$toSkip" \
        --allowed-not-ready-nodes=1 \
        --node-os-distro="windows" \
        --disable-log-dump \
        --ginkgo.progress=true \
        --ginkgo.slowSpecThreshold=120.0 \
        --ginkgo.flakeAttempts=0 \
        --ginkgo.trace=true \
        --ginkgo.v=true \
        --dump-logs-on-failure=true \
        --report-dir="${ARTIFACTS}" \
        --prepull-images=true \
        --v=5 "${ADDITIONAL_E2E_ARGS[@]}" | tee npm-e2e.log || true

    # grep "FAIL: unable to initialize resources: after 10 tries, 2 HTTP servers are not ready

    log "finished npm conformance test"
    ## report if there's a failure
    rc=0; cat npm-e2e.log | grep '"failed":1' > /dev/null 2>&1 || rc=$?
    if [ $rc -eq 0 ]; then
        log "ERROR: found failure in npm e2e test log"
        capture_npm_hns_state
        return 1
    fi
}

# currently takes ~3.5 hours to run
# e.g. 20:49:05 to 00:21:12
run_npm_cyclonus () {
    log "installing cyclonus binary..."
    curl -fsSL github.com/mattfenwick/cyclonus/releases/latest/download/cyclonus_linux_amd64.tar.gz | tar -zxv

    log "beginning npm cyclonus test..."
    echo "" > cyclonus.ran
    ./cyclonus_linux_amd64/cyclonus generate \
        --junit-results-file=cyclonus.xml \
        --fail-fast \
        --noisy=true \
        --retries=7 \
        --ignore-loopback=true \
        --perturbation-wait-seconds=20 \
        --pod-creation-timeout-seconds=480 \
        --job-timeout-seconds=15 \
        --server-protocol=TCP,UDP \
        --exclude sctp,named-port,ip-block-with-except,multi-peer,upstream-e2e,example,end-port,namespaces-by-default-label,update-policy | tee npm-cyclonus.log || true

    # for debugging with a smaller set of tests, use this as the last line instead
        # --exclude sctp,named-port,ip-block-with-except,multi-peer,upstream-e2e,example,end-port,namespaces-by-default-label,update-policy,all-namespaces,all-pods,allow-all,any-peer,any-port,any-port-protocol,deny-all,ip-block-no-except,multi-port/protocol,namespaces-by-label,numbered-port,pathological,peer-ipblock,peer-pods,pods-by-label,policy-namespace,port,protocol,rule,tcp,udp --include conflict,direction,egress,ingress,miscellaneous  | tee npm-cyclonus.log || true

    rc=0; cat npm-cyclonus.log | grep "failed" > /dev/null 2>&1 || rc=$?
    if [[ $rc == 0 ]]; then
        echo "ERROR: failures encountered in npm cyclonus test"
        capture_npm_hns_state
        return 1
    fi

    rc=0; cat npm-cyclonus.log | grep "SummaryTable:" > /dev/null 2>&1 || rc=$?
    if [[ $rc != 0 ]]; then
        log "ERROR: npm cyclonus test did not finish for some reason"
        capture_npm_hns_state
        return 1
    fi
}

run_npm_scale () {
    local kubeconfigFile=$1

    log "beginning npm scale test with kubeconfig [$kubeconfigFile]..."

    rm -rf azure-container-networking/ || true
    git clone https://github.com/Azure/azure-container-networking.git --depth=1 --branch=master

    cd azure-container-networking/test/scale/

    chmod u+x test-scale.sh
    cd connectivity/
    chmod u+x test-connectivity.sh
    cd ../

    # run kwok
    kwok --kubeconfig=$kubeconfigFile \
        --cidr=155.0.0.0/16 \
        --node-ip=155.0.0.1 \
        --manage-all-nodes=false \
        --manage-nodes-with-annotation-selector=kwok.x-k8s.io/node=fake \
        --manage-nodes-with-label-selector= \
        --disregard-status-with-annotation-selector=kwok.x-k8s.io/status=custom \
        --disregard-status-with-label-selector= > ../../../kwok.log &
    kwok_pid=$!

    # exact counts output from script
    # Pod Counts:
    # - 25 fake Pods
    # - 5 real Pods
    # HNS Counts:
    # - number of ACLs per Pod Endpoint: 6 (6*numNetworkPolicies)
    # - number of SetPolicies: ~100 (2*numUniqueLabelsPerPod*numFakePods)
    # - max IPs per SetPolicy: number of total Pods
    ./test-scale.sh --max-kwok-pods-per-node=50 \
        --num-kwok-deployments=5 \
        --num-kwok-replicas=5 \
        --max-real-pods-per-node=30 \
        --num-real-deployments=5 \
        --num-real-replicas=1 \
        --num-network-policies=1 \
        --num-unapplied-network-policies=3 \
        --num-unique-labels-per-pod=2 \
        --num-unique-labels-per-deployment=2 \
        --num-shared-labels-per-pod=10 \
        --delete-labels \
        --delete-labels-interval=60 \
        --delete-labels-times=1 \
        --delete-netpols \
        --delete-netpols-interval=60 \
        --delete-netpols-times=1 \
        --delete-kwok-pods=1 \
        --delete-real-pods=1 \
        --delete-pods-interval=120 \
        --delete-pods-times=1 | tee ../../../npm-scale.log || true

    rc=0; cat ../../../npm-scale.log | grep "FINISHED" > /dev/null 2>&1 || rc=$?
    if [[ $rc != 0 ]]; then
        log "ERROR: npm scale test did not properly scale"
        kill $kwok_pid
        cd ../../../
        return 1
    fi

    log "beginning npm scale connectivity test..."

    cd connectivity/

    minutesToWaitForInitialConnectivity=30
    minutesToWaitAfterAddingNetPol=10
    echo "" > ../../../../scale-connectivity.ran
    ./test-connectivity.sh --num-scale-pods-to-verify=all --max-wait-for-initial-connectivity=$((60*minutesToWaitForInitialConnectivity)) --max-wait-after-adding-netpol=$((60*minutesToWaitAfterAddingNetPol)) | tee ../../../../npm-scale-connectivity.log || true

    cd ../../../../
    rc=0; cat npm-scale-connectivity.log | grep "FINISHED" > /dev/null 2>&1 || rc=$?
    if [[ $rc != 0 ]]; then
        log "ERROR: npm scale test connectivity failed"
        kill $kwok_pid
        capture_npm_hns_state
        return 1
    fi

    echo "" > scale-connectivity.success
    kill $kwok_pid
}


LOG_FILE=cyclonus-$CLUSTER_NAME

# curl -fsSL github.com/mattfenwick/cyclonus/releases/latest/download/cyclonus_linux_amd64.tar.gz | tar -zxv
# ./cyclonus_linux_amd64/cyclonus generate \

# this branch has double the amount of workers
git clone https://github.com/huntergregory/cyclonus.git --branch=slowness --depth=1
cd cyclonus
make cyclonus
cmd/cyclonus/cyclonus generate \
    --noisy=true \
    --retries=7 \
    --ignore-loopback=true \
    --cleanup-namespaces=true \
    --perturbation-wait-seconds=17 \
    --pod-creation-timeout-seconds=480 \
    --job-timeout-seconds=5 \
    --server-protocol=TCP,UDP \
    --exclude sctp,named-port,ip-block-with-except,multi-peer,upstream-e2e,example,end-port,namespaces-by-default-label,update-policy | tee $LOG_FILE

# might need to redirect to /dev/null 2>&1 instead of just grepping with -q to avoid "cat: write error: Broken pipe"
rc=999
cat $LOG_FILE | grep "SummaryTable:" > /dev/null 2>&1 && rc=$?
echo $rc
if [ $rc -ne 0 ]; then
    echo "FAILING because cyclonus tests did not complete"
    exit 2
fi

rc=0
cat $LOG_FILE | grep "failed" > /dev/null 2>&1 || rc=$?
echo $rc
if [ $rc -eq 0 ]; then
    echo "FAILING because cyclonus completed but failures detected"
    exit 3
fi


#!/usr/bin/env bash

set -eo pipefail
set -xv

if [ -z "$1" == "windows"]
  then
    cyclonusProfile="./install-cyclonus-windows.yaml"
  else
    cyclonusProfile="./install-cyclonus.yaml"
fi

if [ -z "$1" ]
  then
    echo "Running with default profile: $cyclonusProfile"
elif [[ $1 == "extended" ]];
then
    # extended will exclude SCTP and will run 214 testcases with cyclonus
    cyclonusProfile="./install-cyclonus-exclude-sctp.yaml"
    echo "Running with exclude SCTP profile with 214 testcases: $cyclonusProfile"
fi

echo "Running with cyclonus profile: $cyclonusProfile"
kubectl delete --ignore-not-found=true clusterrolebinding cyclonus
kubectl delete --ignore-not-found=true sa cyclonus -n kube-system
kubectl delete --ignore-not-found=true -f $cyclonusProfile
kubectl delete --ignore-not-found=true ns x y z

sleep 5

# set up cyclonus
kubectl create clusterrolebinding cyclonus --clusterrole=cluster-admin --serviceaccount=kube-system:cyclonus
kubectl create sa cyclonus -n kube-system
kubectl create -f $cyclonusProfile

sleep 5

time kubectl wait --for=condition=ready --timeout=5m pod -n kube-system -l job-name=cyclonus

#!/bin/bash
{ kubectl logs -f -n kube-system job.batch/cyclonus;  } &
{ time kubectl wait --for=condition=completed --timeout=600m pod -n kube-system -l job-name=cyclonus;  } &
wait -n
pkill -P $$
echo done

# grab the job logs
LOG_FILE=cyclonus-test.txt
kubectl logs -n kube-system job.batch/cyclonus | tee "$LOG_FILE"
cat "$LOG_FILE"

kubectl delete --ignore-not-found=true clusterrolebinding cyclonus
kubectl delete --ignore-not-found=true sa cyclonus -n kube-system
kubectl delete --ignore-not-found=true -f $cyclonusProfile

# might need to redirect to /dev/null 2>&1 instead of just grepping with -q to avoid "cat: write error: Broken pipe"
rc=999
cat $LOG_FILE | grep "SummaryTable:" > /dev/null 2>&1 && rc=$?
echo $rc
if [ $rc -ne 0 ]; then
    echo "FAILING because cyclonus tests did not complete"
    exit 2
fi

rc=0
cat $LOG_FILE | grep "failed" > /dev/null 2>&1 || rc=$?
echo $rc
if [ $rc -eq 0 ]; then
    echo "FAILING because cyclonus completed but failures detected"
    exit 3
fi


#!/bin/bash

MASTER_JSON=$(pwd)/master.json
EXTERNAL_JSON=$(pwd)/external.json

kubectl create namespace kubemark --kubeconfig=$EXTERNAL_JSON
kubectl create configmap node-configmap -n kubemark --from-literal=content.type="test-cluster" --kubeconfig=$EXTERNAL_JSON
kubectl create secret generic kubeconfig --type=Opaque --namespace=kubemark --from-file=kubelet.kubeconfig=$MASTER_JSON --from-file=kubeproxy.kubeconfig=$MASTER_JSON --kubeconfig=$EXTERNAL_JSON


#!/bin/bash

argc=$#

if [[ $argc -ne 1 ]]
then
	echo "cmd [1 (create hollownodes), 2 (clean-up hollownodes), 3 (list hollownodes info), 4 (delete label from hollow-node)]"
	exit -1
fi

MASTER_JSON=$(pwd)/master.json
EXTERNAL_JSON=$(pwd)/external.json

cmd=$1
case $cmd in
"1")
	echo "Deploy hollow nodes on external cluster"
	# 1. Deploy "hollow-node" pods on external K8s cluster
    kubectl apply -f ./hollow-node.yaml --kubeconfig=$EXTERNAL_JSON
	# 2. check whether all "hollow-node" pods are running (i.e., Running status) on external K8s cluster
    watch -n1 kubectl get pods -n kubemark --kubeconfig=$EXTERNAL_JSON
	# 3. check whether all "hollow-node" pods are registed as "hollow-node" nodes on master K8s cluster
    watch -n1 kubectl get nodes -l "hollow-node=" --kubeconfig=$MASTER_JSON
	;;
"2")
	echo "Delete hollow nodes on external cluster and clean-up them on kubemark cluster"
	# 1. Delete "hollow-node" pods on external K8s cluster
    kubectl delete -f ./hollow-node.yaml --kubeconfig=$EXTERNAL_JSON
	# 2. Delete "hollow-node" nodes from master K8s cluster
	# You may need to run below command multiple times since the node is removed when its status is "NotReady"
    kubectl get nodes --kubeconfig=$MASTER_JSON | grep NotReady | awk '{print $1}' |  xargs kubectl delete node --kubeconfig=$MASTER_JSON
	;;
"3")
	echo "Get hollow nodes information on kubemark cluster"
	kubectl get nodes -o wide --kubeconfig=$MASTER_JSON
	echo ""
	kubectl get nodes -o wide --show-labels --kubeconfig=$MASTER_JSON | grep "hollow-node"
	;;
"4")
	# Need to delete "kubernetes.io/os" label not to deploy add-on pods
	# (e.g., azure-cni-networkmonitor-cfmgs, csi-secrets-store-cn9dp, kube-proxy-r9lpq, etc)
	# Something does not work.. Cannot delete "kubernetes.io/os" label on hollownode
	nodes=$(kubectl get nodes -l hollow-node= --kubeconfig=$MASTER_JSON | grep hollow | awk '{print $1}')
	for node in ${nodes[@]}
	do
		echo $node
		kubectl label node $node kubernetes.io/os- --kubeconfig=$MASTER_JSON
	done
	kubectl get nodes -l hollow-node= --show-labels --kubeconfig=$MASTER_JSON
	;;
*)
	echo "Unknown command :", $cmd
	;;
esac


#!/bin/bash
argc=$#

if [[ $argc -ne 1 ]]
then
	echo "cmd [1 (deploy npm on agent), 2 (delete npm), 3 (print npm log), 4 (connect to npm console), 5 [top npm]]"
	exit -1
fi

export KUBECONFIG=$(pwd)"/master.json"

cmd=$1
case $cmd in
"1")
	echo "Deploy NPM pod on agent of master K8s cluster"
	kubectl apply -f azure-npm-with-kubemark.yaml
	;;
"2")
	echo "Deploy NPM pod on agent of master K8s cluster"
	kubectl delete -f azure-npm-with-kubemark.yaml
	;;
"3")
	NPM_POD=$(kubectl get pods -l k8s-app=azure-npm -n kube-system -o wide --kubeconfig=$MASTER_JSON | grep agentpool | awk '{print $1}')
	kubectl logs -f $NPM_POD -n kube-system
	;;
"4")
	NPM_POD=$(kubectl get pods -l k8s-app=azure-npm -n kube-system -o wide --kubeconfig=$MASTER_JSON | grep agentpool | awk '{print $1}')
	kubectl exec -it $NPM_POD -n kube-system bash
	;;
"5")
	watch -n1 kubectl top  pod -l k8s-app=azure-npm -n kube-system
	;;
*)
	echo "Unknown command :", $cmd
	;;
esac


#!/bin/bash
argc=$#

if [[ $argc -ne 1 ]]
then
	echo "cmd [1 (create pods), 2 (delete pods), 3 (list pod), 4 (list deployment)]"
	exit -1
fi

# Deploy pods on hollownodes managed by master cluster.
export KUBECONFIG=$(pwd)/master.json

cmd=$1
case $cmd in
"1")
	echo "Deploy pods on hollow nodes of master K8s cluster"
	for index in {1..10}
	do
		kubectl apply -f deployments/deploy$index.yaml &
	done
	;;
"2")
	echo "Delete pods from hollow nodes of master K8s cluster"
	for index in {1..10}
	do
		kubectl delete -f deployments/deploy$index.yaml &
	done
	;;
"3")
	echo "list pods on master K8s cluster"
	kubectl get pods --all-namespaces -o wide
	;;
"4")
	echo "list deployment on master K8s cluster"
	watch -n1 kubectl get deployment --all-namespaces -o wide
	;;
*)
	echo "Unknown command :", $cmd
	;;
esac


kubectl run wget -it --rm --image busybox --restart Never -- wget --timeout=3 --header=Metadata:true "http://168.63.129.16/machine/plugins?comp=nmagent&type=getinterfaceinfov1"
if [ $? -eq 0 ]; then
    echo "wireserver connectivity expected to fail but succeeded"
    exit 1
fi

kubectl run wget -it --rm --image busybox --restart Never -- wget --timeout=3 --header=Metadata:true "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
if [ $? -ne 0 ]; then
    echo "metadata server connectivity expected to succeed but failed"
fi


KWOK_REPO=kubernetes-sigs/kwok
KWOK_LATEST_RELEASE=$(curl "https://api.github.com/repos/${KWOK_REPO}/releases/latest" | jq -r '.tag_name')
wget -O kwok -c "https://github.com/kubernetes-sigs/kwok/releases/download/${KWOK_LATEST_RELEASE}/kwok-$(go env GOOS)-$(go env GOARCH)"
chmod +x kwok
sudo mv kwok /usr/local/bin/kwok


###############################################################
# Schedule kwok nodes/pods and maintain kwok node heartbeats. #
###############################################################
# can pass kubeconfig as first arg
if [[ -z $1 ]]; then
    kubeconfigFile=~/.kube/config
else
    kubeconfigFile=$1
fi
echo "using kubeconfig $kubeconfigFile"

which kwok || {
    echo "ERROR: kwok not found. Install via ./install-kwok.sh"
    exit 1
}

set -x
kwok --kubeconfig $kubeconfigFile \
    --cidr=155.0.0.0/16 \
    --node-ip=155.0.0.1 \
    --manage-all-nodes=false \
    --manage-nodes-with-annotation-selector=kwok.x-k8s.io/node=fake \
    --manage-nodes-with-label-selector= \
    --disregard-status-with-annotation-selector=kwok.x-k8s.io/status=custom \
    --disregard-status-with-label-selector=