#!/bin/bash set -u # This script downloads, installs, and configures a sample Helix Core # extension from the Public Depot #============================================================================== # Declarations and Environment declare ThisScript="${0##*/}" declare Version=1.2.0 declare ThisUser= declare ThisHost=${HOSTNAME%%.*} declare CmdLine="${0} $*" declare DemoHome="/home/perforce/ExtensionDemo" declare DemoLogs="$DemoHome/logs" declare ExtensionName="login_motd" declare ExtensionProvider="ExampleInc" declare ExtensionInstance="LoginMOTDExt" declare ExtensionInstanceFile="NewExtension.extension-instance.p4s" declare ExtensionConfig="$ExtensionProvider::$ExtensionInstance" declare ExtensionPackage="${ExtensionName}.p4-extension" declare ExtensionDir="$DemoHome/$ExtensionName" declare OldExtensionDir= declare OldExtensionPackage= declare -i Debug=${DEBUG:-0} declare -a SampleFiles declare -i ErrorCount=0 declare -i CMDEXITCODE=0 declare -i NoOp=1 declare Cmd= declare Log= declare LogLink= declare H1="==============================================================================" declare H2="==============================================================================" declare -i ErrorCount=0 declare -i i=0 declare RunHost=bos-helix-01 declare TmpFile= #============================================================================== # Static Data SampleFiles[i]="https://swarm.workshop.perforce.com/download/guest/perforce_software/extensions/main/login_motd/main.lua" i+=1 SampleFiles[i]="https://swarm.workshop.perforce.com/download/guest/perforce_software/extensions/main/login_motd/manifest.json" i+=1 SampleFiles[i]="https://swarm.workshop.perforce.com/download/guest/perforce_software/extensions/main/login_motd/ExtUtils.lua" i+=1 #============================================================================== # Local Functions function msg () { echo -e "$*"; } function dbg () { [[ "$Debug" -eq 0 ]] || msg "DEBUG: $*"; } function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; } function bail () { errmsg "${1:-Unknown Error}"; exit "$ErrorCount"; } #------------------------------------------------------------------------------ # Functions run($cmdAndArgs, $desc, $ignoreNoOp) # # This function is similar to functions defined in SDP core libraries, but we # need to duplicate them here since this script runs before the SDP is # available on the machine (and we require dependencies for this # script). function run { local cmdAndArgs="${1:-echo Testing run}" local desc="${2:-}" local -i ignoreNoOp=${3:-0} [[ -n "$desc" ]] && msg "$desc" if [[ "$NoOp" -eq 0 || "$ignoreNoOp" -eq 1 ]]; then msg "Running: $cmdAndArgs" eval "$cmdAndArgs" CMDEXITCODE=$? else msg "NO_OP: Would have run: $cmdAndArgs" CMDEXITCODE=0 fi return $CMDEXITCODE } #------------------------------------------------------------------------------ # Function: terminate function terminate { # Disable signal trapping. trap - EXIT SIGINT SIGTERM dbg "$ThisScript: EXITCODE: $ErrorCount" # Stop logging. [[ "$Log" == off ]] || msg "\\nLog is: $Log\\n${H1}\\n" # With the trap removed, exit. exit "$ErrorCount" } #------------------------------------------------------------------------------ # Function: usage (required function) # # Input: # $1 - style, either -h (for short form) or -man (for man-page like format). #------------------------------------------------------------------------------ function usage { declare style=${1:--h} msg "USAGE for $ThisScript v$Version: $ThisScript [-y] [-dh <demo_home>] [-L <log>] [-d|-D] or $ThisScript [-h|-man] " if [[ $style == -man ]]; then msg " DESCRIPTION: This script does a demo of an Extensions install. OPTIONS: -L <log> Specify the path to a log file, or the special value 'off' to disable logging. By default, all output (stdout and stderr) goes to: /tmp/${ThisScript%.sh}.<timestamp>.log NOTE: This script is self-logging. That is, output displayed on the screen is simultaneously captured in the log file. It is not necessary (nor harmful) to use redirection operators like '> log' or '2>&1' or 'tee'. This script uses a fixed LogLink of /tmp/${ThisScript%.sh}.log which is updated to point to the newly created log for each run, so that this link reliably points to the most recent execution of the script. HELP OPTIONS: -h Display short help message -man Display man-style help message DEBUGGING OPTIONS: -d Enable debug messages. -D Use bash 'set -x' extreme debugging verbosity. Implies '-d'. LOGGING: This script is self-logging. That is, output displayed on the screen is simultaneously captured in the log file. It is not necessary (nor harmful) to use redirection operators like '> log' or '2>&1' or 'tee'. This script uses a fixed log symlink /tmp/${ThisScript%.sh}.log which is updated to point to the newly created log for each run, so that this symlink reliably points to the most recent execution of the script (unless '-L off' was used). EXAMPLES: Before running this script, get the Battle Schoo Lab Environment ready by running 'lab qa' while logged in as student@bsw-lab-ui. This usually takes about 5 minutes. Then get onto the machine whe the demo is run by using the 's1' alias to become perforce@bos-helix-01 with the proper shell environment loaded. Then proceed like so: \$ cd /home/perforce/ExtensionDemo Do a dry run: \$ ./$ThisScript Do it for real: \$ ./$ThisScript -y " fi exit 2 } #============================================================================== # Command Line Processing declare -i shiftArgs=0 set +u while [[ $# -gt 0 ]]; do case $1 in (-dh) DemoHome="$2"; shiftArgs=1;; (-h) usage -h;; (-man) usage -man;; (-y) NoOp=0;; (-L) Log="$2"; shiftArgs=1;; (-n) NoOp=1;; (-d) Debug=1;; (-D) Debug=1; set -x;; # Debug; use 'set -x' mode. (-*) usage -h "Unknown option ($1).";; (*) usage -h "Unknown parameter ($1).";; esac # Shift (modify $#) the appropriate number of times. shift; while [[ $shiftArgs -gt 0 ]]; do [[ $# -eq 0 ]] && usageError "Bad usage." shiftArgs=$shiftArgs-1 shift done done set -u #============================================================================== # Command Line Verification # shellcheck disable=SC1091 source /p4/common/bin/p4_vars 1 ||\ bail "Could not do: source /p4/common/bin/p4_vars 1" [[ -n "$Log" ]] || Log="$DemoLogs/${ThisScript%.sh}.$(date +'%Y-%m-%d-%H%M%S').log" LogLink="$DemoLogs/${ThisScript%.sh}.log" [[ -d "$DemoLogs" ]] || mkdir "$DemoLogs" || bail "Could not do: mkdir $DemoLogs" #============================================================================== # Main Program trap terminate EXIT SIGINT SIGTERM if [[ "$Log" != off ]]; then touch "$Log" || bail "Couldn't touch log file [$Log]." # Redirect stdout and stderr to a log file. exec > >(tee "$Log") exec 2>&1 # Setup /tmp/test_sdp.log symlink so it points to the current log. rm -f "$LogLink" ln -s "$Log" "$LogLink" msg "${H1}\\nLog is: $Log\\n" fi ThisUser=$(id -n -u) msg "Started $ThisScript v$Version as $ThisUser@$ThisHost on $(date) as pid $$:\\nInitial Command Line:\\n$CmdLine\\n" msg "Starting preflight checks and cleanup from earlier runs." if [[ $ThisHost == "$RunHost" ]]; then msg "Verified: Running on $RunHost." else bail "Not configured to run on host $ThisHost. Run only on $RunHost." fi if [[ -d "$ExtensionDir" ]]; then # mv ExtensionDir to ExtensDir.old.<timestamp> OldExtensionDir="${ExtensionDir%/*}/${ExtensionDir##*/}.old.$(date +'%Y-%m-%d-%H%M%S')" run "mv $ExtensionDir $OldExtensionDir" "Moving aside extension dir from an earlier run." fi if [[ -f "$ExtensionPackage" ]]; then OldExtensionPackage="${ExtensionPackage}.old.$(date +'%Y-%m-%d-%H%M%S')" run "mv $ExtensionPackage $OldExtensionPackage" "Moving aside extension package from an earlier run." fi msg "Checking to see if exenstion aready exists." if p4 extension --configure $ExtensionConfig -o > /dev/null 2>&1; then Cmd="p4 extension --delete $ExtensionConfig --yes" run "$Cmd" "Removing older version of extension" ||\ bail "Could not do: $Cmd" fi msg "${H2}\\nPreflight checks and cleanup complete. Setting configurables." cd "$DemoHome" || bail "Could not do: cd $DemoHome" msg "Operating in: $PWD" run "p4 configure show server.extensions.allow.unsigned" \ "Show if unsigned server-side Extensions are allowed to run." ||\ errmsg "Could not show configurable." run "p4 configure set server.extensions.allow.unsigned=1" \ "Allow unsigned Extensions are allowed to be installed and run (for demo)." ||\ bail "Could not set configurable. Aborting." run "p4 configure show run.clientexts.allow" \ "Show if client-side Extensions are allowed to run." ||\ errmsg "Could not show configurable." run "p4 configure set run.clientexts.allow=1" \ "Allow client-side Extensions to run (though this demo only illustrates server-side extensons)." ||\ bail "Could not set configurable. Aborting." msg "${H2}\\nConfigurables are set. Downloading files." Cmd="p4 extension --sample $ExtensionName" run "$Cmd" "STEP 1: Create sample extension template." ||\ bail "Could not create sample extension." msg "STEP 2: Code your extension in Lua. Here we just download sample code." for url in "${SampleFiles[@]}"; do Cmd="curl -s -L -o $ExtensionDir/${url##*/} $url" run "$Cmd" "Acquring sample file: $url" ||\ bail "Could not do: $Cmd" done msg "${H2}\\nDownloads complete. Showing default login behavior (pre-extension install)." if [[ "$NoOp" -eq 0 ]]; then msg "Running: p4 login < \$SDP_ADMIN_PASSWORD_FILE" p4 login < "$SDP_ADMIN_PASSWORD_FILE" else msg "NO_OP: Would have run: p4 login < \$SDP_ADMIN_PASSWORD_FILE" fi msg "${H2}\\nLoading extensions into p4d." Cmd="p4 extension --package $ExtensionName" run "$Cmd" "STEP 3: Package your local work to create $ExtensionPackage." ||\ bail "Extension package creation failed." Cmd="p4 extension --install $ExtensionName.p4-extension" run "$Cmd" "STEP 4: Preview install of extension $ExtensionName." ||\ bail "Extension install preview failed." Cmd="p4 extension --install $ExtensionName.p4-extension --yes" run "$Cmd" "STEP 5: Install extension $ExtensionName." ||\ bail "Extension install failed." TmpFile=$(mktemp) Cmd="p4 extension --configure $ExtensionConfig" if [[ "$NoOp" -eq 0 ]]; then msg "Displaying extension global config." msg "Running: $Cmd -o > $TmpFile" if $Cmd -o > "$TmpFile"; then msg "Tweaking Extension User (sampleExtensionsUser -> perforce)." sed -i -e 's/sampleExtensionsUser/perforce/g' "$TmpFile" msg "=== BEGIN Extension global config contents ===" cat "$TmpFile" msg "=== END Extension global config contents ===" msg "Running: $Cmd -i < $TmpFile" if eval "$Cmd -i < $TmpFile"; then msg "Extension config tweaked successfully." else bail "Extension config tweak failed." fi else bail "Displaying Extension global config failed." fi else msg "NO_OP: Would have run: $Cmd\\n...and then changed sampleExtensionsUser to perforce." fi Cmd="p4 extension --configure $ExtensionConfig --name $ExtensionName::$ExtensionInstance" if [[ "$NoOp" -eq 0 ]]; then msg "STEP 6: Load Extension Instance config with site-local values for Extension configs, e.g. the motd text to display on login." msg "=== BEGIN Extension instance config contents ===" cat "$ExtensionInstanceFile" msg "=== END Extension instance config contents ===" msg "Running: $Cmd -i < $ExtensionInstanceFile" if eval "$Cmd -i < $ExtensionInstanceFile"; then msg "Extension instance config loaded successfully." else bail "Extension instance config load failed." fi else msg "NO_OP: Would have run: $Cmd\\n...and then added instance config." fi msg "${H2}\\nShowing modified login behavior (with motd installed)." if [[ "$NoOp" -eq 0 ]]; then msg "Running: p4 login < \$SDP_ADMIN_PASSWORD_FILE" p4 login < "$SDP_ADMIN_PASSWORD_FILE" else msg "NO_OP: Would have run: p4 login < \$SDP_ADMIN_PASSWORD_FILE" fi if [[ "$ErrorCount" -eq 0 ]]; then msg "${H1}\\nDemonsration complete. Enjoy Extensions.\\n" else errmsg "Demo is done, but there were errors. Review the output carefully." ErrorCount=$((ErrorCount-1)) fi # Illustrate using $SECONDS to display runtime of a script. msg "Time: Demo took about $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\n" # See the terminate() function, which is really where this script exits. exit "$ErrorCount"
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#6 | 30818 | Perforce maintenance |
Adjust location of logs. Added sample log. |
||
#5 | 30817 | Perforce maintenance | Working version. | ||
#4 | 30811 | Perforce maintenance |
Change from using 2019.1 to using main versions. Added missing instance config load. |
||
#3 | 30807 | Perforce maintenance | Bug fixes. | ||
#2 | 30806 | Perforce maintenance | Added more commands, still WIP. | ||
#1 | 30795 | Perforce maintenance | Added ExtensionsDemo.sh script and its .shellcheckrc file. |