#!/usr/bin/env bash

# Microsoft Azure Linux Agent
#
# Copyright 2018 Microsoft Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
set -euo pipefail

usage() (
    echo "Usage: install-agent -p|--package <path> -v|--version <version>"
    exit 1
)

while [[ $# -gt 0 ]]; do
    case $1 in
        -p|--package)
            shift
            if [ "$#" -lt 1 ]; then
                usage
            fi
            package=$1
            shift
            ;;
        -v|--version)
            shift
            if [ "$#" -lt 1 ]; then
                usage
            fi
            version=$1
            shift
            ;;
        *)
            usage
    esac
done
if [ "$#" -ne 0 ] || [ -z ${package+x} ] || [ -z ${version+x} ]; then
    usage
fi

#
# Find the command to manage services
#
if command -v systemctl &> /dev/null; then
  service-status() { systemctl --no-pager -l status $1; }
  service-stop()   { systemctl stop $1; }
  service-start()  { systemctl start $1; }
else
  service-status() { service $1 status; }
  service-stop()   { service $1 stop; }
  service-start()  { service $1 start; }
fi

#
# Find the service name (walinuxagent in Ubuntu and waagent elsewhere)
#
if service-status walinuxagent > /dev/null 2>&1;then
    service_name="walinuxagent"
else
    service_name="waagent"
fi

#
# Output the initial version of the agent

#
python=$(get-agent-python)
waagent=$(get-agent-bin-path)

echo "========== Initial Status =========="
echo "Service Name: $service_name"
echo "Agent Path: $waagent"
echo "Agent Version:"
$python "$waagent" --version
echo "Service Status:"

# We need to wait for the provisioning code to complete before stopping the agent's service to do the test setup
started=false
for i in {1..12}
do
  if [[ -f /var/lib/waagent/provisioned ]]; then
    started=true
    break
  fi
  echo "Waiting for agent to complete provisioning."
  sleep 30
done
if [ $started == false ]; then
  echo "Provisioning did not complete within the given timeout (cannot find /var/lib/waagent/provisioned)"
  exit 1
fi

#
# Install the package
#
echo "========== Installing Agent =========="
echo "Installing $package as version $version..."
unzip.py "$package" "/var/lib/waagent/WALinuxAgent-$version"

python=$(get-agent-python)
# Ensure that AutoUpdate is enabled. some distros, e.g. Flatcar have a waagent.conf in different path
waagent_conf_path=$($python -c 'from azurelinuxagent.common.osutil import get_osutil; osutil=get_osutil(); print(osutil.agent_conf_file_path)')
echo "Agent's conf path: $waagent_conf_path"
sed -i 's/AutoUpdate.Enabled=n/AutoUpdate.Enabled=y/g' "$waagent_conf_path"
# By default UpdateToLatestVersion flag set to True, so that agent go through update logic to look for new agents.
# But in e2e tests this flag needs to be off in test version 9.9.9.9 to stop the agent updates, so that our scenarios run on 9.9.9.9.
sed -i '$a AutoUpdate.UpdateToLatestVersion=n' "$waagent_conf_path"
# Logging and exiting tests if Extensions.Enabled flag is disabled for other distros than debian
if grep -q "Extensions.Enabled=n" $waagent_conf_path; then
  pypy_get_distro=$(pypy3 -c 'from azurelinuxagent.common.version import get_distro; print(get_distro())')
  python_get_distro=$($python -c 'from azurelinuxagent.common.version import get_distro; print(get_distro())')
  # As we know debian distros disable extensions by default, so we need to enable them to verify agent extension scenarios
  # If rest of the distros disable extensions, then we exit the test setup to fail the test.
  if [[ $pypy_get_distro == *"debian"* ]] || [[ $python_get_distro == *"debian"* ]]; then
      echo "Extensions.Enabled flag is disabled and this is expected in debian distro, so enabling it"
      update-waagent-conf Extensions.Enabled=y
  else
      echo "Extensions.Enabled flag is disabled which is unexpected in this distro, so exiting test setup to fail the test"
      exit 1
  fi
fi

#
# TODO: Remove this block once the symlink is created in the Flatcar image
#
# Currently, the Agent looks for /usr/share/oem/waagent.conf, but new Flatcar images use /etc/waagent.conf. Flatcar will create
# this symlink in new images, but we need to create it for now.
if [[ $(uname -a) == *"flatcar"* ]]; then
  if [[ ! -f /usr/share/oem/waagent.conf ]]; then
    ln -s "$waagent_conf_path" /usr/share/oem/waagent.conf
  fi

  # New flatcar images set the uphold property for agent service that is causing automatic restart on stop cmd
  # [Upholds= dependency on it has a continuous effect, constantly restarting the unit if necessary]
  # Resetting the uphold property as workaround for now
  uphold_target=$(systemctl show waagent --property=UpheldBy)
  # example output: UpheldBy=multi-user.target
  if [[ $uphold_target == *".target"* ]]; then
    target_name="${uphold_target#*=}"
    if [[ ! -d /etc/systemd/system/$target_name.d ]]; then
      mkdir -p /etc/systemd/system/$target_name.d
    fi
    echo -e "[Unit]\nUpholds=" > /etc/systemd/system/$target_name.d/10-waagent-sysext.conf
    systemctl daemon-reload
  fi
  # Flatcar images does automatic reboot without user input, so turning it off
  # Broadcast message from locksmithd at 2024-02-23 19:48:55.478412272 +0000 UTC m=
  # System reboot in 5 minutes!
  echo "REBOOT_STRATEGY=off" > /etc/flatcar/update.conf
  systemctl restart locksmithd
fi

#
# Restart the service
#
echo "Restarting service..."
agent-service stop

# Rename the previous log to ensure the new log starts with the agent we just installed
mv /var/log/waagent.log /var/log/waagent."$(date --iso-8601=seconds)".log

agent-service start

#
# Verify that the new agent is running and output its status.
# Note that the extension handler may take some time to start so give 1 minute.
#
echo "Verifying agent installation..."

check-version() {
  # We need to wait for the extension handler to start, give it a couple of minutes
  for i in {1..12}
  do
    if waagent-version | grep -E "Goal state agent:\s+$version" > /dev/null; then
      return 0
    fi
    sleep 10
  done

  return 1
}

if check-version "$version"; then
  printf "The agent was installed successfully\n"
  exit_code=0
else
  printf "************************************\n"
  printf " * ERROR: Failed to install agent. *\n"
  printf "************************************\n"
  exit_code=1
fi

printf "\n"
echo "========== Final Status =========="
$python "$waagent" --version
printf "\n"
agent-service status

exit $exit_code
