From 20731fc11f3027a7e7a0d287283c27a178eed5f0 Mon Sep 17 00:00:00 2001 From: Tom Scavo <trscavo@internet2.edu> Date: Sun, 28 May 2017 10:57:54 -0400 Subject: [PATCH] Commit new executable --- bin/run_xslt_scripts.sh | 382 ++++++++++++++++++++++++++++++++++++++++ install.sh | 3 +- 2 files changed, 383 insertions(+), 2 deletions(-) create mode 100755 bin/run_xslt_scripts.sh diff --git a/bin/run_xslt_scripts.sh b/bin/run_xslt_scripts.sh new file mode 100755 index 0000000..bc6b39f --- /dev/null +++ b/bin/run_xslt_scripts.sh @@ -0,0 +1,382 @@ +#!/bin/bash + +####################################################################### +# Copyright 2017 Internet2 +# +# 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. +####################################################################### + +####################################################################### +# Help message +####################################################################### + +display_help () { +/bin/cat <<- HELP_MSG + This script applies an arbitrary sequence of XSLT scripts + against a SAML metadata aggregate. The output files will + be written to the output directory specified on the + command line. + + The script depends on cached metadata. It will not fetch + a metadata file from the server. + + Usage: ${0##*/} [-hv] -u MD_LOCATION -d OUT_DIR "XSL_FILENAME [OUTPUT_FILENAME]" ... + + The script takes an arbitrary sequence of compound command-line + arguments. The second sub-argument of each compound argument is + OPTIONAL. If no OUTPUT_FILENAME is given for a particular + XSL_FILENAME, the script computes an output filename as best + it can. + + Options: + -h Display this help message + -v Enable DEBUG mode + -u Specify the metadata location + -d Specify the output directory + + Option -h is mutually exclusive of all other options. + + Option -u specifies the location of the metadata file on the + network. The script uses the location to retrieve the file + from cache. If the file is not cached, the script will fail. + This option is REQUIRED. + + Option -d specifies the ultimate output directory, which is + usually a web directory. This option is REQUIRED. + + Output is all or none. The output files are computed + sequentially and assembled one-by-one in a temporary + directory. All of the output files are moved to the + destination directory at the same time. If even one output + file can not be computed---for whatever reason---none are + written to the output directory. + + ENVIRONMENT + + This script leverages a handful of environment variables: + + LIB_DIR A source library directory + CACHE_DIR A persistent HTTP cache + TMPDIR A temporary directory + LOG_FILE A persistent log file + LOG_LEVEL The global log level [0..5] + + All of the above environment variables are REQUIRED + except LOG_LEVEL, which defaults to LOG_LEVEL=3. + + The following environment variables are REQUIRED: + + $( printf " %s\n" ${env_vars[*]} ) + + The following directories MUST exist: + + $( printf " %s\n" ${dir_paths[*]} ) + + The following files MUST exist: + + $( printf " %s\n" $LOG_FILE ) + + CONFIGURATION + + The following source library files MUST be installed in LIB_DIR: + + $( printf " %s\n" ${lib_filenames[*]} ) + + EXAMPLES + + \$ ${0##*/} -h + \$ md_location=http://md.incommon.org/InCommon/InCommon-metadata-export.xml + \$ out_dir=/home/htdocs/www.incommonfederation.org/federation/metadata/ + \$ ${0##*/} -u \$md_location -d \$out_dir \\ + "list_all_IdPs_csv.xsl all_IdPs_exported.csv" \\ + "list_all_SPs_csv.xsl all_SPs_exported.csv" +HELP_MSG +} + +####################################################################### +# Bootstrap +####################################################################### + +script_name=${0##*/} # equivalent to basename $0 + +# required environment variables +env_vars[1]="LIB_DIR" +env_vars[2]="CACHE_DIR" +env_vars[3]="TMPDIR" +env_vars[4]="LOG_FILE" + +# check environment variables +for env_var in ${env_vars[*]}; do + eval "env_var_val=\${$env_var}" + if [ -z "$env_var_val" ]; then + echo "ERROR: $script_name requires env var $env_var" >&2 + exit 2 + fi +done + +# required directories +dir_paths[1]="$LIB_DIR" +dir_paths[2]="$CACHE_DIR" +dir_paths[3]="$TMPDIR" + +# check required directories +for dir_path in ${dir_paths[*]}; do + if [ ! -d "$dir_path" ]; then + echo "ERROR: $script_name: directory does not exist: $dir_path" >&2 + exit 2 + fi +done + +# check the log file +# devices such as /dev/tty and /dev/null are allowed +if [ ! -f "$LOG_FILE" ] && [[ $LOG_FILE != /dev/* ]]; then + echo "ERROR: $script_name: file does not exist: $LOG_FILE" >&2 + exit 2 +fi + +# default to INFO logging +if [ -z "$LOG_LEVEL" ]; then + LOG_LEVEL=3 +fi + +# library filenames +lib_filenames[1]="core_lib.sh" +lib_filenames[2]="http_tools.sh" + +# check lib files +for lib_filename in ${lib_filenames[*]}; do + lib_file="$LIB_DIR/$lib_filename" + if [ ! -f "$lib_file" ]; then + echo "ERROR: $script_name: lib file does not exist: $lib_file" >&2 + exit 2 + fi +done + +####################################################################### +# Process command-line options and arguments +####################################################################### + +help_mode=false; local_opts= +while getopts ":hvu:d:" opt; do + case $opt in + h) + help_mode=true + ;; + v) + LOG_LEVEL=4 + local_opts="$local_opts -$opt" + ;; + u) + md_location="$OPTARG" + ;; + d) + out_dir="$OPTARG" + ;; + \?) + echo "ERROR: $script_name: Unrecognized option: -$OPTARG" >&2 + exit 2 + ;; + :) + echo "ERROR: $script_name: Option -$OPTARG requires an argument" >&2 + exit 2 + ;; + esac +done + +if $help_mode; then + display_help + exit 0 +fi + +# check the metadata location +if [ -z "$md_location" ]; then + echo "ERROR: $script_name: no metadata location specified (option -u)" >&2 + exit 2 +fi + +# check the output directory +if [ -z "$out_dir" ]; then + echo "ERROR: $script_name: no output directory specified (option -d)" >&2 + exit 2 +fi +if [ ! -d "$out_dir" ]; then + echo "ERROR: $script_name: directory does not exist: $out_dir" >&2 + exit 2 +fi + +# check command-line arguments +shift $(( OPTIND - 1 )) +if [ $# -eq 0 ]; then + echo "ERROR: $script_name: wrong number of arguments: $# (at least one required)" >&2 + exit 2 +fi + +####################################################################### +# Functions +####################################################################### + +# process a compound command-line argument +# present that argument to this function as a pair of arguments: +# XSL_FILENAME [OUTPUT_FILENAME] +# if the latter is omitted, the function computes a suitable output filename +process_arg () { + + local xsl_file + local base_filename + local output_filename + + # check the command-line arguments + if [ $# -lt 1 -o $# -gt 2 ]; then + echo "ERROR: $FUNCNAME: incorrect number of arguments: $# (1 or 2 required)" >&2 + return 2 + fi + + # the first arg is an XSL filename + # the second arg is an (optional) output filename + + # does the first arg end in .xsl? + if [[ $1 != *.xsl ]]; then + echo "ERROR: $FUNCNAME: XSL filename does not end in .xsl: $1" >&2 + return 3 + fi + + # does the corresponding file exist? + xsl_file="$LIB_DIR/$1" + if [ ! -f "$xsl_file" ]; then + echo "ERROR: $FUNCNAME: lib file does not exist: $xsl_file" >&2 + exit 4 + fi + + # capture array elements + xsl_filenames+=("$1") + xsl_files+=("$xsl_file") + + # determine the output filename + output_filename="$2" + if [ -z "$output_filename" ]; then + + # compute the output filename + + # if the XSL filename is of the form + # base_filename_csv.xsl + # or + # base_filename_json.xsl + # then construct the output filename with the corresponding extension: + # base_filename.csv + # base_filename_.son + # otherwise the output filename is the XSL filename sans the .xsl extension + base_filename="${1%%.*}" + if [[ $base_filename =~ _(csv|json)$ ]]; then + output_filename=$( echo "$base_filename" | $_SED -e 's/^\(.*\)_\([^_]*\)$/\1.\2/' ) + else + output_filename="$base_filename" + fi + fi + + # capture remaining array elements + out_filenames+=("$output_filename") + out_files+=("${tmp_dir}/$output_filename") +} + +####################################################################### +# Initialization +####################################################################### + +# source lib files +for lib_filename in ${lib_filenames[*]}; do + lib_file="$LIB_DIR/$lib_filename" + source "$lib_file" + status_code=$? + if [ $status_code -ne 0 ]; then + echo "ERROR: $script_name failed ($status_code) to source lib file $lib_file" >&2 + exit 2 + fi +done + +# create a temporary subdirectory +tmp_dir="${TMPDIR%%/}/${script_name%%.*}_$$" +/bin/mkdir "$tmp_dir" +status_code=$? +if [ $status_code -ne 0 ]; then + echo "ERROR: $script_name failed ($status_code) to create tmp dir $tmp_dir" >&2 + exit 2 +fi + +# specify input file +xml_file="${tmp_dir}/saml-metadata.xml" + +# declare arrays +xsl_filenames=() +xsl_files=() +out_filenames=() +out_files=() + +# iterate over the command-line arguments +num_args=$# # TODO: simplify this loop +for (( i = 0; i < num_args; i++ )); do + + # process the next command-line arg + # (do not quote the arg) + process_arg $1 + status_code=$? + if [ $status_code -ne 0 ]; then + echo "ERROR: $script_name failed ($status_code) to process arg $1" >&2 + exit 2 + fi + + shift +done + +####################################################################### +# Main processing +####################################################################### + +print_log_message -I "$script_name BEGIN" + +# get a cached metadata file +print_log_message -I "$script_name retrieving cached metadata file: $md_location" +conditional_get $local_opts -C -d "$CACHE_DIR" -T "$tmp_dir" "$md_location" > "$xml_file" +status_code=$? +if [ $status_code -eq 1 ]; then + # metadata must be cached + print_log_message -E "$script_name: metadata file not cached: $md_location" + clean_up_and_exit -d "$tmp_dir" 1 +fi +if [ $status_code -gt 1 ]; then + print_log_message -E "$script_name: conditional_get failed ($status_code) on location: $md_location" + clean_up_and_exit -d "$tmp_dir" $status_code +fi +print_log_message -D "$script_name using XML file: $xml_file" + +# create the output files +for i in ${!out_files[*]}; do + print_log_message -I "$script_name writing output file: ${out_filenames[$i]}" + /usr/bin/xsltproc ${xsl_files[$i]} $xml_file > ${out_files[$i]} + status_code=$? + if [ $status_code -ne 0 ]; then + print_log_message -E "$script_name: xsltproc failed ($status_code) on stylesheet: ${xsl_files[$i]}" + clean_up_and_exit -d "$tmp_dir" $status_code + fi +done + +# move the output files to the web directory +print_log_message -I "$script_name moving output files to dir: $out_dir" +/bin/mv $( echo -n ${out_files[*]} ) $out_dir +status_code=$? +if [ $status_code -ne 0 ]; then + print_log_message -E "$script_name: mv failed ($status_code) to dir: $out_dir" + clean_up_and_exit -d "$tmp_dir" $status_code +fi + +print_log_message -I "$script_name END" +clean_up_and_exit -d "$tmp_dir" 0 diff --git a/install.sh b/install.sh index 102cb02..7a8aa4d 100755 --- a/install.sh +++ b/install.sh @@ -93,8 +93,7 @@ while read script_file; do fi done <<SCRIPTS $script_bin/bin/http_xsltproc.sh -$script_bin/bin/process_export_aggregate.sh -$script_bin/bin/process_main_aggregate.sh +$script_bin/bin/run_xslt_scripts.sh SCRIPTS # initialize lib dir