#!/bin/bash -xeu

required_env_vars=(
    "SKU_PREFIX"
    "SKU_TEMPLATE_FILE"
    "AZURE_TENANT_ID"
    "AZURE_CLIENT_ID"
    "AZURE_CLIENT_SECRET"
    "PUBLISHER"
    "OFFER"
    "CONTAINER_RUNTIME"
)

for v in "${required_env_vars[@]}"
do
    if [ -z "${!v}" ]; then
        echo "$v was not set!"
        exit 1
    fi
done

if [ ! -f "$SKU_TEMPLATE_FILE" ]; then
    echo "Could not find sku template file: ${SKU_TEMPLATE_FILE}!"
    exit 1
fi

# we use token as a workaround even after a successful login as a result of pub tool Authorization failure.
# allow-no-subscriptions is safe because we have no sub-level operations
echo "Get cloudpartner access token"
az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET --tenant $AZURE_TENANT_ID --allow-no-subscriptions
token=$(az account get-access-token --resource https://cloudpartner.azure.com --query "accessToken" -o tsv)
export AZURE_TOKEN=$token

ls -lhR artifacts
vhd_artifacts_path="publishing-info-2019"
if [[ ${CONTAINER_RUNTIME} = "containerd" ]]; then
    vhd_artifacts_path="publishing-info-2019-containerd"
fi
VHD_INFO="artifacts/vhd/${vhd_artifacts_path}/vhd-publishing-info.json"
if [ ! -f "$VHD_INFO" ]; then
    echo "Could not find VHD info file: ${VHD_INFO}!"
    exit 1
fi

short_date=$(date +"%y%m")
pretty_date=$(date +"%b %Y")
sku_id="${SKU_PREFIX}-${short_date}"
echo "Checking if offer contains SKU: $sku_id"
# Check if SKU already exists in offer
(set -x; hack/tools/bin/pub skus list -p $PUBLISHER -o $OFFER | jq ".[] | .planId" | tr -d '"' | tee skus.txt)
echo ""
if grep -q $sku_id skus.txt; then
    echo "Offer already has SKU"
else
    echo "Creating new SKU"
    < $SKU_TEMPLATE_FILE sed s/{{ID}}/"$sku_id"/ | sed s/{{MONTH-YEAR}}/"$pretty_date/" | sed s/{{CONTAINER_RUNTIME}}/"$CONTAINER_RUNTIME/" > sku.json
    echo "" ; cat sku.json ; echo ""
    hack/tools/bin/pub skus put -p $PUBLISHER -o $OFFER -f sku.json ; echo ""
fi

echo "Vhd publishing info:"
cat $VHD_INFO
echo

# Get VHD version info for vhd-publishing-info.json produced by previous pipeline stage
vhd_url=$(< $VHD_INFO jq -r ".vhd_url")
redact_vhd_url=${vhd_url/\?*/?***}
image_version=$(< $VHD_INFO jq -r ".image_version")

# generate media name
# Media name must be under 63 characters
media_name="${SKU_PREFIX}-${image_version}"
if [ "${#media_name}" -ge 63 ]; then
	echo "$media_name should be undr 63 characters"
	exit 1
fi

published_date=$(date +"%m/%d/%Y")
published_image_label="AKS Base Image for Windows"
published_image_description="AKS Base Image for Windows"
echo "publish image version to Marketplace"
echo "pubilsher: $PUBLISHER"
echo "offer: $OFFER"
echo "sku id: $sku_id"
echo "image version: $image_version"
echo "vhd url: $redact_vhd_url"
echo "media name: $media_name"
echo "published date: $published_date"
echo "image label: $published_image_label"
echo "image description: $published_image_description"
echo ""
set -x ; hack/tools/bin/pub versions put corevm -p $PUBLISHER -o $OFFER -s $sku_id --version $image_version --vhd-uri $vhd_url --media-name $media_name --label "AKS Base Image for Windows" --desc "AKS Base Image for Windows" --published-date "$published_date"


#!/bin/bash
set -euxo pipefail

source vhdbuilder/scripts/automate_helpers.sh

echo "Triggering ev2 artifact pipeline with Build ID $1"

build_ids=$1

trigger_pipeline() {
    pipeline_id="319030"   # 317897 is the pipeline ID for ev2 artifacts pipeline
    for build_id in $build_ids; do
        echo "Build ID for the release is $build_id"
        az pipelines variable update --name VHD_PIPELINE_RUN_ID --pipeline-id $pipeline_id --value $build_id  # Update the VHD_PIPELINE_RUN_ID with the build ID
        # In case auth fails/other issue, we do not want the pipeline to run if the build ID was not correctly updated
        if [[ $build_id != $(az pipelines variable list --pipeline-id $pipeline_id | jq -r '.VHD_PIPELINE_RUN_ID.value') ]]; then
            echo "Build ID failed to update, cancel operation"
            exit 1
        else
            echo "Build ID successfully updated"
        fi

        # Run the pipeline and fetch the run ID to poll for success later
        run_id=$(az pipelines run --id $pipeline_id | jq -r '.id')
        while ! az pipelines runs show --id $run_id | grep -q '"result": "succeeded"'; do
            echo "ev2 artifacts still running for build $build_id"
            sleep 100
        done
        echo "ev2 artifacts successfully built for build $build_id"
    done
}

trigger_pipeline


#!/bin/bash
set -euxo pipefail

build_ids=$1
global_image_version="${IMAGE_VERSION:=}"
for build_id in $build_ids; do
    for artifact in $(az pipelines runs artifact list --run-id $build_id | jq -r '.[].name'); do    # Retrieve what artifacts were published
        # This loop is because of how the Image Version is set for builds.
        # It uses the UTC time of when the build for a particular SKU ends.
        # So in the past, it has happened that you trigger a build at say 3/4pm PST,
        # some SKUs will have todays date some will have tomorrows based on when they are triggered because of UTC conversion
        # TODO(amaheshwari): Change VHD script to use a common var for image version that is plumbed down to all SKUs
        if [[ $artifact == *"publishing-info"* ]]; then
            az pipelines runs artifact download --artifact-name $artifact --path $(pwd) --run-id $build_id
            current_image_version=$(jq -r .image_version < vhd-publishing-info.json)
            if [[ $global_image_version != $current_image_version ]]; then
                if [[ -z $global_image_version ]]; then
                    global_image_version=$current_image_version
                else
                    echo "mismatched image, exiting"
                    exit 1
                fi
            fi
        fi
    done
done

echo $global_image_version
rm -rf vhd-publishing-info.json


#!/bin/bash
set -x

set_git_config() {
    # git config needs to be set in the agent
    git config --global user.email "amaheshwari@microsoft.com"
    git config --global user.name "anujmaheshwari1"
    git config --list
}

configure_az_devops() {
    # Login to azure devops using PAT/System Access Token for artifacts and triggering ev2 builds
    # TODO(amaheshwari): Use only PAT for both artifacts and builds
    az extension add -n azure-devops

    set +x
    echo $1 | az devops login --organization=https://dev.azure.com/msazure
    set -x

    az devops configure --defaults organization=https://dev.azure.com/msazure project=CloudNativeCompute
}

create_branch() {
    # Create PR branch
    echo "Create branch named $1"
    git checkout master
    git pull
    git checkout -b $1
}

create_pull_request() {
    # Commit current changes and create PR using curl
    echo "Image Version is $1"
    echo "Branch Name is $3"
    echo "PR is for $4"

    git remote set-url origin https://anujmaheshwari1:$2@github.com/Azure/AgentBaker.git  # Set remote URL with PAT
    git add .

    if [[ $4 == "ReleaseNotes" ]]; then
        git commit -m "chore: release notes for release $1"
    else
        git commit -m "chore: bumping image version to $1"
    fi

    git push -u origin $3 -f

    set +x  # To avoid logging PAT during curl
    curl \
        -X POST \
        https://api.github.com/repos/Azure/AgentBaker/pulls \
        -d '{
            "head" : "'$3'",
            "base" : "master",
            "title" : "chore: automated PR to update '$4' for '$1' VHD",
            "body" : "This is an automated PR to bump '$4' for the VHD release with image version '$1'"
        }' \
        -u "anujmaheshwari1:$2"
    set -x

    git checkout master # Checkout to master for subsequent stages of the pipeline
}


#!/bin/bash
set -euxo pipefail

source vhdbuilder/scripts/automate_helpers.sh

echo "Image version for release notes is $1"

image_version=$1
build_ids=$2

set +x
github_access_token=$3
set -x

branch_name=releaseNotes/$1
pr_title="ReleaseNotes"

generate_release_notes() {
    for build_id in $build_ids; do
        echo $build_id
        included_skus=""
        for artifact in $(az pipelines runs artifact list --run-id $build_id | jq -r '.[].name'); do    # Retrieve what artifacts were published
            if [[ $artifact == *"vhd-release-notes"* ]]; then
                sku=$(echo $artifact | cut -d "-" -f4-) # Format of artifact is vhd-release-notes-<name of sku>
                included_skus+="$sku,"
            fi
        done
        echo "SKUs for release notes are $included_skus"
        go run vhdbuilder/release-notes/autonotes/main.go --build $build_id --date $image_version --include ${included_skus%?}
    done
}

set_git_config
if [ `git branch --list $branch_name` ]; then
    git checkout $branch_name
    git pull origin
    git checkout master -- .
else
    create_branch $branch_name
fi

generate_release_notes
git status
set +x
create_pull_request $image_version $github_access_token $branch_name $pr_title


#!/bin/bash
set -euxo pipefail

source vhdbuilder/scripts/automate_helpers.sh

echo "New image version: $1"

current_image_version=""
new_image_version=$1

set +x
github_access_token=$2
set -x

build_ids=$3

branch_name=imageBump/$new_image_version
pr_title="VHDVersion"

# This function finds the current SIG Image version from the input JSON file
find_current_image_version() {
    filepath=$1
    current_image_version=$(jq -r .version $filepath)
    echo "Current image version is: ${current_image_version}"
}

# This function replaces the old image version with the new input image version for all relevant files
update_image_version() {
    sed -i "s/${current_image_version}/${new_image_version}/g" pkg/agent/datamodel/linux_sig_version.json
}

create_image_bump_pr() {
    create_branch $branch_name
    update_image_version

    set +x
    create_pull_request $new_image_version $github_access_token $branch_name $pr_title
    set -x
}

# This function cuts the official branch based off the commit ID that the builds were triggered from and tags it
cut_official_branch() {
    # Image version format: YYYYMM.DD.revision
    # Official branch format: official/vYYYYMMDD
    # Official tag format: v0.YYYYMMDD.revision
    parsed_image_version="$(echo -n "${new_image_version}" | head -c-1 | tr -d .)"
    official_branch_name="official/v${parsed_image_version}"
    official_tag="v0.${parsed_image_version}.0"
    final_commit_hash=""
    for build_id in $build_ids; do
        current_build_commit_hash=$(az pipelines runs show --id $build_id | jq -r '.sourceVersion')
        if [[ -z "$final_commit_hash" ]]; then
            final_commit_hash=$current_build_commit_hash
        else
            if [[ $final_commit_hash != $current_build_commit_hash ]]; then
                echo "Builds are not triggered off the same commit, exit"
                exit 1
            fi
        fi
    done
    echo "All builds are based off the same commit"

    # Checkout branch and commit the image bump file diff to official branch too
    if [ `git branch -r | grep $official_branch_name` ]; then
        git checkout $official_branch_name
        git pull origin
    else
        git checkout -b $official_branch_name $final_commit_hash
    fi
    update_image_version
    git add .
    git commit -m"chore: update image version in official branch"
    git push -u origin $official_branch_name

    git tag $official_tag
    git push origin tag $official_tag -f
    git checkout master
}

set_git_config
find_current_image_version "pkg/agent/datamodel/linux_sig_version.json"
create_image_bump_pr
cut_official_branch


#!/bin/bash
{{/* BCC/BPF-related error codes */}}
ERR_IOVISOR_KEY_DOWNLOAD_TIMEOUT=168 {{/* Timeout waiting to download IOVisor repo key */}}
ERR_IOVISOR_APT_KEY_TIMEOUT=169 {{/* Timeout waiting for IOVisor apt-key */}}
ERR_BCC_INSTALL_TIMEOUT=170 {{/* Timeout waiting for bcc install */}}
ERR_BPFTRACE_BIN_DOWNLOAD_FAIL=171 {{/* Failed to download bpftrace binary */}}
ERR_BPFTRACE_TOOLS_DOWNLOAD_FAIL=172 {{/* Failed to download bpftrace default programs */}}

BPFTRACE_DOWNLOADS_DIR="/opt/bpftrace/downloads"
UBUNTU_CODENAME=$(lsb_release -c -s)

installBpftrace() {
    local version="v0.9.4"
    local bpftrace_bin="bpftrace"
    local bpftrace_tools="bpftrace-tools.tar"
    local bpftrace_url="https://upstreamartifacts.azureedge.net/$bpftrace_bin/$version"
    local bpftrace_filepath="/usr/local/bin/$bpftrace_bin"
    local tools_filepath="/usr/local/share/$bpftrace_bin"
    if [[ -f "$bpftrace_filepath" ]]; then
        installed_version="$($bpftrace_bin -V | cut -d' ' -f2)"
        if [[ "$version" == "$installed_version" ]]; then
            return
        fi
        rm "$bpftrace_filepath"
        if [[ -d "$tools_filepath" ]]; then
            rm -r  "$tools_filepath"
        fi
    fi
    mkdir -p "$tools_filepath"
    install_dir="$BPFTRACE_DOWNLOADS_DIR/$version"
    mkdir -p "$install_dir"
    download_path="$install_dir/$bpftrace_tools"
    retrycmd_if_failure 30 5 60 curl -fSL -o "$bpftrace_filepath" "$bpftrace_url/$bpftrace_bin" || exit $ERR_BPFTRACE_BIN_DOWNLOAD_FAIL
    retrycmd_if_failure 30 5 60 curl -fSL -o "$download_path" "$bpftrace_url/$bpftrace_tools" || exit $ERR_BPFTRACE_TOOLS_DOWNLOAD_FAIL
    tar -xvf "$download_path" -C "$tools_filepath"
    chmod +x "$bpftrace_filepath"
    chmod -R +x "$tools_filepath/tools"
}

ensureGPUDrivers() {
    configGPUDrivers
    systemctlEnableAndStart nvidia-modprobe || exit $ERR_GPU_DRIVERS_START_FAIL
}

disableSystemdResolvedCache() {
    SERVICE_FILEPATH="/etc/systemd/system/resolv-uplink-override.service"
    touch ${SERVICE_FILEPATH}
    cat << EOF >> ${SERVICE_FILEPATH}
[Unit]
Description=Symlink /etc/resolv.conf to /run/systemd/resolve/resolv.conf
After=systemd-networkd.service

[Service]
Type=oneshot
ExecStart=/usr/bin/ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
RemainAfterExit=no

[Install]
RequiredBy=network-online.target kubelet.service
EOF

    systemctlEnableAndStart resolv-uplink-override || exit $ERR_SYSTEMCTL_START_FAIL

}

disableSystemdIptables() {
    systemctlDisableAndStop iptables || exit $ERR_DISBALE_IPTABLES

    # Mask the iptables service to prevent it from ever re-enabling and breaking pod networking.
    systemctl mask iptables || exit $ERR_DISBALE_IPTABLES
}


#!/bin/bash

echo "Sourcing tool_installs_mariner.sh"

installAscBaseline() {
   echo "Mariner TODO: installAscBaseline"
}

installBcc() {
    echo "Installing BCC tools..."
    dnf_makecache || exit $ERR_APT_UPDATE_TIMEOUT
    dnf_install 120 5 25 bcc-tools || exit $ERR_BCC_INSTALL_TIMEOUT
    echo "Installing BCC examples..."
    dnf_install 120 5 25 bcc-examples || exit $ERR_BCC_INSTALL_TIMEOUT
}

addMarinerNvidiaRepo() {
    if [[ $OS_VERSION == "2.0" ]]; then
        MARINER_NVIDIA_REPO_FILEPATH="/etc/yum.repos.d/mariner-nvidia.repo"
        touch "${MARINER_NVIDIA_REPO_FILEPATH}"
        cat << EOF > "${MARINER_NVIDIA_REPO_FILEPATH}"
[mariner-official-nvidia]
name=CBL-Mariner Official Nvidia 2.0 x86_64
baseurl=https://packages.microsoft.com/cbl-mariner/2.0/prod/nvidia/x86_64
gpgkey=file:///etc/pki/rpm-gpg/MICROSOFT-RPM-GPG-KEY file:///etc/pki/rpm-gpg/MICROSOFT-METADATA-GPG-KEY
gpgcheck=1
repo_gpgcheck=1
enabled=1
skip_if_unavailable=True
sslverify=1
EOF
    fi
}

forceEnableIpForward() {
    CONFIG_FILEPATH="/etc/sysctl.d/99-force-bridge-forward.conf"
    touch ${CONFIG_FILEPATH}
    cat << EOF >> ${CONFIG_FILEPATH}
    net.ipv4.ip_forward = 1
    net.ipv4.conf.all.forwarding = 1
    net.ipv6.conf.all.forwarding = 1
    net.bridge.bridge-nf-call-iptables = 1
EOF
}

# The default 99-dhcp-en config on Mariner attempts to assign an IP address
# to the eth1 virtual function device, which delays cluster setup by 2 minutes.
# This workaround makes it so that dhcp is only enabled on eth0.
setMarinerNetworkdConfig() {
    CONFIG_FILEPATH="/etc/systemd/network/99-dhcp-en.network"
    touch ${CONFIG_FILEPATH}
    cat << EOF > ${CONFIG_FILEPATH}
    [Match]
    Name=eth0

    [Network]
    DHCP=yes
    IPv6AcceptRA=no
EOF
# On Mariner 2.0 Marketplace images, the default systemd network config
# has an additional change that prevents Mariner from changing IP addresses
# every reboot
if [[ $OS_VERSION == "2.0" ]]; then
    cat << EOF >> ${CONFIG_FILEPATH}

    [DHCPv4]
    SendRelease=false
EOF
fi
}

listInstalledPackages() {
    rpm -qa
}

# disable and mask all UU timers/services
disableDNFAutomatic() {
    # Make sure dnf-automatic is running with the notify timer rather than the auto install timer
    systemctlEnableAndStart dnf-automatic-notifyonly.timer || exit $ERR_SYSTEMCTL_START_FAIL

    # Ensure the automatic install timer is disabled.
    # systemctlDisableAndStop adds .service to the end which doesn't work on timers.
    systemctl disable dnf-automatic-install.service || exit 1
    systemctl mask dnf-automatic-install.service || exit 1

    systemctl stop dnf-automatic-install.timer || exit 1
    systemctl disable dnf-automatic-install.timer || exit 1
    systemctl mask dnf-automatic-install.timer || exit 1
}

disableTimesyncd() {
    # Disable and Mask timesyncd to prevent it from interfering with chronyd's work
    systemctl stop systemd-timesyncd || exit 1
    systemctl disable systemd-timesyncd || exit 1
    systemctl mask systemd-timesyncd || exit 1

    # Before we return, make sure that chronyd is running
    systemctlEnableAndStart chronyd || exit $ERR_SYSTEMCTL_START_FAIL
}

# Regardless of UU mode, ensure check-restart is running
enableCheckRestart() {
  # Even if UU is disabled, we should still run check-restart so that kured
  # will work as expected if it is installed.
  # At 8:000:00 UTC check if a reboot-required package was installed
  # Touch /var/run/reboot-required if a reboot required package was installed.
  # This helps avoid a Mariner specific reboot check command in kured.
  systemctlEnableAndStart check-restart.timer || exit $ERR_SYSTEMCTL_START_FAIL
}

# There are several issues in default file permissions when trying to run AMA and ASA extensions.
# These will be resolved in an upcoming base image. Work around them here for now.
fixCBLMarinerPermissions() {
# Set the dmi/id/product_uuid permissions to 444 so that mdsd can read the VM unique ID
# https://github.com/Azure/WALinuxAgent/blob/develop/config/99-azure-product-uuid.rules
# Future base images will include this config in the WALinuxAgent package.
    CONFIG_FILEPATH="/etc/udev/rules.d/99-azure-product-uuid.rules"
    touch ${CONFIG_FILEPATH}
    cat << EOF > ${CONFIG_FILEPATH}
SUBSYSTEM!="dmi", GOTO="product_uuid-exit"
ATTR{sys_vendor}!="Microsoft Corporation", GOTO="product_uuid-exit"
ATTR{product_name}!="Virtual Machine", GOTO="product_uuid-exit"
TEST!="/sys/devices/virtual/dmi/id/product_uuid", GOTO="product_uuid-exit"

RUN+="/bin/chmod 0444 /sys/devices/virtual/dmi/id/product_uuid"

LABEL="product_uuid-exit"

EOF

# /etc/rsyslog.d is 750 but should be 755 so non root users can read the configs
# This occurs because the umask in Mariner is 0027 and packer_source.sh created the folder
# Future base images will already have rsyslog installed with 755 /etc/rsyslog.d
    chmod 755 /etc/rsyslog.d
}

enableMarinerKata() {
    # Enable the mshv boot path
    sudo sed -i -e 's@menuentry "CBL-Mariner"@menuentry "Dom0" {\n    search --no-floppy --set=root --file /EFI/Microsoft/Boot/bootmgfw.efi\n        chainloader /EFI/Microsoft/Boot/bootmgfw.efi\n}\n\nmenuentry "CBL-Mariner"@'  /boot/grub2/grub.cfg

    # kata-osbuilder-generate is responsible for triggering the kata-osbuilder.sh script, which uses
    # dracut to generate an initrd for the nested VM using binaries from the Mariner host OS.
    systemctlEnableAndStart kata-osbuilder-generate
}

activateNfConntrack() {
    # explicitly activate nf_conntrack module so associated sysctls can be properly set
    echo nf_conntrack >> /etc/modules-load.d/contrack.conf
}

installFIPS() {

    echo "Installing FIPS..."

    # Install necessary rpm pacakages
    dnf_install 120 5 25 grubby || exit $ERR_APT_INSTALL_TIMEOUT
    dnf_install 120 5 25 dracut-fips || exit $ERR_APT_INSTALL_TIMEOUT

    # Add the boot= cmd line parameter if the boot dir is not the same as the root dir
    boot_dev="$(df /boot/ | tail -1 | cut -d' ' -f1)"
    root_dev="$(df / | tail -1 | cut -d' ' -f1)"
    if [ ! "$root_dev" == "$boot_dev" ]; then
        boot_uuid="UUID=$(blkid $boot_dev -s UUID -o value)"

        # Enable FIPS mode and modify boot directory
        if grub2-editenv - list | grep -q kernelopts;then
                grub2-editenv - set "$(grub2-editenv - list | grep kernelopts) fips=1 boot=$boot_uuid"
        else
                grubby --update-kernel=ALL --args="fips=1 boot=$boot_uuid"
        fi
    fi

}


#!/bin/bash
{{/* FIPS-related error codes */}}
ERR_UA_TOOLS_INSTALL_TIMEOUT=180 {{/* Timeout waiting for ubuntu-advantage-tools install */}}
ERR_ADD_UA_APT_REPO=181 {{/* Error to add UA apt repository */}}
ERR_AUTO_UA_ATTACH=182 {{/* Error to auto UA attach */}}
ERR_UA_DISABLE_LIVEPATCH=183 {{/* Error to disable UA livepatch */}}
ERR_UA_ENABLE_FIPS=184 {{/* Error to enable UA FIPS */}}
ERR_UA_DETACH=185 {{/* Error to detach UA */}}
ERR_LINUX_HEADER_INSTALL_TIMEOUT=186 {{/* Timeout to install linux header */}}
ERR_STRONGSWAN_INSTALL_TIMEOUT=187 {{/* Timeout to install strongswan */}}

ERR_NTP_INSTALL_TIMEOUT=10 {{/*Unable to install NTP */}}
ERR_NTP_START_TIMEOUT=11 {{/* Unable to start NTP */}}
ERR_STOP_OR_DISABLE_SYSTEMD_TIMESYNCD_TIMEOUT=12 {{/* Timeout waiting for systemd-timesyncd stop */}}
ERR_STOP_OR_DISABLE_NTP_TIMEOUT=13 {{/* Timeout waiting for ntp stop */}}
ERR_CHRONY_INSTALL_TIMEOUT=14 {{/*Unable to install CHRONY */}}
ERR_CHRONY_START_TIMEOUT=15 {{/* Unable to start CHRONY */}}

echo "Sourcing tool_installs_ubuntu.sh"

installAscBaseline() {
   echo "Installing ASC Baseline tools..."
   ASC_BASELINE_TMP=/home/packer/asc-baseline.deb
   retrycmd_if_failure_no_stats 120 5 25 dpkg -i $ASC_BASELINE_TMP || exit $ERR_APT_INSTALL_TIMEOUT
   sudo cp /opt/microsoft/asc-baseline/baselines/*.xml /opt/microsoft/asc-baseline/
   cd /opt/microsoft/asc-baseline
   sudo ./ascbaseline -d .
   sudo ./ascremediate -d . -m all
   sudo ./ascbaseline -d . | grep -B2 -A6 "FAIL"
   cd -
   echo "Check UDF"
   cat /etc/modprobe.d/*.conf | grep udf
   echo "Finished Setting up ASC Baseline"
}

installBcc() {
    echo "Installing BCC tools..."
    wait_for_apt_locks
    apt_get_update || exit $ERR_APT_UPDATE_TIMEOUT
    VERSION=$(grep DISTRIB_RELEASE /etc/*-release| cut -f 2 -d "=")
    if [[ "${VERSION}" == "22.04" ]]; then
        apt_get_install 120 5 300 build-essential git bison cmake flex libedit-dev libllvm14 llvm-14-dev libclang-14-dev python3 zlib1g-dev libelf-dev python3-distutils libfl-dev || exit $ERR_BCC_INSTALL_TIMEOUT
    else
        apt_get_install 120 5 300 build-essential git bison cmake flex libedit-dev libllvm6.0 llvm-6.0-dev libclang-6.0-dev python zlib1g-dev libelf-dev python3-distutils libfl-dev || exit $ERR_BCC_INSTALL_TIMEOUT
    fi

    mkdir -p /tmp/bcc
    pushd /tmp/bcc
    git clone https://github.com/iovisor/bcc.git
    mkdir bcc/build; cd bcc/build
    git checkout v0.24.0
    cmake .. || exit 1
    make
    sudo make install || exit 1
    cmake -DPYTHON_CMD=python3 .. || exit 1 # build python3 binding
    pushd src/python/
    make
    sudo make install || exit 1
    popd
    popd
    # we explicitly do not remove build-essential or git
    # these are standard packages we want to keep, they should usually be in the final build anyway.
    # only ensuring they are installed above.
    if [[ "${VERSION}" == "22.04" ]]; then
        apt_get_purge 120 5 300 bison cmake flex libedit-dev libllvm14 llvm-14-dev libclang-14-dev zlib1g-dev libelf-dev libfl-dev || exit $ERR_BCC_INSTALL_TIMEOUT
    else
        apt_get_purge 120 5 300 bison cmake flex libedit-dev libllvm6.0 llvm-6.0-dev libclang-6.0-dev zlib1g-dev libelf-dev libfl-dev || exit $ERR_BCC_INSTALL_TIMEOUT
    fi
}

disableNtpAndTimesyncdInstallChrony() {
    # Disable systemd-timesyncd
    systemctl_stop 20 30 120 systemd-timesyncd || exit $ERR_STOP_OR_DISABLE_SYSTEMD_TIMESYNCD_TIMEOUT
    systemctl disable systemd-timesyncd || exit $ERR_STOP_OR_DISABLE_SYSTEMD_TIMESYNCD_TIMEOUT

    # Disable ntp if present
    status=$(systemctl show -p SubState --value ntp)
    if [ $status == 'dead' ]; then
        echo "ntp is removed, no need to disable"
    else
        systemctl_stop 20 30 120 ntp || exit $ERR_STOP_OR_DISABLE_NTP_TIMEOUT
        systemctl disable ntp || exit $ERR_STOP_OR_DISABLE_NTP_TIMEOUT
    fi

    # Install chrony
    apt_get_update || exit $ERR_APT_UPDATE_TIMEOUT
    apt_get_install 20 30 120 chrony || exit $ERR_CHRONY_INSTALL_TIMEOUT
    cat > /etc/chrony/chrony.conf <<EOF
# Welcome to the chrony configuration file. See chrony.conf(5) for more
# information about usuable directives.

# This will use (up to):
# - 4 sources from ntp.ubuntu.com which some are ipv6 enabled
# - 2 sources from 2.ubuntu.pool.ntp.org which is ipv6 enabled as well
# - 1 source from [01].ubuntu.pool.ntp.org each (ipv4 only atm)
# This means by default, up to 6 dual-stack and up to 2 additional IPv4-only
# sources will be used.
# At the same time it retains some protection against one of the entries being
# down (compare to just using one of the lines). See (LP: #1754358) for the
# discussion.
#
# About using servers from the NTP Pool Project in general see (LP: #104525).
# Approved by Ubuntu Technical Board on 2011-02-08.
# See http://www.pool.ntp.org/join.html for more information.
#pool ntp.ubuntu.com        iburst maxsources 4
#pool 0.ubuntu.pool.ntp.org iburst maxsources 1
#pool 1.ubuntu.pool.ntp.org iburst maxsources 1
#pool 2.ubuntu.pool.ntp.org iburst maxsources 2

# This directive specify the location of the file containing ID/key pairs for
# NTP authentication.
keyfile /etc/chrony/chrony.keys

# This directive specify the file into which chronyd will store the rate
# information.
driftfile /var/lib/chrony/chrony.drift

# Uncomment the following line to turn logging on.
#log tracking measurements statistics

# Log files location.
logdir /var/log/chrony

# Stop bad estimates upsetting machine clock.
maxupdateskew 100.0

# This directive enables kernel synchronisation (every 11 minutes) of the
# real-time clock. Note that it canâ€™t be used along with the 'rtcfile' directive.
rtcsync

# Settings come from: https://docs.microsoft.com/en-us/azure/virtual-machines/linux/time-sync
refclock PHC /dev/ptp0 poll 3 dpoll -2 offset 0
makestep 1.0 -1
EOF

    systemctlEnableAndStart chrony || exit $ERR_CHRONY_START_TIMEOUT
}

installFIPS() {
    echo "Installing FIPS..."
    wait_for_apt_locks

    # installing fips kernel doesn't remove non-fips kernel now, purge current linux-image-azure
    echo "purging linux-image-azure..."
    linuxImages=$(apt list --installed | grep linux-image- | grep azure | cut -d '/' -f 1)
    for image in $linuxImages; do
        echo "Removing non-fips kernel ${image}..."
        if [[ ${image} != "linux-image-$(uname -r)" ]]; then
            apt_get_purge 5 10 120 ${image} || exit 1
        fi
    done

    echo "enabling ua fips-updates..."
    retrycmd_if_failure 5 10 1200 echo y | ua enable fips-updates || exit $ERR_UA_ENABLE_FIPS
}

relinkResolvConf() {
    # /run/systemd/resolve/stub-resolv.conf contains local nameserver 127.0.0.53
    # remove this block after toggle disable-1804-systemd-resolved is enabled prod wide
    resolvconf=$(readlink -f /etc/resolv.conf)
    if [[ "${resolvconf}" == */run/systemd/resolve/stub-resolv.conf ]]; then
        unlink /etc/resolv.conf
        ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
    fi
}

listInstalledPackages() {
    apt list --installed
}

autoAttachUA() {
    echo "auto attaching ua..."
    retrycmd_if_failure 5 10 120 ua auto-attach || exit $ERR_AUTO_UA_ATTACH

    echo "disabling ua livepatch..."
    retrycmd_if_failure 5 10 300 echo y | ua disable livepatch
}

detachAndCleanUpUA() {
    echo "detaching ua..."
    retrycmd_if_failure 5 10 120 printf "y\nN" | ua detach || $ERR_UA_DETACH

    # now that the ESM/FIPS packages are installed, clean up apt settings in the vhd,
    # the VMs created on customers' subscriptions don't have access to UA repo
    rm -f /etc/apt/trusted.gpg.d/ubuntu-advantage-esm-apps.gpg
    rm -f /etc/apt/trusted.gpg.d/ubuntu-advantage-esm-infra-trusty.gpg
    rm -f /etc/apt/trusted.gpg.d/ubuntu-advantage-fips.gpg
    rm -f /etc/apt/sources.list.d/ubuntu-esm-apps.list
    rm -f /etc/apt/sources.list.d/ubuntu-esm-infra.list
    rm -f /etc/apt/sources.list.d/ubuntu-fips-updates.list
    rm -f /etc/apt/auth.conf.d/*ubuntu-advantage
    apt_get_update || exit $ERR_APT_UPDATE_TIMEOUT
}


#!/bin/bash

cd Scenarios/Baseline/bicep

# Registering Resource Providers
az provider register --namespace Microsoft.Network
az provider register --namespace Microsoft.Compute
az provider register --namespace Microsoft.ContainerInstance
az provider register --namespace Microsoft.KeyVault
az provider register --namespace Microsoft.ManagedIdentity
az provider register --namespace Microsoft.Storage
az provider register --namespace Microsoft.HealthcareApis
az provider register --namespace Microsoft.Diagnostics
az provider register --namespace Microsoft.ContainerRegistry
az provider register --namespace Microsoft.Web

# Checking registration status
az provider show --namespace Microsoft.Network
az provider show --namespace Microsoft.Compute
az provider show --namespace Microsoft.ContainerInstance
az provider show --namespace Microsoft.KeyVault
az provider show --namespace Microsoft.ManagedIdentity
az provider show --namespace Microsoft.Storage
az provider show --namespace Microsoft.HealthcareApis
az provider show --namespace Microsoft.Diagnostics
az provider show --namespace Microsoft.ContainerRegistry
az provider show --namespace Microsoft.Web

# To see the resource types for a resource provider
az provider show --namespace Microsoft.Network --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.Compute --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.ContainerInstance --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.KeyVault --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.ManagedIdentity --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.Storage --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.HealthcareApis --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.Diagnostics --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.ContainerRegistry --query "resourceTypes[*].resourceType" --out table
az provider show --namespace Microsoft.Web --query "resourceTypes[*].resourceType" --out table

# AZ CLI
# 01-Network-Hub
# *** The JumpBox VM User Name and Password will be auto generated and will be saved at the Key Vault under HUB Resource Group
# You have to give yourself access in order to read the both Secrets with username and password
az deployment sub create -n "ESLZ-HUB-AHDS" -l "EastUS" -f 01-Network-Hub/main.bicep -p 01-Network-Hub/parameters-main.json
az deployment sub create -n "ESLZ-AHDS-HUB-UDR" -l "EastUS" -f 01-Network-Hub/updateUDR.bicep -p 01-Network-Hub/parameters-updateUDR.json
az deployment sub create -n "ESLZ-HUB-VM" -l "EastUS" -f 01-Network-Hub/deploy-vm.bicep -p 01-Network-Hub/parameters-deploy-vm.json

# 02-Network-LZ
# Bash
rgSpoke=ESLZ-AHDS-SPOKE
# Powershell
$rgSpoke="ESLZ-AHDS-SPOKE"
az deployment sub create -n "ESLZ-Spoke-AHDS" -l "EastUS" -f 02-Network-LZ/main.bicep -p 02-Network-LZ/parameters-main.json -p rgName=$rgSpoke

# 03-AHDS
# ** Important Note ** Review (or Update) 03-AHDS/parameters-main.json file to make sure APIMName on line 36 is globally unique and not used by any one else
# ** and that APIM name should match Application Gateway backend pool value (primaryBackendEndFQDN) on line 81.
az deployment sub create -n "ESLZ-AHDS" -l "EastUS" -f 03-AHDS/main.bicep -p 03-AHDS/parameters-main.json -p rgName=$rgSpoke -p appGatewayFQDN="api.example.com"

# Victor ToDo: Prompt for Region and Application Gateway FQDN
# Victor ToDo: Print the Public IP of the Application Gateway and add a statement saying they must create a DNS record for this IP

# Full Cleanup
# Delete Resource Groups
# az group delete -n ESLZ-AHDS-HUB -y --no-wait
# az group delete -n ESLZ-AHDS-SPOKE -y --no-wait
# az apim deletedservice purge --service-name APIM-AHDS --location EastUS
# # Delete Deployments
# az deployment sub delete -n ESLZ-HUB-AHDS -y --no-wait
# az deployment sub delete -n ESLZ-AHDS-HUB-UDR --no-wait
# az deployment sub delete -n ESLZ-HUB-VM --no-wait
# az deployment sub delete -n ESLZ-Spoke-AHDS --no-wait
# az deployment sub delete -n ESLZ-AHDS-Supporting --no-wait


#!/bin/bash

###################
# Prompt and Validating Azure Region
###################
read -p "Inform Azure Region to be deployed? " answerAzRegion
azRegions=$(az account list-locations --query '[].name' -o tsv)
if [[ $azRegions == *$answerAzRegion* ]]; then
  echo "Azure Region found: $answerAzRegion"
else
  echo "Region $answerAzRegion Not found"
  echo ""
  echo "Use one of the available Azure Regions:"
  echo $azRegions
  exit;
fi

###################
# Prompt Azure Aplication Gateway FQDN
###################
read -p "Inform Azure Application Gateway FQDN? " answerAppGWFQDN
echo "Azure Aplication Gateway FQDN: $answerAppGWFQDN"

###################
# List of required azure providers
###################
azProviders=("Microsoft.Network" "Microsoft.Compute" "Microsoft.ContainerInstance" "Microsoft.KeyVault" "Microsoft.ManagedIdentity" "Microsoft.Storage" "Microsoft.HealthcareApis" "Microsoft.Diagnostics" "Microsoft.ContainerRegistry" "Microsoft.Web")

###################
# Checking if a required provider is not registered and save in array azProvidersNotRegistered
###################
azProvidersNotRegistered=()
for provider in "${azProviders[@]}"
do
  registrationState=$(az provider show --namespace $provider --query "[registrationState]" --output tsv)
  if [ "$registrationState" != "Registered" ]; then
    #echo "Found an Azure Resource Provider not registred: $provider"
    azProvidersNotRegistered+=($provider)
    #echo "${azProvidersNotRegistered[@]}"
  fi
done

###################
# Registering all missing required Azure providers
###################
if (( ${#azProvidersNotRegistered[@]} > 0 )); then
  echo "Registering required Azure Providers"
  echo ""
  for provider in "${azProvidersNotRegistered[@]}"
  do
    echo "Registering Azure Provider: $provider"
    az provider register --namespace $provider
  done
fi
echo ""

###################
# Function to remove an element of an array
###################
remove_array_element_byname(){
    index=0
    name=$1[@]
    param2=$2
    fun_arr=("${!name}")

    for element in "${fun_arr[@]}"
    do
      if [[ $element == $param2 ]]; then
        foundindex=$index
      fi
      index=$(($index + 1))
    done
    unset fun_arr[$foundindex]
    ret_val=("${fun_arr[@]}")
}

###################
# Checking the status of missing Azure Providers
###################
if (( ${#azProvidersNotRegistered[@]} > 0 )); then
  copy_azProvidersNotRegistered=("${azProvidersNotRegistered[@]}")
  while (( ${#copy_azProvidersNotRegistered[@]} > 0 ))
  do
    elementcount=0
    for provider in "${azProvidersNotRegistered[@]}"
    do
      registrationState=$(az provider show --namespace $provider --query "[registrationState]" --output tsv)
      if [ "$registrationState" != "Registered" ]; then
        echo "Waiting for Azure provider $provider ..."
      else
        echo "Azure provider $provider registered!"
        remove_array_element_byname copy_azProvidersNotRegistered $provider
        ret_remove_array_element_byname=("${ret_val[@]}")
        copy_azProvidersNotRegistered=("${ret_remove_array_element_byname[@]}")
      fi
    done
    azProvidersNotRegistered=("${copy_azProvidersNotRegistered[@]}")
    echo ""

    echo "Amount of providers waiting to be registered: ${#azProvidersNotRegistered[@]}"
    echo "Waiting 10 seconds to check the missing providers again"
    echo "############################################################"
    sleep 10
    clear
  done
  echo "Done registering required Azure Providers"
fi

# End of working part
#=======================================================================

######################################################
######################################################
######################################################
#### From this part bellow is working in progress ####
######################################################
######################################################
######################################################

# AZ CLI
# 01-Network-Hub
# *** The JumpBox VM User Name and Password will be auto generated and will be saved at the Key Vault under HUB Resource Group
# You have to give yourself access in order to read the both Secrets with username and password
az deployment sub create -n "ESLZ-HUB-AHDS" -l $answerAzRegion -f 01-Network-Hub/main.bicep -p 01-Network-Hub/parameters-main.json
az deployment sub create -n "ESLZ-AHDS-HUB-UDR" -l $answerAzRegion -f 01-Network-Hub/updateUDR.bicep -p 01-Network-Hub/parameters-updateUDR.json
az deployment sub create -n "ESLZ-HUB-VM" -l $answerAzRegion -f 01-Network-Hub/deploy-vm.bicep -p 01-Network-Hub/parameters-deploy-vm.json

# 02-Network-LZ
rgSpoke=ESLZ-AHDS-SPOKE
az deployment sub create -n "ESLZ-Spoke-AHDS" -l $answerAzRegion -f 02-Network-LZ/main.bicep -p 02-Network-LZ/parameters-main.json -p rgName=$rgSpoke

# 03-AHDS
# ** Important Note ** Review (or Update) 03-AHDS/parameters-main.json file to make sure APIMName on line 36 is globally unique and not used by any one else
# ** and that APIM name should match Application Gateway backend pool value (primaryBackendEndFQDN) on line 81.
# az deployment group create -g "ESLZ-HUB" -n "test-public-ip" -f test.bicep --query "properties.outputs.publicipappgw.value" -o tsv
publicipappgw=$(az deployment sub create -n "ESLZ-AHDS" -l $answerAzRegion -f 03-AHDS/main.bicep -p 03-AHDS/parameters-main.json -p rgName=$rgSpoke -p appGatewayFQDN=$answerAppGWFQDN --query "properties.outputs.publicipappgw.value" -o tsv)
echo "Please create a DNS record for the Application Gateway Public IP: $publicipappgw with the FQDN: $answerAppGWFQDN"

# Victor ToDo: Prompt for Region and Application Gateway FQDN - Done
# Victor ToDo: Print the Public IP of the Application Gateway and add a statement saying they must create a DNS record for this IP

echo Done


#!/bin/bash

# View extension logs by running
# sudo cat /var/log/azure/Microsoft.OSTCExtensions.CustomScriptForLinux/1.5.2.2/extension.log
# (the version may be different)

user=`awk -F: '$3 >= 1000 {print $1, $6}' /etc/passwd | tail -n 1`
echo $user
username=${user% *}
homedir=${user#* }

basedir=$PWD

pushd $homedir/notebooks
rm -rf *
unzip $basedir/Notebooks.zip
chown $username:$username *
popd

touch $homedir/NotebookEnvironmentVariablesConfig.json
cat << EOF > $homedir/NotebookEnvironmentVariablesConfig.json
{
	"DataIngestion" : {
		"STORAGE_ACCOUNT_NAME" : "$3",
		"STORAGE_ACCOUNT_KEY" : "$4",
		"TELEMETRY_CONTAINER_NAME" : "telemetry",
		"LOG_TABLE_NAME" : "Logs",
		"DATA_ROOT_FOLDER" : "$homedir"
	}
}
EOF

mv $basedir/spark-avro_2.11-4.0.0.jar /dsvm/tools/spark/current/jars/

source /anaconda/bin/activate py35

pip install --upgrade pip

#to install ggplot in DSVM uncomment the following
#conda remove -n py35 -y pandas
#conda install -n py35 -y pandas==0.20.3
#conda install -n py35 -y -c conda-forge ggplot

conda install -n py35 -y python-snappy
pip install imblearn
pip install --upgrade --extra-index-url https://azuremlsdktestpypi.azureedge.net/sdk-release/Preview/E7501C02541B433786111FE8E140CAA1 azureml-sdk
pip install --upgrade databricks-cli

touch $homedir/.databrickscfg
cat << EOF > $homedir/.databrickscfg
[DEFAULT]
host = $1
token = $2
EOF


#!/bin/bash

convert -density 150 -background white -alpha remove data_flow.pdf -quality 90 data_flow.png
convert -density 90 -background white -alpha remove data_collection.pdf -quality 90 data_collection.png
convert -density 150 -background white -alpha remove modeling.pdf -quality 90 modeling.png
convert -density 90 -background white -alpha remove productionalization_feature_engineering.pdf -quality 90 productionalization_feature_engineering.png
convert -density 90 -background white -alpha remove productionalization_scoring.pdf -quality 90 productionalization_scoring.png

cp data_collection.png modeling.png productionalization_feature_engineering.png productionalization_scoring.png data_flow.png ../../docs/img/


#!/bin/bash
wget -O spark-logo.png https://spark.apache.org/images/spark-logo-trademark.png
wget -O kafka-logo.png https://svn.apache.org/repos/asf/kafka/site/logos/kafka-logo-no-text.png
wget -O event-hub.svg https://worldvectorlogo.com/download/azure-event-hub.svg
wget -O iot-hub.svg "https://azure.microsoft.com/svghandler/iot-hub/?width=600&height=600"
wget -O databricks.svg "https://azure.microsoft.com/svghandler/databricks?width=600&height=600"
wget -O table-storage.svg "https://docs.microsoft.com/en-us/azure/media/index/storage.svg"
wget -O stream-analytics.svg "https://azure.microsoft.com/svghandler/stream-analytics?width=600&height=600"
wget -O sql-database.svg "https://azure.microsoft.com/svghandler/sql-database?width=600&height=600"
wget -O cosmos-db.svg "https://azure.microsoft.com/svghandler/cosmos-db?width=600&height=600"
wget -O webjob.png https://developersde.blob.core.windows.net/usercontent/2018/4/15734_webjobs.png
wget -O aks.png https://stephanefrechette.com/wp-content/uploads/2018/04/Azure-Container-Service_COLOR-300x300.png
wget -O dashboard.png https://www.freeiconspng.com/uploads/dashboard-icon-3.png
wget -O blob-storage.png https://azureautomation950740325.files.wordpress.com/2018/02/azure-storage-blob.png
wget -O python-logo.png https://upload.wikimedia.org/wikipedia/commons/thumb/c/c3/Python-logo-notext.svg/2000px-Python-logo-notext.svg.png
wget -O dsvm.svg "https://azure.microsoft.com/svghandler/virtual-machines-data-science-virtual-machines/?width=600&height=600"
wget -O databricks.png "https://databricks.com/wp-content/themes/databricks/assets/images/header_logo.png"
wget -O file-storage.png "https://ievgensaxblog.files.wordpress.com/2017/07/azure-storage-files.png"
wget -O aml-workbench.svg "http://azureml.azureedge.net/content/apphome/media/AML-Logo.svg"
wget -O model.png "https://vc4prod.blob.core.windows.net/catalog/Recommendations/Machine-Learning.png"
wget -O jupyter.png "http://jupyter.org/assets/try/jupyter.png"

convert -density 300 event-hub.svg event-hub.png
convert -density 300 iot-hub.svg iot-hub.png
convert -density 300 databricks.svg databricks.png
convert -density 300 table-storage.svg table-storage.png
convert -density 300 stream-analytics.svg stream-analytics.png
convert -density 300 sql-database.svg sql-database.png
convert -density 300 cosmos-db.svg cosmos-db.png
convert -density 300 dsvm.svg dsvm.png
convert -density 300 aml-workbench.svg aml-workbench.png


#!/bin/bash
# Install IOT Edge Runtime and register the edge device

# HOME is not set when the extension runs, so set it now
export HOME=$2

usermod -aG docker $2

source /anaconda/bin/activate root
pip install -U azure-iot-edge-runtime-ctl
iotedgectl setup --connection-string $1 --auto-cert-gen-force-no-passwords
iotedgectl start

chmod 644 /etc/azure-iot-edge/config.json


#!/bin/bash

set -e

# Please Add
# Your AKS Cluster Subscription:
sub="<YOUR-SUBSCRIPTION-ID>"
# Your AKS Cluster Resource Group:
rg="<YOUR-RESOURCE-GROUP-NAME>"
# Your AKS Cluster Name:
cn="<YOUR-AKS-CLUSTER-NAME>"

# Set AKS kubectl creds
az account set --subscription $sub
az aks get-credentials --resource-group $rg --name $cn

mcrg=$(az aks show --name $cn --resource-group $rg --query "nodeResourceGroup" -o tsv)
echo "MC RG $mcrg"

# Check each nodepool individually
for np in $(az aks nodepool list --cluster-name $cn --resource-group $rg --query "[].name" -o tsv)
do
    echo "Going to cleanup for node pool $np"
    # find total nodes
    totalNodes=$(kubectl get nodes -l kubernetes.azure.com/agentpool=$np -o wide | grep $np | wc -l)
    echo "Total nodes of node pool $np is $totalNodes"
    nodeList=$(kubectl get nodes -l kubernetes.azure.com/agentpool=$np -o wide | grep "5.4.0-1095-azure" | awk '{print $1}')
    echo "node list: $nodeList"

    autoScalerEnabled=$(az aks nodepool show --cluster-name $cn --resource-group $rg --name $np --query "enableAutoScaling" -o tsv)
    echo "auto-scaler enabled: $autoScalerEnabled"

    if [ "$autoScalerEnabled" != "true" ]; then
        echo "Scale cluster by 1 node for removal of bad node"
        az aks scale --resource-group $rg --name $cn --node-count $((totalNodes+1)) --nodepool-name $np
    fi

    # Clean up each node with bad kernel
    for ns in $nodeList
    do
        echo "Going to cleanup for node $ns"

        echo "Cordoning $ns"
        kubectl cordon $ns

        echo "Draining $ns"
        kubectl drain $ns --ignore-daemonsets --delete-emptydir-data

        vmssName=$(kubectl get node $ns -o yaml | grep "providerID" | awk -F '/' '{print $(NF-2)}')
        instanceId=$(kubectl get node $ns -o yaml | grep "providerID" | awk -F '/' '{print $NF}')
        echo "Re-image $vmssName/$instanceId"
        az vmss reimage --instance-id $instanceId --name $vmssName --resource-group $mcrg

        echo "Uncordoning $ns"
        kubectl uncordon $ns

        echo "Cleanup for $ns ($vmssName/$instanceId) done"
    done

    if [ "$autoScalerEnabled" != "true" ]; then
        echo "Scale cluster to $totalNodes nodes"
        az aks scale --resource-group $rg --name $cn --node-count $totalNodes --nodepool-name $np
    fi
done


#### First, set the values of the variables (SETTING ALL VARIABLES section)
#### Then run the rest of the script (SCRIPT EXECUTION section)

## Note: if your value set contains spaces please enclose the value in double quotes.
## Also, please make sure to run the following commands from same command directory
## as the location of LvLUpAutoscalingLoadTest.jmx in order to let the "-F file=" parameter
## load the jmx content correctly (use cd to set your command directory) </br>

### *** BEGIN - SETTING ALL VARIABLES
directory_of_LvLUpAutoscalingLoadTestjmx="[cd path of LvLUpAutoscalingLoadTest.jmx]"
subscription=[your subscription id used in Module 1]
rg_name=[name of resource group created in Module 1]
servicebus_namespace=[name of your azure service bus namespace]
azure_key_vault=[your azure key vault name created in Module 1]
alt=[your azure load testing instance name created in Module 1]
## set the value of the azure service bus endpoint uri to test - e.g.: "asbnamespace.servicebus.windows.net" - no http(s) prefix
asb_endpoint_uri=[your asb uri]

### *** END - SETTING ALL VARIABLES

### BEGIN - SCRIPT EXECUTION - copy, paste, run

# Unless you are already logged in, 'az login'  will open a browser window to let you authenticate. Once authenticated, the script will continue running
cd "$directory_of_LvLUpAutoscalingLoadTestjmx"
az login
az account set -s $subscription
asb_queue=orders
asb_queue_key_name=alt-send

asb_uri="https://"$servicebus_namespace".servicebus.windows.net/"$asb_queue"/messages"
asb_queue_primary_key=$(az servicebus queue authorization-rule keys list -g $rg_name --namespace-name $servicebus_namespace --queue-name $asb_queue --name $asb_queue_key_name --query primaryKey -o tsv)
echo $asb_queue_primary_key

get_sas_token() {
    local ASB_URI=$1
    local SHARED_ACCESS_KEY_NAME=$2
    local SHARED_ACCESS_KEY=$3
    local EXPIRY=${EXPIRY:=$((60 * 60 * 8))} # Setting default token expiration at 8 hours

    local ENCODED_URI=$(echo -n $ASB_URI | jq -s -R -r @uri)
    local TTL=$(($(date +%s) + $EXPIRY))
    local UTF8_SIGNATURE=$(printf "%s\n%s" $ENCODED_URI $TTL | iconv -t UTF-8)

    local HASH=$(echo -n "$UTF8_SIGNATURE" | openssl sha256 -hmac $SHARED_ACCESS_KEY -binary | base64)
    local ENCODED_HASH=$(echo -n $HASH | jq -s -R -r @uri)

    echo -n "SharedAccessSignature sr=$ENCODED_URI&sig=$ENCODED_HASH&se=$TTL&skn=$SHARED_ACCESS_KEY_NAME"
}

sastoken=$(get_sas_token $asb_uri $asb_queue_key_name $asb_queue_primary_key)
secretvalue=$sastoken
secret_name="sastoken"

## get current user upn
upn=$(az ad signed-in-user show --query userPrincipalName -o tsv)
## add access policy for current user to azure key vault
az keyvault set-policy -g $rg_name -n $azure_key_vault --secret-permissions all --upn $upn

# this will set the secret expiration in 8 hours from current date/time
expiredate=$(date +%Y-%m-%d'T'%H:%M:%S'Z' -d "$(date) + 8 hours")

az keyvault secret set --name $secret_name --vault-name $azure_key_vault --value "$secretvalue" --subscription $subscription --expires "$expiredate"

secret_uri=$(az keyvault secret show --name $secret_name --vault-name $azure_key_vault --query id -o tsv)
$secret_uri

## Default value already set for the load test instance that we are going to create. Feel free to keep it as-is or modify
testname="LvlUpNewTest"

## Values are already set. No need to change. Modify only if you would like to use different ones.
testdate=$(date)
testdescription="Level Up Azure Load Testing Instance - Created on: $testdate"

## constant values - do not change unless instructed by trainer
arm_apiversion="api-version=2021-12-01-preview"
alt_apiversion="api-version=2021-07-01-preview"

## formatting resourceId string based on submitted variables
resourceId="/subscriptions/"$subscription"/resourcegroups/"$rg_name"/providers/microsoft.loadtestservice/loadtests/"$alt

## formatting management endpoint url based on submitted variables
armEndpoint="https://management.azure.com"$resourceId"?$arm_apiversion"

accessToken=$(az account get-access-token --resource "https://management.core.windows.net" --query accessToken -o tsv)

hdr_authorization="Authorization: Bearer $accessToken"
hdr_content_type="Content-Type: application/json"

dataPlaneURI=$(curl -G -H "$hdr_authorization" -H "$hdr_content_type" $armEndpoint | jq -r .properties.dataPlaneURI)

# utility function to create random guid
uuid()
{
    local N B C='89ab'

    for (( N=0; N < 16; ++N ))
    do
        B=$(( $RANDOM%256 ))

        case $N in
            6)
                printf '4%x' $(( B%16 ))
                ;;
            8)
                printf '%c%x' ${C:$RANDOM%${#C}:1} $(( B%16 ))
                ;;
            3 | 5 | 7 | 9)
                printf '%02x-' $B
                ;;
            *)
                printf '%02x' $B
                ;;
        esac
    done

    echo
}

testId=$(uuid) # do not change

# get access token for Azure Load Testing API endpoint
accessToken=$(az account get-access-token --resource "https://loadtest.azure-dev.com" --query accessToken -o tsv)

## Number of Instances to run the test
EngineInstancesCount=1

## random id for the metrics - no need to change
passFailMetrics1Guid=$(uuid)
passFailMetrics2Guid=$(uuid)

#
testJson=$(cat <<EOF
{
    "resourceId": "$resourceId",
    "testId": "$testId",
    "description": "$testdescription",
    "displayName": "$testname",
    "loadTestConfig": {
        "engineSize": "m",
        "engineInstances": $EngineInstancesCount
    },
    "secrets": {
        "sastoken": {
        "value": "$secret_uri",
        "type": "AKV_SECRET_URI"
        }
    },
    "environmentVariables": {
        "endpoint_uri": "$asb_endpoint_uri"
    },
    "passFailCriteria": {
        "passFailMetrics": {
            "$passFailMetrics1Guid": {
                "clientmetric": "response_time_ms",
                "aggregate": "avg",
                "condition": ">",
                "value": 500,
                "action": "continue",
                "result": null,
                "actualValue": 0
            },
            "$passFailMetrics2Guid": {
                "clientmetric": "error",
                "aggregate": "percentage",
                "condition": ">",
                "value": 30,
                "action": "continue",
                "result": null,
                "actualValue": 0
            }
        }
    }
}
EOF
)

hdr_authorization="Authorization: Bearer $accessToken"
hdr_content_type="Content-Type: application/merge-patch+json"

## set the Create Load Test API Endpoint URI
loadCreateTestURI="https://"$dataPlaneURI"/loadtests/"$testId"?$alt_apiversion"
loadCreateTestResponse=$(curl $loadCreateTestURI -X PATCH -H "$hdr_authorization" -H "$hdr_content_type" -d "$testJson")

echo "****** Begin - Create Test API Response"
echo $loadCreateTestResponse
echo "****** End - Create Test API Response"

### The previous command should result in a json output with the properties of the Test instance just created.
### If you see a json output and no error (or null) value - process is working fine

## Let's wait for the creation of the Test to be completed
sleep 5

fileid=$(uuid)
hdr_authorization="Authorization: Bearer $accessToken"
validateUploadFileTestURI="https://$dataPlaneURI/file/$fileid:validate?"$alt_apiversion
validateUploadFileTestResponse=$(curl $validateUploadFileTestURI -w "%{http_code}" -H "$hdr_authorization" -F "file=@LvLUpAutoscalingLoadTest.jmx")

## Now we will upload the jmx to the test with the next sequence of commands
uploadFileTestURI="https://$dataPlaneURI/loadtests/$testId/files/$fileid?"$alt_apiversion

## Please make sure to run the following from same command directory as the location of LvLUpAutoscalingLoadTest.jmx
## in order to let the -F file= parameter load the jmx content correctly

uploadFileTestURIResponse=$(curl $uploadFileTestURI -X PUT -w "%{http_code}" -H "$hdr_authorization" -F "file=@LvLUpAutoscalingLoadTest.jmx")

### END - SCRIPT EXECUTION

### BEGIN - SOME FINAL CHECKS

## Let's verify that we got a http code 200 = OK for the Test File upload validation
RESPONSE_200_OK="200"
if [[ "$validateUploadFileTestResponse" == *"$RESPONSE_200_OK"* ]]
then
    echo -e "\n\n*** STATUS OK *** :-) --> File ID is available  OK to continue"
else
    echo -e "\n\n*** IMPORTANT *** :'-( ***: File ID validation failed - Stop Executing any further and verify the error"
    echo -e "Status: "$validateUploadFileTestResponse
fi

## Let's verify that we got a http code 201 = OK for the Test creation
RESPONSE_201_OK="201"
if [[ "$uploadFileTestURIResponse" == *"$RESPONSE_201_OK"* ]]
then
    echo -e "\n\n*** STATUS OK *** :-) --> Jmx File Uploaded - OK to continue"
else
    echo -e "\n\n*** IMPORTANT *** :'-( ***: Jmx File Not Uploaded - Stop Executing any further and verify the error"
    echo -e "Status: "$uploadFileTestURIResponse
fi
### END - SOME FINAL CHECKS

### You can also check in the Azure portal that the Test is present and configured correctly (refer to README)


#!/usr/bin/env bash
run_invoke () {
  CLUSTER_NAME=$1
  CLUSTER_RESOURCE_GROUP=$2
  KUBECTL_CMD=$3
  FILEPATH=$4

  KUBECTL_CMD_RESULT=""
  if [ -z $FILEPATH  ]; then
    KUBECTL_CMD_RESULT=$(az aks command invoke -o json --resource-group $CLUSTER_RESOURCE_GROUP --name $CLUSTER_NAME --command "$KUBECTL_CMD")
  else
    KUBECTL_CMD_RESULT=$(az aks command invoke -o json --resource-group $CLUSTER_RESOURCE_GROUP --name $CLUSTER_NAME --command "$KUBECTL_CMD" --file $FILEPATH)
  fi

  FORMATTED_RESULT=$(echo $KUBECTL_CMD_RESULT | tr -d '\n\r')
  KUBECTL_EXIT_CODE=$(echo $FORMATTED_RESULT | jq '.exitCode')

  if [ $KUBECTL_EXIT_CODE != "0" ]
  then
    echo "Failed to run kubectl command $KUBECTL_CMD"
    echo $KUBECTL_CMD_RESULT
    exit $KUBECTL_EXIT_CODE
  fi

  echo $KUBECTL_CMD_RESULT

}


#!/usr/bin/env bash
set -e
source ./devenv/scripts/command_invoke_with_output.sh

CLUSTER_RESOURCE_GROUP=$(cat devenv/state/cluster-info.json | jq '.ClusterResourceGroup' | tr -d '"')
CLUSTER_NAME=$(cat devenv/state/cluster-info.json | jq '.ClusterName' | tr -d '"')

echo "adding image tags to kustomize and generating configmaps..."
cp devenv/kustomize/e2e/* devenv/state/kustomize/e2e
cp devenv/state/e2e-prom-client.txt devenv/state/kustomize/e2e

cd devenv/state/kustomize/e2e # change workingdir to kustomize/e2e
kustomize edit set image placeholderfortesterimage=`cat ../../e2e-image-tag.txt`

echo "deleting any existing e2e job..."
DELETE_APPLY_RESULT=$(run_invoke $CLUSTER_NAME $CLUSTER_RESOURCE_GROUP "kubectl delete jobs app-routing-operator-e2e -n kube-system --ignore-not-found && kubectl apply -k ." ".")

cd ../.. # go back to root as working dir

# wait until cluster has reached terminated status, keep checking until terminated result is not null
NUM_ACTIVE="1"
while [ "$NUM_ACTIVE" = "1" ]
do
  # use az cli to get status from pod JSON
  STATUS=$(run_invoke $CLUSTER_NAME $CLUSTER_RESOURCE_GROUP 'kubectl get jobs --selector=app=app-routing-operator-e2e --output="jsonpath={.items[0].status}" -n kube-system' | jq ".logs" | tr -d '\\' )

  # remove quotes at prefix and suffix from output to be able to use jquery
  STATUSNOQUOTES=${STATUS#"\""}
  STATUSNOQUOTES=${STATUSNOQUOTES%"\""}

  NUM_ACTIVE=$(echo $STATUSNOQUOTES | jq '.active')
  echo "test status is currently $STATUSNOQUOTES"

  sleep 5

done

echo "exited loop with status $STATUSNOQUOTES"

SUCCEEDED=$(echo $STATUSNOQUOTES | jq ".succeeded")

echo "Test finished, echoing test pod logs..."
POD_LOGS_RESULT=$(run_invoke $CLUSTER_NAME $CLUSTER_RESOURCE_GROUP 'kubectl logs jobs/app-routing-operator-e2e -n kube-system' | tr -d '\n\r' | jq ".logs")
echo $POD_LOGS_RESULT

if [[ $SUCCEEDED == "1" ]]
then
  echo "TEST PASSED"
  exit 0
fi

echo "TEST FAILED WITH STATUS $STATUSNOQUOTES"
exit 1


#!/usr/bin/env bash
set -e

source ./devenv/scripts/command_invoke_with_output.sh

# Load variables generated by tf
export CLUSTER_CLIENT_ID=$(cat devenv/state/deployment-auth-info.json | jq '.ClusterClientId' | tr -d '"')
export ARM_CLIENT_TENANT_ID=$(cat devenv/state/deployment-auth-info.json | jq '.ArmTenantId' | tr -d '"')
export RG_LOCATION=$(cat devenv/state/deployment-auth-info.json | jq '.ResourceGroupLocation' | tr -d '"')
export DNS_ZONE_IDS=$(cat devenv/state/deployment-auth-info.json | jq '.DnsZones' | tr -d '"')
export CLUSTER_UID=$(cat devenv/state/deployment-auth-info.json | jq '.ClusterUid' | tr -d '"')

# move into state before envsubst
mkdir -p devenv/state/kustomize/operator-deployment
cp devenv/kustomize/operator-deployment/* devenv/state/kustomize/operator-deployment

# Write env to kustomize patch
envsubst < devenv/kustomize/operator-deployment/kustomization.yaml > devenv/state/kustomize/operator-deployment/kustomization.yaml

# Get cluster information for az aks command invoke
CLUSTER_RESOURCE_GROUP=$(cat devenv/state/cluster-info.json | jq '.ClusterResourceGroup' | tr -d '"')
CLUSTER_NAME=$(cat devenv/state/cluster-info.json | jq '.ClusterName' | tr -d '"')

echo "deploying to ${CLUSTER_NAME} in resource group ${CLUSTER_RESOURCE_GROUP}"
cd devenv/state/kustomize/operator-deployment

APPLY_RESULT=$(run_invoke $CLUSTER_NAME $CLUSTER_RESOURCE_GROUP "kubectl apply -k ." ".")


#!/usr/bin/env bash
set -e
source ./devenv/scripts/command_invoke_with_output.sh

# Get cluster information for az aks command invoke
CLUSTER_RESOURCE_GROUP=$(cat devenv/state/cluster-info.json | jq '.ClusterResourceGroup' | tr -d '"')
CLUSTER_NAME=$(cat devenv/state/cluster-info.json | jq '.ClusterName' | tr -d '"')

if [ -z $CLUSTER_RESOURCE_GROUP  ]; then
  echo "CLUSTER_RESOURCE_GROUP is empty"
  exit 1
fi

if [ -z $CLUSTER_NAME  ]; then
  echo "CLUSTER_NAME is empty"
  exit 1
fi

TAG=$(cat devenv/state/operator-image-tag.txt)

if [ -z $TAG  ]; then
  echo "TAG is empty"
  exit 1
fi

# Push image
CMD="kubectl set image -n kube-system deployments/app-routing-operator operator=$TAG"

run_invoke $CLUSTER_NAME $CLUSTER_RESOURCE_GROUP "$CMD"


set -e
echo "beginning private cluster tests..."
make dev CLUSTER_TYPE=private
make push
make e2e


set -e
echo "beginning public cluster tests..."
make clean
make dev CLUSTER_TYPE=public
make push
make e2e


#!/bin/sh

/app/setup.sh
exec /app/monitor.sh


#!/bin/sh

while :
do
    if [ ! -z "$(ls /audit-rules)" ]; then
        cp /audit-rules/* /node/etc/audit/rules.d/
    fi

    if [ ! -z "$(ls /audisp-plugins)" ]; then
        cp /audisp-plugins/* /node/etc/audisp/plugins.d/
    fi

    if [ ! -z "$(ls /oms-config)" ]; then
        cp /oms-config/* /node/etc/opt/microsoft/omsagent/${LOG_ANALYTICS_WORKSPACE_ID}/conf/omsagent.d/
    fi

    chroot /node systemctl reload auditd
    sleep 30
done


#!/bin/sh

# Install auditd on VMSS worker node
echo "Installing auditd"
chroot /node apt-get update
chroot /node apt-get install auditd -y

# Make sure that auditd is running
chroot /node systemctl start auditd


#!/bin/bash
set -e

echo "getting akv secretid for $CERTNAME";
versionedSecretId=$(az keyvault certificate show -n $CERTNAME --vault-name $KVNAME --query "sid" -o tsv);
unversionedSecretId=$(echo $versionedSecretId | cut -d'/' -f-5) # remove the version from the url;
echo $unversionedSecretId;

echo "creating root certificate reference in application gateway";
rootcertcmd="az network application-gateway root-cert create --gateway-name $AGNAME  -g $RG -n $CERTNAME --keyvault-secret $unversionedSecretId";
$rootcertcmd


#!/bin/bash
set -e

echo "getting id for ${CERTNAME}-fe";
versionedSecretId=$(az keyvault certificate show -n ${CERTNAME}-fe --vault-name $AKVNAME --query "sid" -o tsv);
unversionedSecretId=$(echo $versionedSecretId | cut -d'/' -f-5) # remove the version from the url;
echo $unversionedSecretId;

echo "Creating SSL Cert ${CERTNAME}-fe in application gateway"
fecertcmd="az network application-gateway ssl-cert create -n ${CERTNAME}-fe --gateway-name $AGNAME -g $RG --key-vault-secret-id $unversionedSecretId";
$fecertcmd


#!/bin/bash
set -e

certnamebackend=$APPNAME
certnamefrontend="$APPNAME-fe"

echo "creating akv cert $certnamebackend";
az keyvault certificate create --vault-name $AKVNAME -n $certnamebackend -p "$(az keyvault certificate get-default-policy | sed -e s/CN=CLIGetDefaultPolicy/CN=${certnamebackend}/g )";

echo "creating akv cert $certnamefrontend";
az keyvault certificate create --vault-name $AKVNAME -n $certnamefrontend -p "$(az keyvault certificate get-default-policy | sed -e s/CN=CLIGetDefaultPolicy/CN=${certnamefrontend}/g )";

sleep 2m


#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

echo "docker login to ${MCR_REGISTRY}"
docker login ${MCR_REGISTRY} -u ${MCR_USERNAME} -p ${MCR_PASSWORD}

TAG=${TAG:-$BUILD_NUMBER}
echo "image tag will be ${TAG}"

export IMG="${MCR_REGISTRY}/public/aks/${APP}:${TAG}"
make docker-build
make docker-push

# push to latest tag as well
export IMG="${MCR_REGISTRY}/public/aks/${APP}:latest"
docker tag "${MCR_REGISTRY}/public/aks/${APP}:${TAG}" "${IMG}"
make docker-push


#!/bin/bash
set -e

echo "Installing Cert Manager from $CERTMANAGERURI"
kubectl apply -f $CERTMANAGERURI
sleep 1m

echo "Installing Cert Manager ClusterIssuer"
echo "Email Address for Lets Encrypt: $EMAILAD"
helm upgrade --install smokecertissuer $CERTMANAGERISSUERURI --set email=$EMAILAD
sleep 1m


#!/bin/bash
set -e

echo "Retrieving KubeletId for $AKSNAME in $RG"
KubeletId=$(az aks show -n $AKSNAME -g $RG --query "identityProfile.kubeletidentity.clientId" -o tsv)
TenantId=$(az account show --query tenantId -o tsv)
SubscriptionId=$(az account show --query id -o tsv)

JSONSECRETPATH="azure.json"
cat<<EOF>$JSONSECRETPATH
{
"userAssignedIdentityID": "$KubeletId",
"tenantId": "$TenantId",
"useManagedIdentityExtension": true,
"subscriptionId": "$SubscriptionId",
"resourceGroup": "$DNSRG"
}
EOF

cat azure.json

kubectl create secret generic azure-config-file --dry-run=client -o yaml --from-file=azure.json | kubectl apply -f -

echo "Installing ExternalDns for $DNSDOMAIN"
helm upgrade --install externaldns $EXTERNALDNSURI --set externaldns.domainfilter="$DNSDOMAIN"


#!/bin/sh

begin=$(date +"%s")
echo "Creating Sku list..."

#Parameters
locationsInputFile="../../helper/src/locations.json"
skuFamiliesInputFile="../../helper/src/skuFamilies.json"
skuOutputFile="../../helper/src/vmSKUs.json"
tempFile="tempSkus.json"
ephMinCacheSizeGB=137
minCPUs=2
maxCPUs=8

#Variables
SubscriptionId=$(az account show --query id -o tsv)

#if subscription id is null
if [ -z "$SubscriptionId" ]; then exit 1; fi

echo "Using SubscriptionId $SubscriptionId"

#Load Files
locations=$(cat $locationsInputFile | jq) ##Get Locations
skuFamilies=$(cat $skuFamiliesInputFile | jq) #Get Virtual Machine SKU Families

#Loop through sku families
for loc in $(echo "${locations}" | jq -r '.[] | @base64'); do
    _jqloc() {
    echo ${loc} | base64 --decode | jq -r ${1}
    }
    location=$(_jqloc '.key') #location
    locationFilter="location%20eq%20'$location'"
    #Only call API for locations and not groups of locations
    if [ $(_jqloc 'has("itemType")') = false ]
    then
        reqUrl="https://management.azure.com/subscriptions/$SubscriptionId/providers/Microsoft.Compute/skus?api-version=2021-07-01&\$filter=$locationFilter"
        skus=$(az rest --method GET --uri $reqUrl)

        #Looking to reduce the json object size for performance
        skus=$(echo "${skus}" | jq -r --argjson family "$skuFamilies"  '.value[] | select(.resourceType == "virtualMachines") | select(.family|  IN($family[].key) )')

        for fam in $(echo "${skuFamilies}" | jq -r '.[] | @base64'); do
            _jqfam() {
            echo ${fam} | base64 --decode | jq -r ${1}
            }
            family=$(_jqfam '.key')
            computeType=$(_jqfam '.computeType')

            jq -n \
            --arg key "$family" \
            --arg text "$(_jqfam '.text')" \
            --arg itemType 2 \
            --arg location "$location" \
            --arg computeType "$computeType" \
            --arg eph false \
            '{key: $key, text: $text, itemType: $itemType | tonumber, eph: $eph | test("true"), location: $location, computeType: $computeType}'

            for row in $(echo "${skus}" | jq -r --arg family "$family" 'select(.family == $family) |  @base64'); do
                _jq() {
                echo ${row} | base64 --decode | jq -r ${1}
                }
                cpu=$(echo $(_jq) | jq -r        '.capabilities | .[] | select(.name=="vCPUs") | .value')
                if [ $cpu -ge $minCPUs ] && [ $cpu -le $maxCPUs ];
                then
                    name=$(_jq '.name')
                    osSize=$(echo $(_jq) | jq -r     '.capabilities | .[] | select(.name=="OSVhdSizeMB") | .value')
                    ram=$(echo $(_jq) | jq -r        '.capabilities | .[] | select(.name=="MemoryGB") | .value')
                    cachedSize=$(echo $(_jq) | jq -r '.capabilities | .[] | select(.name=="CachedDiskBytes") | .value')

                    #Convert to GB
                    osSizeGB=$(( osSize/1024 ))
                    cacheGB=$(( cachedSize/1073741824 ))

                    #Build text property
                    cacheGB=$((cacheGB + 0))
                    if [ $cacheGB -eq 0  ];
                    then
                        cache=""
                        eph=false
                    else
                        iops=$(echo $(_jq) | jq -r       '.capabilities | .[] | select(.name=="CombinedTempDiskAndCachedIOPS") | .value')
                        cache=", $cacheGB cache ($iops IOPS)"
                        if [ $cacheGB -ge $ephMinCacheSizeGB ];
                        then
                            eph=true
                        else
                            eph=false
                        fi
                    fi
                    text="[$name]: $cpu vCPU, $ram RAM, $osSizeGB SSD $cache"

                    #Create JSON
                    jq -n \
                    --arg key "$name" \
                    --arg text "$text" \
                    --arg eph $eph \
                    --arg location "$location" \
                    --arg computeType "$computeType" \
                    '{key: $key, text: $text, eph: $eph | test("true"), location: $location, computeType: $computeType}'
                fi
            done
        done
    fi
done | jq -n '[inputs]'  > $tempFile
mv $tempFile $skuOutputFile

#Write out durable of script execution
termin=$(date +"%s")
difftimelps=$(($termin-$begin))
echo "$(($difftimelps / 60)) minutes and $(($difftimelps % 60)) seconds elapsed for Script Execution."


#!/bin/bash

# ---------------------------------------------------------------------------
# NOTE: This needs to be kept in sync with the postdeploy.ps1 (PowerShell) script
# ---------------------------------------------------------------------------

# Fail if any command fails
set -e

ingress=""
monitor=""
enableMonitorIngress="false"
grafanaHostname="grafana"
ingressEveryNode=""
dnsZoneId=""
denydefaultNetworkPolicy=""
certEmail=""
certClusterIssuer="letsencrypt-prod"
containerLogsV2=""

acrName=""
KubeletId=""
TenantId=""

release_version=""

while getopts "p:g:n:r:" opt; do
  case ${opt} in
    p )
        IFS=',' read -ra params <<< "$OPTARG"
        for i in "${params[@]}"; do
            if [[ $i =~ (ingress|monitor|enableMonitorIngress|grafanaHostname|ingressEveryNode|dnsZoneId|denydefaultNetworkPolicy|certEmail|certClusterIssuer|acrName|KubeletId|TenantId|containerLogsV2)=([^ ]*) ]]; then
                echo "set ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}"
                declare ${BASH_REMATCH[1]}=${BASH_REMATCH[2]}
            else
                echo "Unknown parameter $i"
                show_usage=true
                break
            fi
        done
      ;;
    r )
     release_version=$OPTARG
     ;;
    \? )
      echo "Unknown arg"
      show_usage=true

      ;;
  esac
done

dnsZoneId_domain=""
if [ "$dnsZoneId" ]; then
    if [[ $dnsZoneId =~ ^/subscriptions/([^/ ]+)/resourceGroups/([^/ ]+)/providers/Microsoft.Network/(dnszones|privateDnsZones)/([^/ ]+)$ ]]; then
        dnsZoneId_sub=${BASH_REMATCH[1]}
        dnsZoneId_rg=${BASH_REMATCH[2]}
        dnsZoneId_type=${BASH_REMATCH[3]}
        dnsZoneId_domain=${BASH_REMATCH[4]}
    else
        echo "dnsZoneId parameter needs to be a resourceId format for Azure DNS Zone"
        show_usage=true
    fi

    if [ -z "$KubeletId" ] || [ -z "$TenantId" ]; then
        echo "If supplying dnsZoneId for extneral-dns, need to also provide 'KubeletId' && 'TenantId'"
        show_usage=true
    fi

fi

if [ "$ingressEveryNode" ] && [[ ! $ingressEveryNode = "true" ]]; then
 echo "supported ingressEveryNode parameter values (true)"
 show_usage=true
fi

if [ "$denydefaultNetworkPolicy" ] && [[ ! $denydefaultNetworkPolicy = "true" ]]; then
 echo "supported denydefaultNetworkPolicy parameter values (true)"
 show_usage=true
fi

if [ "$ingress" ] && [[ ! $ingress =~ (appgw|contour|nginx|traefik) ]]; then
 echo "supported ingress parameter values (appgw|contour|nginx|traefik)"
 show_usage=true
fi

if [ "$ingressEveryNode" ] && [[ $ingress = "appgw" ]]; then
 echo "ingressEveryNode only supported if ingress parameter is (nginx|contour|traefik)"
 show_usage=true
fi

if [  "$monitor" ] && [[ ! "$monitor" = "oss" ]]; then
 echo "supported monitor parameter values are (oss)"
 show_usage=true
fi

if [  "$certClusterIssuer" ] && [[ ! $certClusterIssuer =~ (letsencrypt-staging|letsencrypt-prod) ]]; then
 echo "supported cluster issuer parameter values are (letsencrypt-staging|letsencrypt-prod)"
 show_usage=true
fi

if [ "$show_usage" ]; then
    echo "Usage: $0"
    echo "args:"
    echo " < -r release download url>  the github release download url where the dependent files will be referenced"
    echo " [ -p: parameters] : Can provide one or multiple features:"
    echo "     ingress=<appgw|contour|nginx> - Enable cluster AutoScaler with max nodes"
    echo "     monitor=<oss> - Enable cluster AutoScaler with max nodes"
    echo "     enableMonitorIngress=<true> - Enable Ingress for prometheus"
    echo "     grafanaHostname=<true> - Specify a hostname for the grafana dashboard"
    echo "     ingressEveryNode=<true> - Enable cluster AutoScaler with max nodes"
    echo "     denydefaultNetworkPolicy=<true> - Deploy deny all network police"
    echo "     dnsZoneId=<Azure DNS Zone resourceId> - Enable cluster AutoScaler with max nodes"
    echo "     certEmail=<email for certman certificates> - Enables cert-manager"
    echo "     certClusterIssuer=<letsencrypt-staging|letsencrypt-prod> - Specifies cert-manager cluster issuer used by grafana"
    echo "     KubeletId=<managed identity of Kubelet> *Require for cert-manager"
    echo "     TenantId=<AzureAD TenentId> *Require for cert-manager"
    echo "     acrName=<name of ACR> * If provided, used imported images for 3rd party charts"
    echo "     containerLogsV2=<true> - Enables ContainerLogsV2"
    exit 1
fi

#  Uses dependencies.json as a config file to retrieve Helm Chart version details
get_image_property () {

    fileloc=${release_version:-./helper/src}/dependencies.json

    if [ "$release_version" ] && [[ $release_version == http* ]]; then
      dependenciesJson=$(curl -sL $fileloc)
    else
      dependenciesJson=$(cat $fileloc)
    fi

    arrKey=(${1//./ })
    nk=false
    n=-1
    l=()
    while IFS="[: ,]+" read -ra tokens; do
        for i in "${tokens[@]}"; do
            if [ "$i" = "{" ]; then
            ((n+=1))
            nk=true
            elif  [ "$i" = "}" ]; then
            ((n-=1))
            else
            if $nk; then
                #echo "testing: new key $n - $i"
                l[$n]=$(echo $i | tr -d '"')
                nk=false
            else
                print=true
                #echo "testing:  n=$n"
                for o in $(seq 0 $n); do
                    #echo "testing:  ${l[$o]} = ${arrKey[$o]}"
                    if [[ ! ${l[$o]} = ${arrKey[$o]} ]]; then
                    print=false
                    break
                    fi
                done
                if $print; then
                echo -n $i | tr -d '"'
                fi
                nk=true
            fi
            fi
        done
    done <<<$dependenciesJson

}

#  AWK Not on Invote Command. Use the dependencies file to get the helmchart image details
get_image_property_awk () {

    fileloc=${release_version:-./helper/src}/dependencies.json

    if [ "$release_version" ] && [[ $release_version == http* ]]; then
      dependenciesJson=$(curl -sL $fileloc)
    else
      dependenciesJson=$(cat $fileloc)
    fi

    echo $dependenciesJson | awk -v key=$1 'BEGIN { FS="[: \t\n,]+";  RS="[ \t\n]+:[ \t\n]+"; nk=0; n=0; split(key,ka,".")} {
        for(i=1;i<=NF;i++) {
            if ($i ~ /[{\[]/ ) {
                n++; if ($1 == "{") nk=1; else nk=0
            } else if ($i ~ /[}\]]/) { n-- } else {
                gsub(/"/, "", $i)
                if (nk) { l[n] = $i; nk=0
                } else {
                    p=1; for (o=0;o<=n;o++) if (l[o]!=ka[o]) p=0
                    if (p) printf("%s", $i)
                    nk=1
                }
            }
        }
    }' -
}

## KH - Check this workaround is still needed with the latest AGIC - MAYBE NOT!

#if [ "$vnet_opt" = "byo" ] && [ "$ingress" = "appgw" ]; then
#    echo "# ------------------------------------------------"
#    echo "#          Workaround to enable AGIC with BYO VNET"
#    APPGW_RG_ID="$(az group show -n ${rg} --query id -o tsv)"
#    APPGW_ID="$(az network application-gateway show -g ${rg} -n ${agw} --query id -o tsv)"
#    az aks enable-addons -n ${aks} -g ${rg} -a ingress-appgw --appgw-id $APPGW_ID

#    AKS_AGIC_IDENTITY_ID="$(az aks show -g ${rg} -n ${aks} --query addonProfiles.ingressApplicationGateway.identity.objectId -o tsv)"
#    az role assignment create --role "Contributor" --assignee-principal-type ServicePrincipal --assignee-object-id $AKS_AGIC_IDENTITY_ID --scope $APPGW_ID
#    az role assignment create --role "Reader" --assignee-principal-type ServicePrincipal --assignee-object-id $AKS_AGIC_IDENTITY_ID --scope $APPGW_RG_ID

    #  additionally required if appgwKVIntegration (app gateway has assigned identity)
#    if true; then

#        APPGW_IDENTITY="$(az network application-gateway show -g ${rg} -n ${agw} --query 'keys(identity.userAssignedIdentities)[0]' -o tsv)"
#        az role assignment create --role "Managed Identity Operator" --assignee-principal-type ServicePrincipal --assignee-object-id $AKS_AGIC_IDENTITY_ID --scope $APPGW_IDENTITY
#    fi
#fi

## KH - Moved to Bicep!! YAY
#
#if [ "$dnsZoneId"  ] && [ "$ingress" ]; then

#    KubeletId=$(az aks show -g ${rg} -n ${aks} --query identityProfile.kubeletidentity.clientId -o tsv)
#    TenantId=$(az account show --query tenantId -o tsv)

#        if [ "$apisecurity" = "private" ]; then
#            # Import external-dns Image to ACR
#            export acrName=$(az acr list -g ${rg} --query [0].name -o tsv)
#            az acr import -n $acrName --source ${EXTERNAL_DNS_REGISTRY}/${EXTERNAL_DNS_REPO}:${EXTERNAL_DNS_TAG} --image ${EXTERNAL_DNS_REPO}:${EXTERNAL_DNS_TAG}
#        fi
#fi

# ingress_controller_kind="Deployment"
# ingress_externalTrafficPolicy="Cluster"
# if [ "$ingressEveryNode" ]; then
#     ingress_controller_kind="DaemonSet"
#     ingress_externalTrafficPolicy="Local"
# fi
ingress_metrics_enabled=false
if [ "$monitor" = "oss" ]; then
    ingress_metrics_enabled=true
fi

ingressClass=$ingress
legacyIngressClass=$ingress
# https://azure.github.io/application-gateway-kubernetes-ingress/ingress-v1/
if [ "$ingress" = "appgw" ]; then
    ingressClass="azure-application-gateway"
    legacyIngressClass="azure/application-gateway"
fi

prometheus_namespace="monitoring"
prometheus_helm_release_name="monitoring"

if [ "$monitor" = "oss" ]; then
    echo "# ------------------------------------------------"
    echo "#              Install kube-prometheus-stack chart"
    helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
    helm repo update
    kubectl create namespace ${prometheus_namespace} --dry-run=client -o yaml | kubectl apply -f -
    helm upgrade --install ${prometheus_helm_release_name} prometheus-community/kube-prometheus-stack --namespace ${prometheus_namespace} \
        --set grafana.ingress.enabled=${enableMonitorIngress} \
        --set grafana.ingress.annotations."cert-manager\.io/cluster-issuer"=$certClusterIssuer \
        --set grafana.ingress.annotations."ingress\.kubernetes\.io/force-ssl-redirect"=\"true\" \
        --set grafana.ingress.ingressClassName=${ingressClass} \
        --set grafana.ingress.hosts[0]=${grafanaHostname}.${dnsZoneId_domain} \
        --set grafana.ingress.tls[0].hosts[0]=${grafanaHostname}.${dnsZoneId_domain},grafana.ingress.tls[0].secretName=aks-grafana
fi

if [ "$ingress" = "nginx" ]; then

    ingress_controller_kind="Deployment"
    ingress_externalTrafficPolicy="Cluster"
    if [ "$ingressEveryNode" ]; then
    ingress_controller_kind="DaemonSet"
    ingress_externalTrafficPolicy="Local"
    fi
    nginx_namespace="ingress-basic"
    nginx_helm_release_name="nginx-ingress"

    echo "# ------------------------------------------------"
    echo "#                 Install Nginx Ingress Controller"
    kubectl create namespace ${nginx_namespace} --dry-run=client -o yaml | kubectl apply -f -
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm upgrade --install ${nginx_helm_release_name} ingress-nginx/ingress-nginx \
        --set controller.publishService.enabled=true \
        --set controller.kind=${ingress_controller_kind} \
        --set controller.service.externalTrafficPolicy=${ingress_externalTrafficPolicy} \
        --set controller.metrics.enabled=${ingress_metrics_enabled} \
        --set controller.metrics.serviceMonitor.enabled=${ingress_metrics_enabled} \
        --set controller.metrics.serviceMonitor.namespace=${prometheus_namespace} \
        --set controller.metrics.serviceMonitor.additionalLabels.release=${prometheus_helm_release_name} \
        --namespace ${nginx_namespace}
fi

if [ "$ingress" = "traefik" ]; then

    ingress_controller_kind="Deployment"
    ingress_externalTrafficPolicy="Cluster"
    if [ "$ingressEveryNode" ]; then
    ingress_controller_kind="DaemonSet"
    ingress_externalTrafficPolicy="Local"
    fi

    traefik_namespace="ingress-basic"
    traefik_helm_release_name="traefik"

    echo "# ------------------------------------------------"
    echo "#                 Install Traefik Ingress Controller"
    kubectl create namespace ${traefik_namespace} --dry-run=client -o yaml | kubectl apply -f -
    helm repo add traefik https://helm.traefik.io/traefik
    helm upgrade --install ${traefik_helm_release_name} traefik/traefik \
        --set deployment.kind="${ingress_controller_kind}" \
        --set service.spec.externalTrafficPolicy=${ingress_externalTrafficPolicy} \
        --set providers.kubernetesIngress.publishedService.enabled=true \
        --set metrics.prometheus.enabled=true \
        --namespace ${traefik_namespace}
fi

if [ "$ingress" = "contour" ]; then

    ingress_controller_kind="deployment"
    ingress_externalTrafficPolicy="Cluster"
    if [ "$ingressEveryNode" ]; then
    ingress_controller_kind="daemonset"
    ingress_externalTrafficPolicy="Local"
    fi

    contour_namespace="ingress-basic"
    contour_helm_release_name="contour-ingress"
    # https://artifacthub.io/packages/helm/bitnami/contour
    echo "# ------------------------------------------------"
    echo "#               Install Contour Ingress Controller"
    helm repo add bitnami https://charts.bitnami.com/bitnami
    helm upgrade --install ${contour_helm_release_name} bitnami/contour --namespace ${contour_namespace} --create-namespace \
        --set envoy.kind=${ingress_controller_kind} \
        --set contour.service.externalTrafficPolicy=${ingress_externalTrafficPolicy} \
        --set metrics.serviceMonitor.enabled=${ingress_metrics_enabled} \
        --set commonLabels."release"=${prometheus_helm_release_name} \
        --set metrics.serviceMonitor.namespace=${prometheus_namespace}
fi

# External DNS
# external-dns needs permissions to make changes in the Azure DNS server.
# https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/azure.md#azure-managed-service-identity-msi
if [ "$dnsZoneId" ]; then

    echo "# ------------------------------------------------"
    echo "#                             Install external-dns"
    kubectl create secret generic aks-kube-msi --from-literal=azure.json="{
        userAssignedIdentityID: $KubeletId,
        tenantId: $TenantId,
        useManagedIdentityExtension: true,
        subscriptionId: ${dnsZoneId_sub},
        resourceGroup: ${dnsZoneId_rg}
    }" --dry-run=client -o yaml | kubectl apply -f -

    provider="azure"
    if [ "$dnsZoneId_type" = "privateDnsZones" ]; then
        provider="azure-private-dns"
    fi

    EXTERNAL_DNS_REPO=$(get_image_property "externaldns.1_9_0.images.image.repository")
    dnsImageRepo="$(get_image_property "externaldns.1_9_0.images.image.registry")/${EXTERNAL_DNS_REPO}"
    if [ "$acrName" ]; then
        dnsImageRepo="${acrName}.azurecr.io/${EXTERNAL_DNS_REPO}"
    fi

    helm upgrade --install externaldns "https://$(get_image_property "externaldns.1_9_0.github_https_url")" \
    --set domainFilters={"${dnsZoneId_domain}"} \
    --set provider="${provider}" \
    --set extraVolumeMounts[0].name=aks-kube-msi,extraVolumeMounts[0].mountPath=/etc/kubernetes,extraVolumeMounts[0].readOnly=true \
    --set extraVolumes[0].name=aks-kube-msi,extraVolumes[0].secret.secretName=aks-kube-msi \
    --set image.repository=${dnsImageRepo} \
    --set image.tag=$(get_image_property "externaldns.1_9_0.images.image.tag")
fi

if [ "$certEmail" ]; then

    echo "# ------------------------------------------------"
    echo "#                             Install cert-manager"

    #certMan_Version="v1.8.2"
    # NOT Needed anymore!
    #if [ "$ingress" = "appgw" ]; then
    #    echo "Downgrading cert-manager for AppGateway IC"
    #    certMan_Version="v1.5.3"
    #fi

    kubectl apply -f "https://$(get_image_property "cert_manager.1_8_2.github_https_url")"
    sleep 30s # wait for cert-manager webhook to install

    helm upgrade --install letsencrypt-issuer ${release_version:-./postdeploy/helm}/Az-CertManagerIssuer-0.3.0.tgz \
        --set email=${certEmail}  \
        --set ingressClass=${legacyIngressClass}
fi

if [ "$denydefaultNetworkPolicy" ]; then
    echo "# ----------- Default Deny All Network Policy, east-west traffic in cluster"
    kubectl apply -f ${release_version:-./postdeploy/k8smanifests}/networkpolicy-deny-all.yml
fi

if [ "$containerLogsV2" ]; then
    echo "Downloading default ConfigMap"
    configMapYamlFile="$(curl -s https://raw.githubusercontent.com/microsoft/Docker-Provider/ci_prod/kubernetes/container-azm-ms-agentconfig.yaml)"
    echo "Setting containerlog_schema_version to v2"
    configMapYamlFile=$(sed 's/#\[log_collection_settings.schema\]/[log_collection_settings.schema]/'<<<$configMapYamlFile)
    configMapYamlFile=$(sed 's/# containerlog_schema_version = \"v2\"/containerlog_schema_version = "v2"/'<<<$configMapYamlFile)
    echo "$configMapYamlFile" > container-azm-ms-agentconfig.yaml
    echo "Applying ConfigMap using kubectl apply"
    kubectl apply -f container-azm-ms-agentconfig.yaml
fi


#!/bin/bash

get_image_property () {

    dependenciesJson=$(cat $1)
    arrKey=(${2//./ })
    nk=false
    n=-1
    l=()
    while IFS="[: ,]+" read -ra tokens; do
        for i in "${tokens[@]}"; do
            if [ "$i" = "{" ]; then
            ((n+=1))
            nk=true
            elif  [ "$i" = "}" ]; then
            ((n-=1))
            else
            if $nk; then
                #echo "new key $n - $i"
                l[$n]=$(echo $i | tr -d '"')
                nk=false
            else
                print=true
                #echo "testing:  n=$n"
                for o in $(seq 0 $n); do

                    #echo "testing:  ${l[$o]} = ${arrKey[$o]}"
                    if [[ ! ${l[$o]} = ${arrKey[$o]} ]]; then
                    print=false
                    break
                    fi
                done
                if $print; then
                echo -n $i | tr -d '"'
                fi
                nk=true
            fi
            fi
        done
    done <<<$dependenciesJson
}

TEST=$(get_image_property $1 "externaldns.1_9_0.images.image.repository")
echo $TEST


#!/bin/sh -l

. /root/.bashrc

export ARM_CLIENT_ID=$INPUT_ARM_CLIENT_ID
export ARM_CLIENT_SECRET=$INPUT_ARM_CLIENT_SECRET
export ARM_SUBSCRIPTION_ID=$INPUT_ARM_SUBSCRIPTION_ID
export ARM_TENANT_ID=$INPUT_ARM_TENANT_ID
export STORAGE_ACCOUNT_NAME=$INPUT_STORAGE_ACCOUNT_NAME
export STORAGE_CONTAINER_NAME=$INPUT_STORAGE_CONTAINER_NAME
export STORAGE_ACCESS_KEY=$INPUT_STORAGE_ACCESS_KEY
export IAC_TYPE=$INPUT_IAC_TYPE

export TF_VAR_resource_group_name=$INPUT_RESOURCE_GROUP_NAME
export TF_VAR_cluster_name=$INPUT_CLUSTER_NAME
export TF_VAR_create_acr=$INPUT_CREATE_ACR
export TF_IN_AUTOMATION=true

echo "*******************"
echo "Running init"
echo "*******************"

cd /action/$INPUT_CLUSTER_SIZE

# Using Pulumi
if [ $INPUT_IAC_TYPE = "pulumi" ]; then
 echo "Using Pulumi"

 /pulumi/bin/pulumi stack select dev --create
 /pulumi/bin/pulumi config set azure:clientId ${ARM_CLIENT_ID}
 /pulumi/bin/pulumi config set azure:clientSecret ${ARM_CLIENT_SECRET} --secret
 /pulumi/bin/pulumi config set azure:tenantId ${ARM_TENANT_ID}
 /pulumi/bin/pulumi config set azure:subscriptionId ${ARM_SUBSCRIPTION_ID}

  if [ $INPUT_ACTION_TYPE = "destroy" ]; then
      echo "*******************"
      echo "Running destroy"
      echo "*******************"
      /pulumi/bin/pulumi destroy -force
  else
      echo "*******************"
      echo "Running apply"
      echo "*******************"
      /pulumi/bin/pulumi up --yes
  fi

  exit 1
fi

# Using Terraform -  Default
echo "Using Terraform"
terraform init -backend-config="resource_group_name=${TF_VAR_resource_group_name}" \
-backend-config="storage_account_name=${STORAGE_ACCOUNT_NAME}" \
-backend-config="container_name=${STORAGE_CONTAINER_NAME}" \
-backend-config="key=${TF_VAR_cluster_name}.tfstate" \
-backend-config="access_key=${STORAGE_ACCESS_KEY}"

if [ $INPUT_ACTION_TYPE = "destroy" ]; then
    echo "*******************"
    echo "Running destroy"
    echo "*******************"
    terraform destroy -force
else
    echo "*******************"
    echo "Running plan"
    echo "*******************"

    terraform plan -no-color -out=tfplan -input=false

    echo "*******************"
    echo "Running apply"
    echo "*******************"

    terraform apply tfplan
fi


#!/bin/bash

usage="$(basename "$0") [-h] [-c CLUSTER_NAME] [-g RESOURCE_GROUP_NAME] [-s SUBSCRIPTION_ID] [-r REGION]
Creates a service principal and storage account for using terraform on Azure
where:
    -h  show this help text
    -c  desired cluster name
    -g  desired resource group name
    -s  subscription id for cluster
    -r  region for cluster"

while getopts h:c:g:s:r: flag
do
    case "${flag}" in
        h) echo "$usage"; exit;;
        c) cluster_name=${OPTARG};;
        g) resource_group_name=${OPTARG};;
        s) subscription=${OPTARG};;
        r) region=${OPTARG};;
        :) printf "missing argument for -%s\n" "$OPTARG" >&2; echo "$usage" >&2; exit 1;;
        \?) printf "illegal option: -%s\n" "$OPTARG" >&2; echo "$usage" >&2; exit 1;;
    esac
done

# mandatory arguments
if [ ! "$cluster_name" ] || [ ! "$resource_group_name" ] || [ ! "$subscription" ] || [ ! "$region" ]; then
  echo "all arguments must be provided"
  echo "$usage" >&2; exit 1
fi

echo "Arguments provided:"
echo "Cluster Name: $cluster_name";
echo "Resource Group Name: $resource_group_name";
echo "Subscription: $subscription";
echo "Region: $region";

STORAGE_ACCOUNT_NAME=$(echo "${resource_group_name}" | tr '[:upper:]' '[:lower:]')$RANDOM
CONTAINER_NAME=$(echo "${cluster_name}" | tr '[:upper:]' '[:lower:]')tstate

az account set --subscription $subscription &> /dev/null
# Create resource group
az group create --location $region --resource-group $resource_group_name &> /dev/null

#Create service principal and give it access to group
SP_OUTPUT=$(az ad sp create-for-rbac --name $resource_group_name --role contributor --scopes /subscriptions/$subscription/resourceGroups/$resource_group_name --sdk-auth)
echo $SP_OUTPUT
ARM_CLIENT_ID=$(echo $SP_OUTPUT | jq -r .clientId)
ARM_CLIENT_SECRET=$(echo $SP_OUTPUT | jq -r .clientSecret)
ARM_TENANT_ID=$(echo $SP_OUTPUT | jq -r .tenantId)

# Create storage account
az storage account create --resource-group $resource_group_name --name $STORAGE_ACCOUNT_NAME --sku Standard_LRS --encryption-services blob

# Get storage account key
ACCOUNT_KEY=$(az storage account keys list --resource-group $resource_group_name --account-name $STORAGE_ACCOUNT_NAME --query '[0].value' -o tsv)

# Create blob container
az storage container create --name $CONTAINER_NAME --account-name $STORAGE_ACCOUNT_NAME --account-key $ACCOUNT_KEY

echo "____________________________________________________________"
echo "____________________________________________________________"
echo "the following should be passed to the action"
echo "CLUSTER_NAME: $cluster_name";
echo "RESOURCE_GROUP_NAME: $resource_group_name";
echo "STORAGE_ACCOUNT_NAME: $STORAGE_ACCOUNT_NAME"
echo "STORAGE_CONTAINER_NAME: $CONTAINER_NAME"
echo "STORAGE_ACCESS_KEY: $ACCOUNT_KEY"
echo "ARM_CLIENT_ID: $ARM_CLIENT_ID"
echo "ARM_CLIENT_SECRET: $ARM_CLIENT_SECRET"
echo "ARM_SUBSCRIPTION_ID: $subscription"
echo "ARM_TENANT_ID: $ARM_TENANT_ID"


# Copyright (C) 2021 scalers.ai

WELD_POROSITY_MODEL=/models/weld_porosity/FP32/weld-porosity-detection-0001.xml

runPipeline() {
gst-launch-1.0 \
    rtspsrc location=$INPUT ! decodebin  ! videoconvert ! video/x-raw,format=BGRx ! \
    gvapython module=weld_porosity.py class=InferenceTime ! \
    gvainference model=${WELD_POROSITY_MODEL} inference-interval=1  device=$DEVICE ! \
    gvapython  module=weld_porosity.py class=WeldPorosity ! \
    gvametaconvert format=json add-tensor-data=true ! \
    gvametapublish method=mqtt address=$MQTT_IP:1883 topic=weld

return
}

until runPipeline;
do
    echo 'Restarting pipeline'
    sleep 1
done


#sh
# Copyright (C) 2021 scalers.ai

./rtsp-simple-server & \
python3 streamer.py


#! /bin/bash
set -x

group=$1
subscription=$2
location=$3

az group create --name $group --location $3 --subscription $2

# Create role
az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/$subscription/resourceGroups/$group" >~/.kube/$group-sp.json
# shellcheck disable=SC2002,SC2155
export appId=$(cat ~/.kube/$group-sp.json | jq -r .appId)
# shellcheck disable=SC2002,SC2155
export password=$(cat ~/.kube/$group-sp.json | jq -r .password)

# give the sp time to propagate
sleep 180

# Deploy Cluster
aks-engine deploy --subscription-id $subscription --resource-group $group --location $location us --api-model apimodel.json --dns-prefix $group

cp $(pwd)/_output/$group/kubeconfig/kubeconfig.eastus.json ~/.kube/$group.json

sleep 180

aks-engine addpool --subscription-id $subscription --resource-group $group --location $location us --api-model _output/$group/apimodel.json --agent-pool agentpool.json

az vmss list -g $group --subscription $subscription -o table

KUBECONFIG=~/.kube/$group.json kubectl get nodes

#cleanup
#az vmss delete -n $(az vmss list -g $group --subscription $subscription -o json | jq .[1].name) -g $group --subscription $subscription --no-wait

#az group delete -g $group --subscription $subscription --no-wait


#!/bin/bash

KIND= # allowed values "deployment" or "statefulset"
NS= # namespace name of the deployment/statefulset, ex: "default"
NAME= # resource name of the deployment/statefulset
PVC_LIST= # PVCs to migrate, ex: "pvc1-name pvc2-name"
TMP=$(mktemp -d)

mkdir -p ${TMP}/${KIND} ${TMP}/pvc ${TMP}/pv

# Back kind/name, remove ID
ID_PROPS=".metadata.annotations, .metadata.creationTimestamp, .metadata.generation, .metadata.resourceVersion, .metadata.uid, .metadata.managedFields, .status, .spec.template.metadata.creationTimestamp"
if [[ "${KIND,,}" == "statefulset" ]]; then
    ID_PROPS="${ID_PROPS}, .spec.volumeClaimTemplates[].metadata.creationTimestamp, .spec.volumeClaimTemplates[].status"
fi

kubectl get ${KIND}/${NAME} -n ${NS} -o json | \
    jq "del(${ID_PROPS})" \
    > ${TMP}/${KIND}/${NS}-${NAME}.json

# Delete kind/name
kubectl delete -n ${NS} ${KIND}/${NAME}

for pvc in ${PVC_LIST}
do
    # Get PV data from PVC
    PV_NAME=$(kubectl get pvc ${pvc} -o jsonpath='{.spec.volumeName}')
    PV_DISK_URI=$(kubectl get pv ${PV_NAME} -o jsonpath='{.spec.azureDisk.diskURI}')
    PV_FS_TYPE=$(kubectl get pv ${PV_NAME} -o jsonpath='{.spec.azureDisk.fSType}')

    # Back PVC, remove ID
    kubectl get pvc ${pvc} -n ${NS} -o json | \
        jq 'del(.metadata.annotations, .metadata.creationTimestamp, .metadata.resourceVersion, .metadata.uid, .status)' \
        > ${TMP}/pvc/${NS}-${pvc}.json

    # Back PV, remove ID, remove spec.azureDisk, add spec.csi
    cat << EOF > ${TMP}/csi-pv.spec
{
    "csi": {
        "driver": "disk.csi.azure.com",
        "volumeHandle": "${PV_DISK_URI}",
        "fsType": "${PV_FS_TYPE}"
    }
}
EOF

    kubectl get pv ${PV_NAME} -n ${NS} -o json | \
        jq 'del(.metadata.annotations, .metadata.creationTimestamp, .metadata.managedFields, .metadata.resourceVersion, .metadata.uid, .status, .spec.claimRef.resourceVersion, .spec.claimRef.uid, .spec.azureDisk)' | \
        jq ".spec += $(cat ${TMP}/csi-pv.spec)" \
        > ${TMP}/pv/${NS}-${PV_NAME}.json

    # Retain Azure disk on PV deletion
    kubectl patch pv ${PV_NAME} -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

    # Delete PVC+PV pair
    kubectl delete -n ${NS} pvc/${pvc}
    kubectl delete pv/${PV_NAME}
done

# Recreate resources
kubectl apply -f ${TMP}/pv
if [[ "${KIND,,}" == "deployment" ]]; then
    kubectl apply -f ${TMP}/pvc;
fi
kubectl apply -f ${TMP}/${KIND}


#!/bin/bash
# Add support for registering host on dns server. Must allow non-secure updates

set -e

DOMAINNAME=$1

echo $(date) " - Starting Script"

cat > /etc/network/if-up.d/register-dns <<EOFDHCP
#!/bin/sh

# only execute on the primary nic
if [ "\${IFACE}" = "eth0" ]
then
    ip=\$(ip address show eth0 | awk '/inet / {print \$2}' | cut -d/ -f1)
    host=\$(hostname -s)
    nsupdatecmds=/var/tmp/nsupdatecmds
    echo "update delete \${host}.${DOMAINNAME} a" > \$nsupdatecmds
    echo "update add \${host}.${DOMAINNAME} 3600 a \${ip}" >> \$nsupdatecmds
    echo "send" >> \$nsupdatecmds

    nsupdate \$nsupdatecmds
fi
EOFDHCP

chmod 755 /etc/network/if-up.d/register-dns

if ! grep -Fq "${DOMAINNAME}" /etc/dhcp/dhclient.conf
then
    echo $(date) " - Adding domain to dhclient.conf"

    echo "supersede domain-name \"${DOMAINNAME}\";" >> /etc/dhcp/dhclient.conf
    echo "prepend domain-search \"${DOMAINNAME}\";" >> /etc/dhcp/dhclient.conf
fi

# service networking restart
echo $(date) " - Restarting network"
sudo ifdown eth0 && sudo ifup eth0


#!/bin/bash

# Script file to run hello-world in bash

echo "hello"


#!/bin/bash

# Script file to install the docker hello-world container

set -e

echo $(date) " - Starting Script"

echo $(date) " - Waiting for API Server to start"
kubernetesStarted=1
for i in {1..600}; do
    if [ -e /usr/local/bin/kubectl ]
    then
        if /usr/local/bin/kubectl cluster-info
        then
            echo "kubernetes started"
            kubernetesStarted=0
            break
        fi
    else
        if /usr/bin/docker ps | grep apiserver
        then
            echo "kubernetes started"
            kubernetesStarted=0
            break
        fi
    fi
    sleep 1
done
if [ $kubernetesStarted -ne 0 ]
then
    echo "kubernetes did not start"
    exit 1
fi

# Deploy container
echo $(date) " - Deploying hello-world container"

kubectl run hello-world --quiet --image=busybox --restart=OnFailure -- echo "Hello Kubernetes!"

echo $(date) " - run kubectl get pods --show-all to list the pods"
echo $(date) " - run kubectl logs (passing the pod name gathered from kubectl get pods)"
echo $(date) " - Script complete"