diff --git a/modules/install-consul/README.md b/modules/install-consul/README.md index e8f2647b..dea1258e 100644 --- a/modules/install-consul/README.md +++ b/modules/install-consul/README.md @@ -44,7 +44,7 @@ example](https://github.com/hashicorp/terraform-aws-consul/tree/master/examples/ The `install-consul` script accepts the following arguments: * `version VERSION`: Install Consul version VERSION. Optional if download-url is provided. -* `dowload-url URL`: Install the Consul package hosted in this url. Optional if version is provided. +* `download-url URL`: Install the Consul package hosted in this url. Optional if version is provided. * `path DIR`: Install Consul into folder DIR. Optional. * `user USER`: The install dirs will be owned by user USER. Optional. * `ca-file-path PATH`: Path to a PEM-encoded certificate authority used to encrypt and verify authenticity of client and server connections. Optional. diff --git a/modules/install-consul/install-consul b/modules/install-consul/install-consul index 03b856aa..ac53a779 100755 --- a/modules/install-consul/install-consul +++ b/modules/install-consul/install-consul @@ -41,30 +41,30 @@ function print_usage { } function log { - local readonly level="$1" - local readonly message="$2" - local readonly timestamp=$(date +"%Y-%m-%d %H:%M:%S") + local -r level="$1" + local -r message="$2" + local -r timestamp=$(date +"%Y-%m-%d %H:%M:%S") >&2 echo -e "${timestamp} [${level}] [$SCRIPT_NAME] ${message}" } function log_info { - local readonly message="$1" + local -r message="$1" log "INFO" "$message" } function log_warn { - local readonly message="$1" + local -r message="$1" log "WARN" "$message" } function log_error { - local readonly message="$1" + local -r message="$1" log "ERROR" "$message" } function assert_not_empty { - local readonly arg_name="$1" - local readonly arg_value="$2" + local -r arg_name="$1" + local -r arg_value="$2" if [[ -z "$arg_value" ]]; then log_error "The value for '$arg_name' cannot be empty" @@ -74,10 +74,10 @@ function assert_not_empty { } function assert_either_or { - local readonly arg1_name="$1" - local readonly arg1_value="$2" - local readonly arg2_name="$3" - local readonly arg2_value="$4" + local -r arg1_name="$1" + local -r arg1_value="$2" + local -r arg2_name="$3" + local -r arg2_value="$4" if [[ -z "$arg1_value" && -z "$arg2_value" ]]; then log_error "Either the value for '$arg1_name' or '$arg2_name' must be passed, both cannot be empty" @@ -86,6 +86,30 @@ function assert_either_or { fi } +# A retry function that attempts to run a command a number of times and returns the output +function retry { + local -r cmd="$1" + local -r description="$2" + + for i in $(seq 1 5); do + log_info "$description" + + # The boolean operations with the exit status are there to temporarily circumvent the "set -e" at the + # beginning of this script which exits the script immediatelly for error status while not losing the exit status code + output=$(eval "$cmd") && exit_status=0 || exit_status=$? + log_info "$output" + if [[ $exit_status -eq 0 ]]; then + echo "$output" + return + fi + log_warn "$description failed. Will sleep for 10 seconds and try again." + sleep 10 + done; + + log_error "$description failed after 5 attempts." + exit $exit_status +} + # Install steps are based on: http://unix.stackexchange.com/a/291098/215969 function install_supervisord_debian { sudo apt-get install -y supervisor @@ -166,12 +190,12 @@ function install_dependencies { } function user_exists { - local readonly username="$1" + local -r username="$1" id "$username" >/dev/null 2>&1 } function create_consul_user { - local readonly username="$1" + local -r username="$1" if $(user_exists "$username"); then echo "User $username already exists. Will not create again." @@ -182,8 +206,8 @@ function create_consul_user { } function create_consul_install_paths { - local readonly path="$1" - local readonly username="$2" + local -r path="$1" + local -r username="$2" log_info "Creating install dirs for Consul at $path" sudo mkdir -p "$path" @@ -198,24 +222,25 @@ function create_consul_install_paths { } function fetch_binary { - local readonly version="$1" + local -r version="$1" local download_url="$2" if [[ -z "$download_url" && -n "$version" ]]; then download_url="https://releases.hashicorp.com/consul/${version}/consul_${version}_linux_amd64.zip" fi - log_info "Downloading Consul to $DOWNLOAD_PACKAGE_PATH" - curl -o "$DOWNLOAD_PACKAGE_PATH" "$download_url" --location --silent --fail --show-error + retry \ + "curl -o '$DOWNLOAD_PACKAGE_PATH' '$download_url' --location --silent --fail --show-error" \ + "Downloading Consul to $DOWNLOAD_PACKAGE_PATH" } function install_binary { - local readonly install_path="$1" - local readonly username="$2" + local -r install_path="$1" + local -r username="$2" - local readonly bin_dir="$install_path/bin" - local readonly consul_dest_path="$bin_dir/consul" - local readonly run_consul_dest_path="$bin_dir/run-consul" + local -r bin_dir="$install_path/bin" + local -r consul_dest_path="$bin_dir/consul" + local -r run_consul_dest_path="$bin_dir/run-consul" unzip -d /tmp "$DOWNLOAD_PACKAGE_PATH" @@ -224,7 +249,7 @@ function install_binary { sudo chown "$username:$username" "$consul_dest_path" sudo chmod a+x "$consul_dest_path" - local readonly symlink_path="$SYSTEM_BIN_DIR/consul" + local -r symlink_path="$SYSTEM_BIN_DIR/consul" if [[ -f "$symlink_path" ]]; then log_info "Symlink $symlink_path already exists. Will not add again." else @@ -239,14 +264,14 @@ function install_binary { } function install_tls_certificates { - local readonly path="$1" - local readonly user="$2" - local readonly ca_file_path="$3" - local readonly cert_file_path="$4" - local readonly key_file_path="$5" - - local readonly consul_tls_certs_path="$path/tls" - local readonly ca_certs_path="$consul_tls_certs_path/ca" + local -r path="$1" + local -r user="$2" + local -r ca_file_path="$3" + local -r cert_file_path="$4" + local -r key_file_path="$5" + + local -r consul_tls_certs_path="$path/tls" + local -r ca_certs_path="$consul_tls_certs_path/ca" log_info "Moving TLS certs to $consul_tls_certs_path and $ca_certs_path" diff --git a/modules/install-dnsmasq/install-dnsmasq b/modules/install-dnsmasq/install-dnsmasq index c4797c4b..ee8e007e 100755 --- a/modules/install-dnsmasq/install-dnsmasq +++ b/modules/install-dnsmasq/install-dnsmasq @@ -34,30 +34,30 @@ function print_usage { } function log { - local readonly level="$1" - local readonly message="$2" - local readonly timestamp=$(date +"%Y-%m-%d %H:%M:%S") + local -r level="$1" + local -r message="$2" + local -r timestamp=$(date +"%Y-%m-%d %H:%M:%S") >&2 echo -e "${timestamp} [${level}] [$SCRIPT_NAME] ${message}" } function log_info { - local readonly message="$1" + local -r message="$1" log "INFO" "$message" } function log_warn { - local readonly message="$1" + local -r message="$1" log "WARN" "$message" } function log_error { - local readonly message="$1" + local -r message="$1" log "ERROR" "$message" } function assert_not_empty { - local readonly arg_name="$1" - local readonly arg_value="$2" + local -r arg_name="$1" + local -r arg_value="$2" if [[ -z "$arg_value" ]]; then log_error "The value for '$arg_name' cannot be empty" @@ -75,7 +75,7 @@ function has_apt_get { } function install_dnsmasq { - local readonly consul_ip="$1" + local -r consul_ip="$1" log_info "Installing Dnsmasq" @@ -95,9 +95,9 @@ function install_dnsmasq { } function write_consul_config { - local readonly consul_domain="$1" - local readonly consul_ip="$2" - local readonly consul_port="$3" + local -r consul_domain="$1" + local -r consul_ip="$2" + local -r consul_port="$3" log_info "Configuring Dnsmasq to forward lookups of the '$consul_domain' domain to $consul_ip:$consul_port in $CONSUL_DNS_MASQ_CONFIG_FILE" mkdir -p "$DNS_MASQ_CONFIG_DIR" diff --git a/modules/run-consul/run-consul b/modules/run-consul/run-consul index 9ae89f4b..a8352648 100755 --- a/modules/run-consul/run-consul +++ b/modules/run-consul/run-consul @@ -70,37 +70,37 @@ function print_usage { } function log { - local readonly level="$1" - local readonly message="$2" - local readonly timestamp=$(date +"%Y-%m-%d %H:%M:%S") + local -r level="$1" + local -r message="$2" + local -r timestamp=$(date +"%Y-%m-%d %H:%M:%S") >&2 echo -e "${timestamp} [${level}] [$SCRIPT_NAME] ${message}" } function log_info { - local readonly message="$1" + local -r message="$1" log "INFO" "$message" } function log_warn { - local readonly message="$1" + local -r message="$1" log "WARN" "$message" } function log_error { - local readonly message="$1" + local -r message="$1" log "ERROR" "$message" } # Based on code from: http://stackoverflow.com/a/16623897/483528 function strip_prefix { - local readonly str="$1" - local readonly prefix="$2" + local -r str="$1" + local -r prefix="$2" echo "${str#$prefix}" } function assert_not_empty { - local readonly arg_name="$1" - local readonly arg_value="$2" + local -r arg_name="$1" + local -r arg_value="$2" if [[ -z "$arg_value" ]]; then log_error "The value for '$arg_name' cannot be empty" @@ -110,12 +110,12 @@ function assert_not_empty { } function lookup_path_in_instance_metadata { - local readonly path="$1" + local -r path="$1" curl --silent --show-error --location "$EC2_INSTANCE_METADATA_URL/$path/" } function lookup_path_in_instance_dynamic_data { - local readonly path="$1" + local -r path="$1" curl --silent --show-error --location "$EC2_INSTANCE_DYNAMIC_DATA_URL/$path/" } @@ -132,8 +132,8 @@ function get_instance_region { } function get_instance_tags { - local readonly instance_id="$1" - local readonly instance_region="$2" + local -r instance_id="$1" + local -r instance_region="$2" local tags="" local count_tags="" @@ -159,8 +159,8 @@ function get_instance_tags { } function get_asg_size { - local readonly asg_name="$1" - local readonly aws_region="$2" + local -r asg_name="$1" + local -r aws_region="$2" local asg_json="" log_info "Looking up the size of the Auto Scaling Group $asg_name in $aws_region" @@ -169,8 +169,8 @@ function get_asg_size { } function get_cluster_size { - local readonly instance_tags="$1" - local readonly aws_region="$2" + local -r instance_tags="$1" + local -r aws_region="$2" local asg_name="" asg_name=$(get_tag_value "$instance_tags" "$AWS_ASG_TAG_KEY") @@ -185,14 +185,14 @@ function get_cluster_size { # Get the value for a specific tag from the tags JSON returned by the AWS describe-tags: # https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-tags.html function get_tag_value { - local readonly tags="$1" - local readonly tag_key="$2" + local -r tags="$1" + local -r tag_key="$2" echo "$tags" | jq -r ".Tags[] | select(.Key == \"$tag_key\") | .Value" } function assert_is_installed { - local readonly name="$1" + local -r name="$1" if [[ ! $(command -v ${name}) ]]; then log_error "The binary '$name' is required by this script but is not installed or in the system's PATH." @@ -208,26 +208,26 @@ function join_by { } function generate_consul_config { - local readonly server="${1}" - local readonly config_dir="${2}" - local readonly user="${3}" - local readonly cluster_tag_key="${4}" - local readonly cluster_tag_value="${5}" - local readonly datacenter="${6}" - local readonly enable_gossip_encryption="${7}" - local readonly gossip_encryption_key="${8}" - local readonly enable_rpc_encryption="${9}" - local readonly ca_path="${10}" - local readonly cert_file_path="${11}" - local readonly key_file_path="${12}" - local readonly cleanup_dead_servers="${13}" - local readonly last_contact_threshold="${14}" - local readonly max_trailing_logs="${15}" - local readonly server_stabilization_time="${16}" - local readonly redundancy_zone_tag="${17}" - local readonly disable_upgrade_migration="${18}" - local readonly upgrade_version_tag=${19} - local readonly config_path="$config_dir/$CONSUL_CONFIG_FILE" + local -r server="${1}" + local -r config_dir="${2}" + local -r user="${3}" + local -r cluster_tag_key="${4}" + local -r cluster_tag_value="${5}" + local -r datacenter="${6}" + local -r enable_gossip_encryption="${7}" + local -r gossip_encryption_key="${8}" + local -r enable_rpc_encryption="${9}" + local -r ca_path="${10}" + local -r cert_file_path="${11}" + local -r key_file_path="${12}" + local -r cleanup_dead_servers="${13}" + local -r last_contact_threshold="${14}" + local -r max_trailing_logs="${15}" + local -r server_stabilization_time="${16}" + local -r redundancy_zone_tag="${17}" + local -r disable_upgrade_migration="${18}" + local -r upgrade_version_tag=${19} + local -r config_path="$config_dir/$CONSUL_CONFIG_FILE" local instance_id="" local instance_ip_address="" @@ -316,14 +316,14 @@ EOF } function generate_supervisor_config { - local readonly supervisor_config_path="$1" - local readonly consul_config_dir="$2" - local readonly consul_data_dir="$3" - local readonly consul_log_dir="$4" - local readonly consul_bin_dir="$5" - local readonly consul_user="$6" + local -r supervisor_config_path="$1" + local -r consul_config_dir="$2" + local -r consul_data_dir="$3" + local -r consul_log_dir="$4" + local -r consul_bin_dir="$5" + local -r consul_user="$6" shift 6 - local readonly environment=("$@") + local -r environment=("$@") log_info "Creating Supervisor config file to run Consul in $supervisor_config_path" cat > "$supervisor_config_path" <