| #!/bin/bash |
| |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You 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. |
| # |
| |
| # This test script runs a simple smoke test in standalone cluster: |
| # - create docker network |
| # - start up a master |
| # - start up a worker |
| # - wait for the web UI endpoint to return successfully |
| # - run a simple smoke test in standalone cluster |
| # - clean up test resource |
| |
| CURL_TIMEOUT=1 |
| CURL_COOLDOWN=1 |
| CURL_MAX_TRIES=30 |
| |
| NETWORK_NAME=spark-net-bridge |
| |
| SUBMIT_CONTAINER_NAME=spark-submit |
| MASTER_CONTAINER_NAME=spark-master |
| WORKER_CONTAINER_NAME=spark-worker |
| SPARK_MASTER_PORT=7077 |
| SPARK_MASTER_WEBUI_CONTAINER_PORT=8080 |
| SPARK_MASTER_WEBUI_HOST_PORT=8080 |
| SPARK_WORKER_WEBUI_CONTAINER_PORT=8081 |
| SPARK_WORKER_WEBUI_HOST_PORT=8081 |
| |
| SCALA_VERSION="2.12" |
| SPARK_VERSION="3.3.0" |
| IMAGE_URL= |
| |
| # Create a new docker bridge network |
| function create_network() { |
| if [ ! -z $(docker network ls --filter name=^${NETWORK_NAME}$ --format="{{ .Name }}") ]; then |
| # bridge network already exists, need to kill containers attached to the network and remove network |
| cleanup |
| remove_network |
| fi |
| docker network create --driver bridge "$NETWORK_NAME" > /dev/null |
| } |
| |
| # Remove docker network |
| function remove_network() { |
| docker network rm "$NETWORK_NAME" > /dev/null |
| } |
| |
| # Find and kill any remaining containers attached to the network |
| function cleanup() { |
| local containers |
| containers="$(docker ps --quiet --filter network="$NETWORK_NAME")" |
| |
| if [ -n "$containers" ]; then |
| echo >&2 -n "==> Killing $(echo -n "$containers" | grep -c '^') orphaned container(s)..." |
| echo "$containers" | xargs docker kill > /dev/null |
| echo >&2 " done." |
| fi |
| } |
| |
| # Exec docker run command |
| function docker_run() { |
| local container_name="$1" |
| local docker_run_command="$2" |
| local args="$3" |
| |
| echo >&2 "===> Starting ${container_name}" |
| if [ "$container_name" = "$MASTER_CONTAINER_NAME" -o "$container_name" = "$WORKER_CONTAINER_NAME" ]; then |
| # --detach: Run spark-master and spark-worker in background, like spark-daemon.sh behaves |
| eval "docker run --rm --detach --network $NETWORK_NAME --name ${container_name} ${docker_run_command} $IMAGE_URL ${args}" |
| else |
| eval "docker run --rm --network $NETWORK_NAME --name ${container_name} ${docker_run_command} $IMAGE_URL ${args}" |
| fi |
| } |
| |
| # Start up a spark master |
| function start_spark_master() { |
| docker_run \ |
| "$MASTER_CONTAINER_NAME" \ |
| "--publish $SPARK_MASTER_WEBUI_HOST_PORT:$SPARK_MASTER_WEBUI_CONTAINER_PORT $1" \ |
| "/opt/spark/bin/spark-class org.apache.spark.deploy.master.Master" > /dev/null |
| } |
| |
| # Start up a spark worker |
| function start_spark_worker() { |
| docker_run \ |
| "$WORKER_CONTAINER_NAME" \ |
| "--publish $SPARK_WORKER_WEBUI_HOST_PORT:$SPARK_WORKER_WEBUI_CONTAINER_PORT $1" \ |
| "/opt/spark/bin/spark-class org.apache.spark.deploy.worker.Worker spark://$MASTER_CONTAINER_NAME:$SPARK_MASTER_PORT" > /dev/null |
| } |
| |
| # Wait container ready until endpoint returns successfully |
| function wait_container_ready() { |
| local container_name="$1" |
| local host_port="$2" |
| i=0 |
| echo >&2 "===> Waiting for ${container_name} to be ready..." |
| while true; do |
| i=$((i+1)) |
| |
| set +e |
| |
| curl \ |
| --silent \ |
| --max-time "$CURL_TIMEOUT" \ |
| localhost:"${host_port}" \ |
| > /dev/null |
| |
| result=$? |
| |
| set -e |
| |
| if [ "$result" -eq 0 ]; then |
| break |
| fi |
| |
| if [ "$i" -gt "$CURL_MAX_TRIES" ]; then |
| echo >&2 "===> \$CURL_MAX_TRIES exceeded waiting for ${container_name} to be ready" |
| return 1 |
| fi |
| |
| sleep "$CURL_COOLDOWN" |
| done |
| |
| echo >&2 "===> ${container_name} is ready." |
| } |
| |
| # Run spark pi |
| function run_spark_pi() { |
| docker_run \ |
| "$SUBMIT_CONTAINER_NAME" \ |
| "$1" \ |
| "/opt/spark/bin/spark-submit --master spark://$MASTER_CONTAINER_NAME:$SPARK_MASTER_PORT --class org.apache.spark.examples.SparkPi /opt/spark/examples/jars/spark-examples_$SCALA_VERSION-$SPARK_VERSION.jar 20" |
| } |
| |
| # Run smoke standalone test |
| function run_smoke_test_in_standalone() { |
| local docker_run_command=$1 |
| |
| create_network |
| cleanup |
| |
| start_spark_master "${docker_run_command}" |
| start_spark_worker "${docker_run_command}" |
| |
| wait_container_ready "$MASTER_CONTAINER_NAME" "$SPARK_MASTER_WEBUI_HOST_PORT" |
| wait_container_ready "$WORKER_CONTAINER_NAME" "$SPARK_WORKER_WEBUI_HOST_PORT" |
| |
| run_spark_pi "${docker_run_command}" |
| |
| cleanup |
| remove_network |
| } |
| |
| # Run a master and worker and verify they start up and connect to each other successfully. |
| # And run a smoke test in standalone cluster. |
| function smoke_test() { |
| if [ -z "$IMAGE_URL" ]; then |
| echo >&2 "Image url is need, please set it with --image-url" |
| exit -1 |
| fi |
| |
| echo >&2 "===> Smoke test for $IMAGE_URL as root" |
| run_smoke_test_in_standalone |
| |
| echo >&2 "===> Smoke test for $IMAGE_URL as non-root" |
| run_smoke_test_in_standalone "--user spark" |
| } |
| |
| # Parse arguments |
| while (( "$#" )); do |
| case $1 in |
| --scala-version) |
| SCALA_VERSION="$2" |
| shift |
| ;; |
| --spark-version) |
| SPARK_VERSION="$2" |
| shift |
| ;; |
| --image-url) |
| IMAGE_URL="$2" |
| shift |
| ;; |
| *) |
| echo "Unexpected command line flag $2 $1." |
| exit 1 |
| ;; |
| esac |
| shift |
| done |
| |
| # Run smoke test |
| smoke_test |