view thermostat-ng.sh @ 11:13709102af90

Build web-client with testing environment Reviewed-by: jkang Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2017-August/024576.html
author Andrew Azores <aazores@redhat.com>
date Fri, 18 Aug 2017 10:31:35 -0400
parents 873a1db68bca
children 2f04aa98a8a9
line wrap: on
line source

#!/bin/bash
#
# Runs Thermostat.next() all-in-one locally
#
# Examples:
#
# Build everything and run thermostat:
#  $ ./thermostat-ng -a     OR
#  $ ./thermostat-ng -b all
#
# Build only agent and run thermostat:
#  $ ./thermostat-ng -b agent
#
# Run thermostat without any build:
#  $ ./thermostat-ng -b none OR
#  $ ./thermostat-ng -s
#
#set -xv
#set -e

script_directory() {
  # Compute the parent directory. I.e. the (symlink-resolved) location of the
  # currently executing code's directory. See
  # http://stackoverflow.com/a/246128/3561275 for implementation details.
  SOURCE="${BASH_SOURCE[0]}"
  while [ -h "$SOURCE" ]; do
    DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
    SOURCE="$(readlink "$SOURCE")"
    [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
  done
  DIR="$(cd -P "$(dirname "$SOURCE")" && pwd)"
  echo "$DIR"
}

check_sources_sane() {
  local error=0
  local base_hg_path="$(hg paths default)"
  for dir in $WEB_GATEWAY_ROOT $AGENT_ROOT; do
    if [ ! -e "${dir}" ]; then
      sub_repo="$(basename ${dir})"
      echo 2>&1 "${dir} does not exist. Try to clone it via: hg clone ${base_hg_path}/${sub_repo}"
      error=$(( $error + 1 ))
    fi
  done
  if [ $error -gt 0 ]; then
    echo 2>&1 "Required repositories do not exist. Exiting."
    exit 1
  fi
}

check_success_msg() {
  local retval=$1
  local msg=$2
  if [ $retval -ne 0 ]; then
    echo 2>&1 "Error: $msg"
    exit 1
  fi
}

fail() {
  local msg=$1
  check_success_msg 1 "$msg"
}

wait_for_ready() {
  local expected_msg="$1"
  local log_file="$2"
  local max_attempts=40
  while [ $max_attempts -gt 0 ]; do
    if grep -q "$expected_msg" "$log_file"; then
      return 0
    fi
    sleep 1
    max_attempts=$(( $max_attempts - 1 ))
  done
  return 1
}

# Start/Stop mongodb
mongodb() {
  local action="$1"
  case $action in
    start)
      ;& # fall-through
    stop)
      if [ $CYGWIN_MODE == 1 ] ; then
        $WEB_GATEWAY_ROOT/distribution/target/image/bin/thermostat-mongodb.sh $action &
      else
        $WEB_GATEWAY_ROOT/distribution/target/image/bin/thermostat-mongodb.sh $action
        check_success_msg $? "Failed to $action mongodb."
      fi
      ;;
    *)
      fail "Unknown action '$action'"
      ;;
  esac
}

start_web_gateway() {
  local error=0
  local fail_msg="Failed to start web-gateway"
  echo "Starting web-gateway ..."
  $WEB_GATEWAY_ROOT/distribution/target/image/bin/thermostat-web-gateway.sh > "$GW_LOG_FILE" 2>&1 &
  error=$?
  echo $! > "$GW_PID_FILE"
  check_success_msg $error $fail_msg
  wait_for_ready "Server:main: Started" "$GW_LOG_FILE"
  check_success_msg $? $fail_msg
  echo "web-gateway started."
  echo "PID file: $GW_PID_FILE"
  echo "Log file: $GW_LOG_FILE"
}

stop_web_gateway() {
  _stop "$GW_PID_FILE" "web-gateway does not appear to be running."
}

_stop() {
  local pidFile="$1"
  local errorMsg="$2"
  if [ -f "$pidFile" ]; then
    pid="$(cat "$pidFile")"
    kill $pid
  else
    echo "$errorMsg"
  fi
}

# Start/stop web-gateway
web_gateway() {
  local action="$1"
  case $action in
    start)
      start_web_gateway
      ;;
    stop)
      stop_web_gateway
      ;;
    *)
      fail "Unknown action '$action'"
      ;;
  esac
}

start_agent() {
  local fail_msg="Failed to start agent"
  config_agent
  echo "Starting agent ..."
  $AGENT_ROOT/distribution/target/image/bin/thermostat -J-Dthermostat.agent.verbose=true -Tbg "$AGENT_PID_FILE" > "$AGENT_LOG_FILE" 2>&1
  check_success_msg $? $fail_msg
  wait_for_ready "Agent started" "$AGENT_LOG_FILE"
  check_success_msg $? $fail_msg
  echo "agent started."
  echo "PID file: $AGENT_PID_FILE"
  echo "Log file: $AGENT_LOG_FILE"
}

stop_agent() {
  _stop "$AGENT_PID_FILE" "agent does not appear to be running."
}

# Start/stop agent
agent() {
  local action="$1"
  case $action in
    start)
      start_agent
      ;;
    stop)
      stop_agent
      ;;
    *)
      fail "Unknown action '$action'"
      ;;
  esac
}

build() {
  local dir="$1"
  if [ "${DO_BUILD}_" == "true_" ]; then
    local build_fn=$2
    local error=0
    local component=$(basename $dir)
    pushd "$dir"
      $build_fn;
      error=$?
    popd
    check_success_msg $error "Failed to build $component"
  else
    echo "Build of $dir is skipped."
  fi
}

mvn_build() {
  mvn clean verify
}

npm_build() {
  # setup environment variables
  export NODE_ENV=testing
  export GATEWAY_URL
  npm install
  npm run build
}

build_web_gateway() {
  build "$WEB_GATEWAY_ROOT" mvn_build
}

config_agent() {
  local agent_conf_dir="$HOME/.thermostat/etc"
  local agent_conf="${agent_conf_dir}/agent.auth"
  if [ ! -d "$agent_conf" ]; then
    mkdir -p "$agent_conf_dir"
  fi
  echo "username=foo-agent-user" >> $agent_conf
  echo "password=agent-pwd" >> $agent_conf
  ## convert Windows backslashes in paths to '/'
  if [ $CYGWIN_MODE == 0 ] ; then
    cp $AGENT_ROOT/distribution/target/image/etc/examples/ssl.properties.example $AGENT_ROOT/distribution/target/image/etc/ssl.properties
  else
   sed sX\\\\X/Xg $AGENT_ROOT/distribution/target/image/etc/examples/ssl.properties.example >$AGENT_ROOT/distribution/target/image/etc/ssl.properties
  fi
}


build_agent() {
  build "$AGENT_ROOT" mvn_build
}

build_web_client() {
  build "$WEB_CLIENT_ROOT" npm_build
}

# deploy web-client resources statically, more info at http://icedtea.classpath.org/pipermail/thermostat/2017-May/023164.html
copy_web_client_to_web_gateway() {
  local dist_dir="${WEB_CLIENT_ROOT}/dist";
  if [ -d "$dist_dir" ]; then
    cp -r $dist_dir $WEB_GATEWAY_ROOT/distribution/target/image/web-client;
    echo "Web client copied to web-gateway."
  else
    fail "Web client could not be copied to web-gateway because the directory web-client/dist/ does not exist. Make sure the web-client has been built correctly."
  fi
}

# Shuts down everything in reverse order.
# Called via trap
stop_all() {
  echo
  echo "Shutting down everything..."
  agent stop
  web_gateway stop
  mongodb stop
  rm -rf "$RUN_DATA_DIR"
  echo "Done. Bye now."
  exit 0
}

# Idle loop so as to be able to receive signals
idle() {
  echo "Thermostat started. Stop with CTRL+C"
  echo "The web client can be accessed at: $GATEWAY_URL/web-client/"
  echo "Use credentials 'test-user':'test-pass' to log in."
  while true; do
    sleep 60
  done
}

# set global variable for Cygwin testing
# between all shell files, we pass cygwin-compatible paths,
#    and let each script decide when to convert them.
# an exception is command line args for java programs, which
#    need to be converted to windows format at creation time
if [ "$(uname -s | cut -b1-6)" == "CYGWIN" ]; then
  ##echo "Running under Cygwin"
  export CYGWIN_MODE=1
else
  ##echo "Running under Linux"
  export CYGWIN_MODE=0
fi

TOP_DIR="$(script_directory)"
WEB_GATEWAY_ROOT="${TOP_DIR}/web-gateway"
AGENT_ROOT="${TOP_DIR}/agent"
WEB_CLIENT_ROOT="${TOP_DIR}/web-client"
GATEWAY_URL="https://127.0.0.1:30000"

DO_BUILD=${BUILD:-true}
RUN_DATA_DIR="$TOP_DIR/data"
LOG_DIR="$RUN_DATA_DIR/logs"
PID_DIR="$RUN_DATA_DIR/pids"
GW_LOG_FILE="$LOG_DIR/web-gateway.log"
GW_PID_FILE="$PID_DIR/web-gateway.pid"
AGENT_LOG_FILE="$LOG_DIR/agent.log"
AGENT_PID_FILE="$PID_DIR/agent.pid"

mkdir -p "$LOG_DIR" "$PID_DIR"

PARTIAL_BUILD=false
WEB_GATEWAY=true
WEB_CLIENT=true
AGENT=true

HELP_STRING="\nUSAGE: $0 [BUILD_OPTION]
    -a
        Build everything. No values are bound to this flag.
    -b [module_names...]|all|none
        Specify which modules should be built. In case the -b flag has more than one value, it should be specified as the last flag.
        It is possible to specify more than one value via repetition of this flag, e.g. $0 -b agent -b web-client
    -s
        Skip build of all components and directly start Thermostat. No values are bound to this flag.\n\n"

print_help() {
  printf "$HELP_STRING"
}

mark_everything_to_be_built() {
  WEB_GATEWAY=true
  WEB_CLIENT=true
  AGENT=true
}

mark_nothing_to_be_built() {
  WEB_GATEWAY=false
  WEB_CLIENT=false
  AGENT=false
}

# Check whether the component passed as the first argument of this function exists.
# "all" is also acceptable as a parameter, which results in the same behaviour as if all components were specified.
# Component name can also end with a forward slash (UNIX autocompletion support).
resolve_component_name() {
  local component_name
  component_name=$1
  case "${component_name}" in
    web-gateway|web-gateway/)
      WEB_GATEWAY=true
      ;;
    web-client|web-client/)
      WEB_CLIENT=true
      ;;
    agent|agent/)
      AGENT=true
      ;;
    none)
      mark_nothing_to_be_built
      ;;
    all)
      mark_everything_to_be_built
      ;;
    *)
      echo "Component '${component_name}' does not exist."
      print_help
      exit 1
  esac
}

build_all_requested_components() {
  if [ "$WEB_GATEWAY" = "true" ]; then
    build_web_gateway
  fi
  if [ "$WEB_CLIENT" = "true" ]; then
    build_web_client; copy_web_client_to_web_gateway
  fi
  if [ "$AGENT" = "true" ]; then
    build_agent
  fi
}

check_for_remaining_components() {
  # Iterate through remaining arguments and consider them as component names
  local remaining_args_count remaining_args
  remaining_args_count=$1
  remaining_args=$2
  if [ "$PARTIAL_BUILD" = "true" ]; then
    for comp in ${remaining_args}; do
      resolve_component_name $comp
    done
  elif [ "$remaining_args_count" -ne "0" ]; then
    print_help
    exit 1
  fi
}

parse_args() {
  local OPTIND
  OPTIND=1
  while getopts ":b:as" opt ; do
    case "${opt}" in
      a)
        mark_everything_to_be_built
        break
        ;;
      b)
        if [ "$PARTIAL_BUILD" = "false" ]; then
          # First occurence of -b flag, first assume no components are going to be built
          # (by default, all components are going to be built if no flags are specified)
          # and then resolve component names with $PARTIAL_BUILD=true afterwards.
          mark_nothing_to_be_built
          PARTIAL_BUILD=true
        fi
        resolve_component_name $OPTARG
        ;;
      s)
        mark_nothing_to_be_built
        break
        ;;
      :)
        printf "\nOption '$OPTARG' requires parameters."
        print_help
        exit 1
        ;;
      *)
        printf "Unexpected option '$OPTARG'"
        print_help
        exit 1
        ;;
    esac
  done
  shift $((OPTIND-1))
  #OPTIND is local
  check_for_remaining_components $# $@
}

parse_args "$@"

# Be sure source tree looks OK.
check_sources_sane

# Build all components that were requested in command line arguments.
build_all_requested_components

trap stop_all INT

mongodb "start"
web_gateway "start"
agent "start"

# Idle until interrupted with "CTRL + C"
# The trap for INT will stop everything we've
# started.
idle