summaryrefslogtreecommitdiff
path: root/deps
diff options
context:
space:
mode:
authorYehonal <yehonal.azeroth@gmail.com>2018-07-15 22:40:49 +0200
committerYehonal <yehonal.azeroth@gmail.com>2018-07-15 22:51:17 +0200
commit85388901cf6a69659569ad751767fd7108b25a3c (patch)
treea004b01dfd378841c2ee473023313ade212118d7 /deps
parent07a451e1402cf8a7c24cf6196d541d304f5dcff2 (diff)
Rewrite of bash system
+ Implemented new dashboard menu + some fixes for db_assembler + new module installation process with version check via json files + some fixes to modules installer + implemented simple crossplatform worldserver and authserver restarters + new compiler script + client data downloader (beta) + various other fixes
Diffstat (limited to 'deps')
-rw-r--r--deps/jsonpath/.gitignore5
-rw-r--r--deps/jsonpath/.travis.yml10
-rw-r--r--deps/jsonpath/CNAME1
-rw-r--r--deps/jsonpath/JSONPath.sh857
-rw-r--r--deps/jsonpath/LICENSE.APACHE215
-rw-r--r--deps/jsonpath/LICENSE.MIT24
-rw-r--r--deps/jsonpath/MANIFEST.in3
-rw-r--r--deps/jsonpath/README.md491
-rw-r--r--deps/jsonpath/_config.yml1
-rw-r--r--deps/jsonpath/all-tests.sh33
-rw-r--r--deps/jsonpath/package.json19
-rw-r--r--deps/jsonpath/setup.py31
-rw-r--r--deps/semver_bash/.gitignore4
-rw-r--r--deps/semver_bash/LICENSE26
-rw-r--r--deps/semver_bash/README.md31
-rw-r--r--deps/semver_bash/semver.sh130
-rw-r--r--deps/semver_bash/semver_test.sh151
17 files changed, 1832 insertions, 0 deletions
diff --git a/deps/jsonpath/.gitignore b/deps/jsonpath/.gitignore
new file mode 100644
index 0000000000..36ed3d2069
--- /dev/null
+++ b/deps/jsonpath/.gitignore
@@ -0,0 +1,5 @@
+test/errlog
+test/outlog
+
+# vi .swp files
+.*.swp
diff --git a/deps/jsonpath/.travis.yml b/deps/jsonpath/.travis.yml
new file mode 100644
index 0000000000..acf1f26295
--- /dev/null
+++ b/deps/jsonpath/.travis.yml
@@ -0,0 +1,10 @@
+language: python
+
+addons:
+ apt:
+ packages:
+ - bash
+
+# Whatever the current shebang, replace with hardcoded shell
+script: >
+ ./all-tests.sh
diff --git a/deps/jsonpath/CNAME b/deps/jsonpath/CNAME
new file mode 100644
index 0000000000..4f3d0812c3
--- /dev/null
+++ b/deps/jsonpath/CNAME
@@ -0,0 +1 @@
+jsonpath.obdi.io \ No newline at end of file
diff --git a/deps/jsonpath/JSONPath.sh b/deps/jsonpath/JSONPath.sh
new file mode 100644
index 0000000000..a03752e130
--- /dev/null
+++ b/deps/jsonpath/JSONPath.sh
@@ -0,0 +1,857 @@
+#!/bin/bash
+
+# ---------------------------------------------------------------------------
+# GLOBALS
+# ---------------------------------------------------------------------------
+
+DEBUG=0
+INCLEMPTY=0
+NOCASE=0
+WHOLEWORD=0
+FILE=
+NO_HEAD=0
+NORMALIZE_SOLIDUS=0
+BRIEF=0
+PASSTHROUGH=0
+JSON=0
+PRINT=1
+MULTIPASS=0
+FLATTEN=0
+STDINFILE=/var/tmp/JSONPath.$$.stdin
+STDINFILE2=/var/tmp/JSONPath.$$.stdin2
+PASSFILE=/var/tmp/JSONPath.$$.pass1
+declare -a INDEXMATCH_QUERY
+
+# ---------------------------------------------------------------------------
+main() {
+# ---------------------------------------------------------------------------
+# It all starts here
+
+ parse_options "$@"
+
+ trap cleanup EXIT
+
+ if [[ $QUERY == *'?(@'* ]]; then
+ # This will be a multipass query
+
+ [[ -n $FILE ]] && STDINFILE=$FILE
+ [[ -z $FILE ]] && cat >$STDINFILE
+
+ while true; do
+ tokenize_path
+ create_filter
+
+ cat "$STDINFILE" | tokenize | parse | filter | indexmatcher >$PASSFILE
+
+ [[ $MULTIPASS -eq 1 ]] && {
+ # replace filter expression with index sequence
+ SET=$(sed -rn 's/.*,([0-9]+)[],].*/\1/p' $PASSFILE | tr '\n' ,)
+ SET=${SET%,}
+ QUERY=$(echo $QUERY | sed "s/?(@[^)]\+)/$SET/")
+ [[ $DEBUG -eq 1 ]] && echo "QUERY=$QUERY"
+ reset
+ continue
+ }
+
+ cat $PASSFILE | flatten | json | brief
+
+ break
+ done
+
+ else
+
+ tokenize_path
+ create_filter
+
+ if [[ $PASSTHROUGH -eq 1 ]]; then
+ JSON=1
+ flatten | json
+ elif [[ -z $FILE ]]; then
+ tokenize | parse | filter | indexmatcher | flatten | json | brief
+ else
+ cat "$FILE" | tokenize | parse | filter | indexmatcher | flatten | \
+ json | brief
+ fi
+
+ fi
+}
+
+# ---------------------------------------------------------------------------
+reset() {
+# ---------------------------------------------------------------------------
+
+ # Reset some vars
+ declare -a INDEXMATCH_QUERY
+ PATHTOKENS=
+ FILTER=
+ OPERATOR=
+ RHS=
+ MULTIPASS=0
+}
+
+# ---------------------------------------------------------------------------
+cleanup() {
+# ---------------------------------------------------------------------------
+
+ [[ -e "$PASSFILE" ]] && rm -f "$PASSFILE"
+ [[ -e "$STDINFILE2" ]] && rm -f "$STDINFILE2"
+ [[ -z "$FILE" && -e "$STDINFILE" ]] && rm -f "$STDINFILE"
+}
+
+# ---------------------------------------------------------------------------
+usage() {
+# ---------------------------------------------------------------------------
+
+ echo
+ echo "Usage: JSONPath.sh [-b] [j] [-h] [-f FILE] [pattern]"
+ echo
+ echo "pattern - the JSONPath query. Defaults to '$.*' if not supplied."
+ #echo "-s - Remove escaping of the solidus symbol (straight slash)."
+ echo "-b - Brief. Only show values."
+ echo "-j - JSON ouput."
+ echo "-u - Strip unnecessary leading path elements."
+ echo "-i - Case insensitive."
+ echo "-p - Pass-through to the JSON parser."
+ echo "-w - Match whole words only (for filter script expression)."
+ echo "-f FILE - Read a FILE instead of stdin."
+ #echo "-n - No-head. Do not show nodes that have no path (lines that start with [])."
+ echo "-h - This help text."
+ echo
+}
+
+# ---------------------------------------------------------------------------
+parse_options() {
+# ---------------------------------------------------------------------------
+
+ set -- "$@"
+ local ARGN=$#
+ while [ "$ARGN" -ne 0 ]
+ do
+ case $1 in
+ -h) usage
+ exit 0
+ ;;
+ -f) shift
+ FILE=$1
+ ;;
+ -i) NOCASE=1
+ ;;
+ -j) JSON=1
+ ;;
+ -n) NO_HEAD=1
+ ;;
+ -b) BRIEF=1
+ ;;
+ -u) FLATTEN=1
+ ;;
+ -p) PASSTHROUGH=1
+ ;;
+ -w) WHOLEWORD=1
+ ;;
+ -s) NORMALIZE_SOLIDUS=1
+ ;;
+ ?*) QUERY=$1
+ ;;
+ esac
+ shift 1
+ ARGN=$((ARGN-1))
+ done
+ [[ -z $QUERY ]] && QUERY='$.*'
+}
+
+# ---------------------------------------------------------------------------
+awk_egrep() {
+# ---------------------------------------------------------------------------
+ local pattern_string=$1
+
+ gawk '{
+ while ($0) {
+ start=match($0, pattern);
+ token=substr($0, start, RLENGTH);
+ print token;
+ $0=substr($0, start+RLENGTH);
+ }
+ }' pattern="$pattern_string"
+}
+
+# ---------------------------------------------------------------------------
+tokenize() {
+# ---------------------------------------------------------------------------
+# json parsing
+
+ local GREP
+ local ESCAPE
+ local CHAR
+
+ if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1
+ then
+ GREP='egrep -ao --color=never'
+ else
+ GREP='egrep -ao'
+ fi
+
+ if echo "test string" | egrep -o "test" >/dev/null 2>&1
+ then
+ ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
+ CHAR='[^[:cntrl:]"\\]'
+ else
+ GREP=awk_egrep
+ ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
+ CHAR='[^[:cntrl:]"\\\\]'
+ fi
+
+ local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
+ local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
+ local KEYWORD='null|false|true'
+ local SPACE='[[:space:]]+'
+
+ # Force zsh to expand $A into multiple words
+ local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$')
+ if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi
+ $GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$"
+ if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi
+}
+
+# ---------------------------------------------------------------------------
+tokenize_path () {
+# ---------------------------------------------------------------------------
+ local GREP
+ local ESCAPE
+ local CHAR
+
+ if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1
+ then
+ GREP='egrep -ao --color=never'
+ else
+ GREP='egrep -ao'
+ fi
+
+ if echo "test string" | egrep -o "test" >/dev/null 2>&1
+ then
+ CHAR='[^[:cntrl:]"\\]'
+ else
+ GREP=awk_egrep
+ #CHAR='[^[:cntrl:]"\\\\]'
+ fi
+
+ local WILDCARD='\*'
+ local WORD='[ A-Za-z0-9_-]*'
+ local INDEX="\\[$WORD(:$WORD){0,2}\\]"
+ local INDEXALL="\\[\\*\\]"
+ local STRING="[\\\"'][^[:cntrl:]\\\"']*[\\\"']"
+ local SET="\\[($WORD|$STRING)(,($WORD|$STRING))*\\]"
+ local FILTER='\?\(@[^)]+'
+ local DEEPSCAN="\\.\\."
+ local SPACE='[[:space:]]+'
+
+ # Force zsh to expand $A into multiple words
+ local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$')
+ if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi
+ readarray -t PATHTOKENS < <( echo "$QUERY" | \
+ $GREP "$INDEX|$STRING|$WORD|$WILDCARD|$FILTER|$DEEPSCAN|$SET|$INDEXALL|." | \
+ egrep -v "^$SPACE$|^\\.$|^\[$|^\]$|^'$|^\\\$$|^\)$")
+ [[ $DEBUG -eq 1 ]] && {
+ echo "egrep -o '$INDEX|$STRING|$WORD|$WILDCARD|$FILTER|$DEEPSCAN|$SET|$INDEXALL|.'"
+ echo -n "TOKENISED QUERY="; echo "$QUERY" | \
+ $GREP "$INDEX|$STRING|$WORD|$WILDCARD|$FILTER|$DEEPSCAN|$SET|$INDEXALL|." | \
+ egrep -v "^$SPACE$|^\\.$|^\[$|^\]$|^'$|^\\\$$|^\)$"
+ }
+ if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi
+}
+
+# ---------------------------------------------------------------------------
+create_filter() {
+# ---------------------------------------------------------------------------
+# Creates the filter from the user's query.
+# Filter works in a single pass through the data, unless a filter (script)
+# expression is used, in which case two passes are required (MULTIPASS=1).
+
+ local len=${#PATHTOKENS[*]}
+
+ local -i i=0
+ local query="^\[" comma=
+ while [[ i -lt len ]]; do
+ case "${PATHTOKENS[i]}" in
+ '"') :
+ ;;
+ '..') query+="$comma[^]]*"
+ comma=
+ ;;
+ '[*]') query+="$comma[^,]*"
+ comma=","
+ ;;
+ '*') query+="$comma(\"[^\"]*\"|[0-9]+[^],]*)"
+ comma=","
+ ;;
+ '?(@'*) a=${PATHTOKENS[i]#?(@.}
+ elem="${a%%[<>=!]*}"
+ rhs="${a##*[<>=!]}"
+ a="${a#$elem}"
+ elem="${elem//./[\",.]+}" # Allows child node matching
+ operator="${a%$rhs}"
+ [[ -z $operator ]] && { operator="=="; rhs=; }
+ if [[ $rhs == *'"'* || $rhs == *"'"* ]]; then
+ case $operator in
+ '=='|'=') OPERATOR=
+ if [[ $elem == '?(@' ]]; then
+ # To allow search on @.property such as:
+ # $..book[?(@.title==".*Book 1.*")]
+ query+="$comma[0-9]+[],][[:space:]\"]*${rhs//\"/}"
+ else
+ # To allow search on @ (this node) such as:
+ # $..reviews[?(@==".*Fant.*")]
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*${rhs//\"/}"
+ fi
+ FILTER="$query"
+ ;;
+ '>='|'>') OPERATOR=">"
+ RHS="$rhs"
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
+ FILTER="$query"
+ ;;
+ '<='|'<') OPERATOR="<"
+ RHS="$rhs"
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
+ FILTER="$query"
+ ;;
+ esac
+ else
+ case $operator in
+ '=='|'=') OPERATOR=
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*$rhs"
+ FILTER="$query"
+ ;;
+ '>=') OPERATOR="-ge"
+ RHS="$rhs"
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
+ FILTER="$query"
+ ;;
+ '>') OPERATOR="-gt"
+ RHS="$rhs"
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
+ FILTER="$query"
+ ;;
+ '<=') OPERATOR="-le"
+ RHS="$rhs"
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
+ FILTER="$query"
+ ;;
+ '<') OPERATOR="-lt"
+ RHS="$rhs"
+ query+="$comma[0-9]+,\"$elem\"[],][[:space:]\"]*"
+ FILTER="$query"
+ esac
+ fi
+ MULTIPASS=1
+ ;;
+ "["*) if [[ ${PATHTOKENS[i]} =~ , ]]; then
+ a=${PATHTOKENS[i]#[}
+ a=${a%]}
+ if [[ $a =~ [[:alpha:]] ]]; then
+ # converts only one comma: s/("[^"]+),([^"]+")/\1`\2/g;s/"//g
+ #a=$(echo $a | sed 's/\([[:alpha:]]*\)/"\1"/g')
+ a=$(echo $a | sed -r "s/[\"']//g;s/([^,]*)/\"\1\"/g")
+ fi
+ query+="$comma(${a//,/|})"
+ elif [[ ${PATHTOKENS[i]} =~ : ]]; then
+ if ! [[ ${PATHTOKENS[i]} =~ [0-9][0-9] || ${PATHTOKENS[i]} =~ :] ]]
+ then
+ if [[ ${PATHTOKENS[i]#*:} =~ : ]]; then
+ INDEXMATCH_QUERY+=("${PATHTOKENS[i]}")
+ query+="$comma[^,]*"
+ else
+ # Index in the range of 0-9 can be handled by regex
+ query+="${comma}$(echo ${PATHTOKENS[i]} | \
+ awk '/:/ { a=substr($0,0,index($0,":")-1);
+ b=substr($0,index($0,":")+1,index($0,"]")-index($0,":")-1);
+ if(b>0) { print a ":" b-1 "]" };
+ if(b<=0) { print a ":]" } }' | \
+ sed 's/\([0-9]\):\([0-9]\)/\1-\2/;
+ s/\[:\([0-9]\)/[0-\1/;
+ s/\([0-9]\):\]/\1-9999999]/')"
+ fi
+ else
+ INDEXMATCH_QUERY+=("${PATHTOKENS[i]}")
+ query+="$comma[^,]*"
+ fi
+ else
+ a=${PATHTOKENS[i]#[}
+ a=${a%]}
+ if [[ $a =~ [[:alpha:]] ]]; then
+ a=$(echo $a | sed -r "s/[\"']//g;s/([^,]*)/\"\1\"/g")
+ else
+ [[ $i -gt 0 ]] && comma=","
+ fi
+ #idx=$(echo "${PATHTOKENS[i]}" | tr -d "[]")
+ query+="$comma$a"
+ fi
+ comma=","
+ ;;
+ *) PATHTOKENS[i]=${PATHTOKENS[i]//\'/\"}
+ query+="$comma\"${PATHTOKENS[i]//\"/}\""
+ comma=","
+ ;;
+ esac
+ i=i+1
+ done
+
+ [[ -z $FILTER ]] && FILTER="$query[],]"
+ [[ $DEBUG -eq 1 ]] && echo "FILTER=$FILTER"
+}
+
+# ---------------------------------------------------------------------------
+parse_array () {
+# ---------------------------------------------------------------------------
+# json parsing
+
+ local index=0
+ local ary=''
+ read -r token
+ case "$token" in
+ ']')
+ ;;
+ *)
+ while :
+ do
+ parse_value "$1" "$index"
+ index=$((index+1))
+ ary="$ary""$value"
+ read -r token
+ case "$token" in
+ ']') break ;;
+ ',') ary="$ary," ;;
+ *) throw "EXPECTED , or ] GOT ${token:-EOF}" ;;
+ esac
+ read -r token
+ done
+ ;;
+ esac
+ value=
+ :
+}
+
+# ---------------------------------------------------------------------------
+parse_object () {
+# ---------------------------------------------------------------------------
+# json parsing
+
+ local key
+ local obj=''
+ read -r token
+ case "$token" in
+ '}')
+ ;;
+ *)
+ while :
+ do
+ case "$token" in
+ '"'*'"') key=$token ;;
+ *) throw "EXPECTED string GOT ${token:-EOF}" ;;
+ esac
+ read -r token
+ case "$token" in
+ ':') ;;
+ *) throw "EXPECTED : GOT ${token:-EOF}" ;;
+ esac
+ read -r token
+ parse_value "$1" "$key"
+ obj="$obj$key:$value"
+ read -r token
+ case "$token" in
+ '}') break ;;
+ ',') obj="$obj," ;;
+ *) throw "EXPECTED , or } GOT ${token:-EOF}" ;;
+ esac
+ read -r token
+ done
+ ;;
+ esac
+ value=
+ :
+}
+
+# ---------------------------------------------------------------------------
+parse_value () {
+# ---------------------------------------------------------------------------
+# json parsing
+
+ local jpath="${1:+$1,}$2" isleaf=0 isempty=0 print=0
+ case "$token" in
+ '{') parse_object "$jpath" ;;
+ '[') parse_array "$jpath" ;;
+ # At this point, the only valid single-character tokens are digits.
+ ''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;;
+ *) value=$token
+ # if asked, replace solidus ("\/") in json strings with normalized value: "/"
+ [ "$NORMALIZE_SOLIDUS" -eq 1 ] && value=$(echo "$value" | sed 's#\\/#/#g')
+ isleaf=1
+ [ "$value" = '""' ] && isempty=1
+ ;;
+ esac
+ [[ -z INCLEMPTY ]] && [ "$value" = '' ] && return
+ [ "$NO_HEAD" -eq 1 ] && [ -z "$jpath" ] && return
+
+ [ "$isleaf" -eq 1 ] && [ $isempty -eq 0 ] && print=1
+ [ "$print" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value"
+ :
+}
+
+# ---------------------------------------------------------------------------
+flatten() {
+# ---------------------------------------------------------------------------
+# Take out
+
+ local path a prevpath pathlen
+
+ if [[ $FLATTEN -eq 1 ]]; then
+ cat >"$STDINFILE2"
+
+ highest=9999
+
+ while read line; do
+ a=${line#[};a=${a%%]*}
+ readarray -t path < <(grep -o "[^,]*"<<<"$a")
+ [[ -z $prevpath ]] && {
+ prevpath=("${path[@]}")
+ highest=$((${#path[*]}-1))
+ continue
+ }
+
+ pathlen=$((${#path[*]}-1))
+
+ for i in `seq 0 $pathlen`; do
+ [[ ${path[i]} != ${prevpath[i]} ]] && {
+ high=$i
+ break
+ }
+ done
+
+ [[ $high -lt $highest ]] && highest=$high
+
+ prevpath=("${path[@]}")
+ done <"$STDINFILE2"
+
+ if [[ $highest -gt 0 ]]; then
+ sed -r 's/\[(([0-9]+|"[^"]+")[],]){'$((highest))'}(.*)/[\3/' \
+ "$STDINFILE2"
+ else
+ cat "$STDINFILE2"
+ fi
+ else
+ cat
+ fi
+}
+
+# ---------------------------------------------------------------------------
+indexmatcher() {
+# ---------------------------------------------------------------------------
+# For double digit or greater indexes match each line individually
+# Single digit indexes are handled more efficiently by regex
+
+ local a b
+
+ [[ $DEBUG -eq 1 ]] && {
+ for i in `seq 0 $((${#INDEXMATCH_QUERY[*]}-1))`; do
+ echo "INDEXMATCH_QUERY[$i]=${INDEXMATCH_QUERY[i]}"
+ done
+ }
+
+ matched=1
+
+ step=
+ if [[ ${#INDEXMATCH_QUERY[*]} -gt 0 ]]; then
+ while read -r line; do
+ for i in `seq 0 $((${#INDEXMATCH_QUERY[*]}-1))`; do
+ [[ ${INDEXMATCH_QUERY[i]#*:} =~ : ]] && {
+ step=${INDEXMATCH_QUERY[i]##*:}
+ step=${step%]}
+ INDEXMATCH_QUERY[i]="${INDEXMATCH_QUERY[i]%:*}]"
+ }
+ q=${INDEXMATCH_QUERY[i]:1:-1} # <- strip '[' and ']'
+ a=${q%:*} # <- number before ':'
+ b=${q#*:} # <- number after ':'
+ [[ -z $b ]] && b=99999999999
+ readarray -t num < <( (grep -Eo ',[0-9]+[],]' | tr -d ,])<<<$line )
+ if [[ ${num[i]} -ge $a && ${num[i]} -lt $b && matched -eq 1 ]]; then
+ matched=1
+ [[ $i -eq $((${#INDEXMATCH_QUERY[*]}-1)) ]] && {
+ if [[ $step -gt 1 ]]; then
+ [[ $(((num[i]-a)%step)) -eq 0 ]] && {
+ [[ $DEBUG -eq 1 ]] && echo -n "($a,$b,${num[i]}) "
+ echo "$line"
+ }
+ else
+ [[ $DEBUG -eq 1 ]] && echo -n "($a,$b,${num[i]}) "
+ echo "$line"
+ fi
+ }
+ else
+ matched=0
+ continue
+ fi
+ done
+ matched=1
+ done
+ else
+ cat -
+ fi
+}
+
+# ---------------------------------------------------------------------------
+brief() {
+# ---------------------------------------------------------------------------
+# Only show the value
+
+ if [[ $BRIEF -eq 1 ]]; then
+ sed 's/^[^\t]*\t//;s/^"//;s/"$//;'
+ else
+ cat
+ fi
+}
+
+# ---------------------------------------------------------------------------
+json() {
+# ---------------------------------------------------------------------------
+# Turn output into JSON
+
+ local a tab=$(echo -e "\t")
+ local UP=1 DOWN=2 SAME=3
+ local prevpathlen=-1 prevpath=() path a
+ declare -a closers
+
+ if [[ $JSON -eq 0 ]]; then
+ cat -
+ else
+ while read -r line; do
+ a=${line#[};a=${a%%]*}
+ readarray -t path < <(grep -o "[^,]*"<<<"$a")
+ value=${line#*$tab}
+
+ # Not including the object itself (last item)
+ pathlen=$((${#path[*]}-1))
+
+ # General direction
+
+ direction=$SAME
+ [[ $pathlen -gt $prevpathlen ]] && direction=$DOWN
+ [[ $pathlen -lt $prevpathlen ]] && direction=$UP
+
+ # Handle jumps UP the tree (close previous paths)
+
+ [[ $prevpathlen != -1 ]] && {
+ for i in `seq 0 $((pathlen-1))`; do
+ [[ ${prevpath[i]} == ${path[i]} ]] && continue
+ [[ ${path[i]} != '"'* ]] && {
+ a=(${!arrays[*]})
+ [[ -n $a ]] && {
+ for k in `seq $((i+1)) ${a[-1]}`; do
+ arrays[k]=
+ done
+ }
+ a=(${!comma[*]})
+ [[ -n $a ]] && {
+ for k in `seq $((i+1)) ${a[-1]}`; do
+ comma[k]=
+ done
+ }
+ for j in `seq $((prevpathlen)) -1 $((i+2))`
+ do
+ arrays[j]=
+ [[ -n ${closers[j]} ]] && {
+ let indent=j*4
+ printf "\n%0${indent}s${closers[j]}" ""
+ unset closers[j]
+ comma[j]=
+ }
+ done
+ direction=$DOWN
+ break
+ }
+ direction=$DOWN
+ for j in `seq $((prevpathlen)) -1 $((i+1))`
+ do
+ arrays[j]=
+ [[ -n ${closers[j]} ]] && {
+ let indent=j*4
+ printf "\n%0${indent}s${closers[j]}" ""
+ unset closers[j]
+ comma[j]=
+ }
+ done
+ a=(${!arrays[*]})
+ [[ -n $a ]] && {
+ for k in `seq $i ${a[-1]}`; do
+ arrays[k]=
+ done
+ }
+ break
+ done
+ }
+
+ [[ $direction -eq $UP ]] && {
+ [[ $prevpathlen != -1 ]] && comma[prevpathlen]=
+ for i in `seq $((prevpathlen+1)) -1 $((pathlen+1))`
+ do
+ arrays[i]=
+ [[ -n ${closers[i]} ]] && {
+ let indent=i*4
+ printf "\n%0${indent}s${closers[i]}" ""
+ unset closers[i]
+ comma[i]=
+ }
+ done
+ a=(${!arrays[*]})
+ [[ -n $a ]] && {
+ for k in `seq $i ${a[-1]}`; do
+ arrays[k]=
+ done
+ }
+ }
+
+ # Opening braces (the path leading up to the key)
+
+ broken=
+ for i in `seq 0 $((pathlen-1))`; do
+ [[ -z $broken && ${prevpath[i]} == ${path[i]} ]] && continue
+ [[ -z $broken ]] && {
+ broken=$i
+ [[ $prevpathlen -ne -1 ]] && broken=$((i+1))
+ }
+ if [[ ${path[i]} == '"'* ]]; then
+ # Object
+ [[ $i -ge $broken ]] && {
+ let indent=i*4
+ printf "${comma[i]}%0${indent}s{\n" ""
+ closers[i]='}'
+ comma[i]=
+ }
+ let indent=(i+1)*4
+ printf "${comma[i]}%0${indent}s${path[i]}:\n" ""
+ comma[i]=",\n"
+ else
+ # Array
+ if [[ ${arrays[i]} != 1 ]]; then
+ let indent=i*4
+ printf "%0${indent}s" ""
+ echo "["
+ closers[i]=']'
+ arrays[i]=1
+ comma[i]=
+ else
+ let indent=(i+1)*4
+ printf "\n%0${indent}s${closers[i-1]}" ""
+ direction=$DOWN
+ comma[i+1]=",\n"
+ fi
+ fi
+ done
+
+ # keys & values
+
+ if [[ ${path[-1]} == '"'* ]]; then
+ # Object
+ [[ $direction -eq $DOWN ]] && {
+ let indent=pathlen*4
+ printf "${comma[pathlen]}%0${indent}s{\n" ""
+ closers[pathlen]='}'
+ comma[pathlen]=
+ }
+ let indent=(pathlen+1)*4
+ printf "${comma[pathlen]}%0${indent}s" ""
+ echo -n "${path[-1]}:$value"
+ comma[pathlen]=",\n"
+ else
+ # Array
+ [[ ${arrays[i]} != 1 ]] && {
+ let indent=(pathlen-0)*4
+ printf "%0${indent}s[\n" ""
+ closers[pathlen]=']'
+ comma[pathlen]=
+ arrays[i]=1
+ }
+ let indent=(pathlen+1)*4
+ printf "${comma[pathlen]}%0${indent}s" ""
+ echo -n "$value"
+ comma[pathlen]=",\n"
+ fi
+
+ prevpath=("${path[@]}")
+ prevpathlen=$pathlen
+ done
+
+ # closing braces
+
+ for i in `seq $((pathlen)) -1 0`
+ do
+ let indent=i*4
+ printf "\n%0${indent}s${closers[i]}" ""
+ done
+ echo
+ fi
+}
+
+# ---------------------------------------------------------------------------
+filter() {
+# ---------------------------------------------------------------------------
+# Apply the query filter
+
+ local a tab=$(echo -e "\t") v
+
+ [[ $NOCASE -eq 1 ]] && opts+="-i"
+ [[ $WHOLEWORD -eq 1 ]] && opts+=" -w"
+ if [[ -z $OPERATOR ]]; then
+ egrep $opts "$FILTER"
+ else
+ egrep $opts "$FILTER" | \
+ while read line; do
+ v=${line#*$tab}
+ case $OPERATOR in
+ '-ge') if awk '{exit !($1>=$2)}'<<<"$v $RHS";then echo "$line"; fi
+ ;;
+ '-gt') if awk '{exit !($1>$2) }'<<<"$v $RHS";then echo "$line"; fi
+ ;;
+ '-le') if awk '{exit !($1<=$2) }'<<<"$v $RHS";then echo "$line"; fi
+ ;;
+ '-lt') if awk '{exit !($1<$2) }'<<<"$v $RHS";then echo "$line"; fi
+ ;;
+ '>') v=${v#\"};v=${v%\"}
+ RHS=${RHS#\"};RHS=${RHS%\"}
+ [[ "$v" > "$RHS" ]] && echo "$line"
+ ;;
+ '<') v=${v#\"};v=${v%\"}
+ RHS=${RHS#\"};RHS=${RHS%\"}
+ [[ "$v" < "$RHS" ]] && echo "$line"
+ ;;
+ esac
+ done #< <(egrep $opts "$FILTER")
+ fi
+}
+
+# ---------------------------------------------------------------------------
+parse () {
+# ---------------------------------------------------------------------------
+# Parses json
+
+ read -r token
+ parse_value
+ read -r token
+ case "$token" in
+ '') ;;
+ *) throw "EXPECTED EOF GOT $token"
+ exit 1;;
+ esac
+}
+
+# ---------------------------------------------------------------------------
+throw() {
+# ---------------------------------------------------------------------------
+ echo "$*" >&2
+ exit 1
+}
+
+if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]);
+then
+ main "$@"
+fi
+
+# vi: expandtab sw=2 ts=2 \ No newline at end of file
diff --git a/deps/jsonpath/LICENSE.APACHE2 b/deps/jsonpath/LICENSE.APACHE2
new file mode 100644
index 0000000000..6366c04716
--- /dev/null
+++ b/deps/jsonpath/LICENSE.APACHE2
@@ -0,0 +1,15 @@
+Apache License, Version 2.0
+
+Copyright (c) 2011 Dominic Tarr
+
+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.
diff --git a/deps/jsonpath/LICENSE.MIT b/deps/jsonpath/LICENSE.MIT
new file mode 100644
index 0000000000..6eafbd734a
--- /dev/null
+++ b/deps/jsonpath/LICENSE.MIT
@@ -0,0 +1,24 @@
+The MIT License
+
+Copyright (c) 2011 Dominic Tarr
+
+Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to
+deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/deps/jsonpath/MANIFEST.in b/deps/jsonpath/MANIFEST.in
new file mode 100644
index 0000000000..b98f63d048
--- /dev/null
+++ b/deps/jsonpath/MANIFEST.in
@@ -0,0 +1,3 @@
+include README.md
+include LICENSE.MIT
+include LICENSE.APACHE2 \ No newline at end of file
diff --git a/deps/jsonpath/README.md b/deps/jsonpath/README.md
new file mode 100644
index 0000000000..5b770bc5d1
--- /dev/null
+++ b/deps/jsonpath/README.md
@@ -0,0 +1,491 @@
+# JSONPath.sh
+
+yo, so it's a JSONPath implementation written in Bash - and it probably only works in Bash.
+
+[![travis](https://secure.travis-ci.org/mclarkson/JSONPath.sh.png?branch=master)](https://travis-ci.org/mclarkson/JSONPath.sh)
+
+## Invocation
+
+ JSONPath.sh [-b] [-i] [-j] [-h] [-p] [-u] [-f FILE] [pattern]
+
+pattern
+> the JSONPath query. Defaults to '$.\*' if not supplied.
+
+-b
+> Brief output. Only show the values, not the path and key.
+
+-f FILE
+> Read a FILE instead of reading from standard input.
+
+-i
+> Case insensitive searching.
+
+-j
+> Output in JSON format, instead of JSON.sh format.
+
+-u
+> Strip unnecessary leading path elements.
+
+-p
+> Pass JSON.sh formatted data through to the JSON parser only. Useful after
+> JSON.sh data has been manipulated.
+
+-h
+> Show help text.
+
+## Requirements
+
+JSONPath.sh is a Bash script that uses the standard GNU tools: *bash*, *cat*, *sed*, *awk*, *grep*, and *seq*.
+
+## Installation
+
+Install with pip:
+
+* `sudo pip install git+https://github.com/mclarkson/JSONPath.sh#egg=JSONPath.sh`
+
+Install with npm:
+
+* `sudo npm install -g jsonpath.sh`
+
+Or copy the `JSONPath.sh` script to your PATH, for example:
+
+``` bash
+curl -O https://raw.githubusercontent.com/mclarkson/JSONPath.sh/master/JSONPath.sh
+chmod +x JSONPath.sh
+mv JSONPath.sh ~/bin
+```
+
+## Examples
+
+``` bash
+$ ./JSONPath.sh < package.json
+["name"] "JSONPath.sh"
+["version"] "0.0.0"
+["description"] "JSONPath implementation written in Bash"
+["homepage"] "http://github.com/mclarkson/JSONPath.sh"
+["repository","type"] "git"
+["repository","url"] "https://github.com/mclarkson/JSONPath.sh.git"
+["bin","JSONPath.sh"] "./JSONPath.sh"
+["author"] "Mark Clarkson <mark.clarkson@smorg.co.uk>"
+["scripts","test"] "./all-tests.sh"
+```
+
+more complex examples:
+
+*NPMJS.ORG EXAMPLES*
+
+``` bash
+# Number of downloads yesterday
+curl -s https://api.npmjs.org/downloads/point/last-day/jsonpath.sh | \
+ JSONPath.sh '$.downloads' -b
+
+# Show all versions
+curl registry.npmjs.org/express | ./JSONPath.sh '$.versions.*.version'
+
+# Show version 2.2.0
+./JSONPath.sh \
+ -f test/valid/npmjs.org.json \
+ '$.versions.["2.2.0"]'
+
+# Find versions 2.2.x (using a regular expression)
+# and show version and contributors
+./JSONPath.sh \
+ -f test/valid/npmjs.org.json \
+ '$..["2.2.*"].[version,contributors]'
+```
+*JSONPATH.ORG EXAMPLES*
+
+``` bash
+# The default query
+./JSONPath.sh \
+ -f test/valid/jsonpath.com.json \
+ '$.phoneNumbers[:1].type'
+
+# The same, but using a filter (script) expression
+# (This takes 2 passes through the data)
+./JSONPath.sh \
+ -f test/valid/jsonpath.com.json \
+ '$.phoneNumbers[?(@.type=iPhone)]'
+```
+
+*KUBERNETES EXAMPLES*
+
+``` bash
+# Show the NodePort of a service named bob
+# from a list of all services
+kubectl get svc -o json | JSONPath.sh \
+ '$..items[?(@.metadata.name==bob)].spec.ports[0].nodePort' -b
+
+# Or, more simply, show the NodePort of the service
+kubectl get svc bob -o json | JSONPath.sh '$..nodePort' -b
+
+# Get the port of the kubernetes-dashboard and output as json:
+kubectl get svc --all-namespaces -o json | JSONPath.sh -j -u \
+ '$.items[?(@.spec.selector.app=".*dashboard")]..ports[*].nodePort'
+```
+
+*DOCKER EXAMPLES*
+
+``` bash
+# Show Everything
+./JSONPath.sh -f test/valid/docker_stopped.json '$.*'
+
+# Look for an ip address (using case insensitive searching to start)
+./JSONPath.sh \
+ -f test/valid/docker_running.json \
+ /valid/docker_running.json -i '$..".*ip.*"'
+
+# Now get the IP address exactly
+./JSONPath.sh \
+ -f test/valid/docker_running.json \
+ '$.*.NetworkSettings.IPAddress' -b
+
+# Show all Mounts
+./JSONPath.sh \
+ -f test/valid/docker_stopped.json \
+ '$.[*].Mounts'
+
+# Show sources and destinations for all mounts
+./JSONPath.sh \
+ -f test/valid/docker_stopped.json \
+ '$.[*].Mounts[*].[Source,Destination]'
+
+# Use brief (-b) output to store mounts in an array for use in a loop
+readarray -t MNTS \
+ < <(./JSONPath.sh -b -f test/valid/docker_stopped.json '$.*.Mounts[*].[Source,Destination]')
+
+# the loop:
+for idx in `seq 0 $((${#MNTS[*]}/2-1))`; do
+ echo "'${MNTS[idx*2]}' is mounted on the host at '${MNTS[idx*2+1]}'"
+done
+```
+
+*GOESSNER.NET (EXPANDED) EXAMPLES*
+
+``` bash
+# dot-notation (my latest favourite book)
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ '$.store.book[16].title'
+
+# dot-notation with a node set
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ '$.store.book[4,6,16,22].title'
+
+# bracket-notation ('$[' needs escaping at the
+# command line, so bash doesn't think it's an
+# arithmetic expression)
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ "\$['store']['book'][16]['title']"
+
+# bracket-notation with an array slice and a set
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ "\$['store']['book'][14:25:2]['title','reviews']"
+
+# Mixed bracket- and dot- notation
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ "\$['store'].book[16].title"
+
+# Show all titles
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ '$..book[*].title'
+
+# All books with 'Book 1' somewhere in the title
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ -i '$..book[?(@.title==".*Book 1.*")].title'
+
+# All books with a price less than or equal to 4.20
+# Show both the title and the price and output in
+# JSON format but without redundant path elements.
+./JSONPath.sh -j -u \
+ -f test/valid/goessner.net.expanded.json \
+ '$.store.book[?(@.price<4.20)].[title,price]'
+
+# The following does not work yet (TODO)
+./JSONPath.sh \
+ -f test/valid/goessner.net.expanded.json \
+ '$.store.book[(@.length-1)].title'
+```
+
+## JSONPath patterns and extensions
+
+### Supported JSONPath options
+
+| JSONPath | Supported | Comment |
+| -----------------------|-----------|---------------------------------------------------------|
+| $ | Y | the root object/element (optional) |
+| @ | Y | the current object/element |
+| . or [] | Y | child operator. |
+| .. | Y | recusive descent. |
+| * | Y | wildcard. All objects/elements regardless their names. |
+| [] | Y | subscript operator. |
+| [,] | Y | node sets. |
+| ```[start:end:step]``` | Y | array slice operator. |
+| ?() | Y | applies a filter (script) expressions |
+| () | Y | script expression, using the underlying script engine. |
+
+### Searching for things
+
+"regex"
+
+Use a regular expression inside the JSONPath pattern.<br>
+Combine with '-i' for case insensitive search.<br>
+Combine with '-w' to match whole words only.
+
+Examples:
+
+Find every node key starting with 'ip':
+
+``` bash
+# These are all equivalent
+./JSONPath.sh -f test/valid/docker_running.json -i "$..['ip.*']"
+./JSONPath.sh -f test/valid/docker_running.json -i '$..["ip.*"]'
+./JSONPath.sh -f test/valid/docker_running.json -i '$.."ip.*"'
+./JSONPath.sh -f test/valid/docker_running.json -i "$..'ip.*'"
+```
+
+Restrict the previous search to the bridge object.
+
+``` bash
+./JSONPath.sh -f test/valid/docker_running.json -i "$..bridge.'ip.*'"
+```
+
+Show all book titles by authors starting with 'Doug'.
+
+``` bash
+# Show the title
+./JSONPath.sh -f test/valid/goessner.net.expanded.json -i \
+ "$..book[?(@.author==Doug)].title"
+
+# Show the author, title and rating (can be with or without double quotes)
+./JSONPath.sh -f test/valid/goessner.net.expanded.json -i \
+ '$..book[?(@.author="Doug")].["author","title",rating]'
+```
+
+### Modification
+
+A common task is to modify JSON data on-the-fly. Unix style 'one-liners' can be
+created to easily and logically modify JSON data.
+
+The key to data modification (that is: add, modify or deletion of data) is to
+modify the *JSON.sh* formatted data, then use the passthrough, '-p', option to
+output again as JSON. Sequence is:
+
+1. Read JSON data and output as *JSON.sh* data.
+2. Modify *JSON.sh* data using standard Unix tools.
+3. Pipe modified *JSON.sh* data to JSONPath.sh with passthrough option producing
+ JSON data again.
+
+For example: The following 'one-liner' will read a kubernetes deployment
+configuration (using 'kubectl get ...'), output it in *JSON.sh* format (using
+'JSONPath.sh'), change the number of replicas from the existing value to 5
+(using *sed*), output again in JSON (using 'JSONPath.sh -p'), then replace the
+original deployment with the newly changed one (using 'kubectl replace ...').
+
+```
+kubectl get deployment sample-deployment -o json | \
+JSONPath.sh | \
+sed 's/\["spec","replicas"\].*/["spec","replicas"]\t5/' | \
+JSONPath.sh -p | \
+kubectl replace deployment sample-deployment -f -
+```
+
+This allows you to reuse your Unix skills rather than learn new terse syntax
+or Domain Specific Language.
+
+### Re-injection
+
+This tool, JSONPath.sh, is really handy for handing json formatted
+data to other tools, and using pass-through mode (-p) comes in quite
+handy for creating complex queries and outputting in json.
+
+**Re-injection** allows the user to overcome the limitation
+of a single filter expression per invocation. To do this the first
+query, or set of queries, should output in JSON format using the
+'-j' option.
+
+**Usage Example**
+
+Show all books with a price greater than 4 that also have a 5 star
+rating (note that the first process in the pipeline outputs in json):
+
+```
+./JSONPath.sh -j -f test/valid/goessner.net.expanded.json \
+ '$..book[?(@.price>4)]' | ./JSONPath.sh \
+ '$..book[?(@.rating==5)].title'
+```
+
+**Pass-through mode** reads the standard output JSONPath.sh (or JSON.sh)
+produces and outputs JSON. This gives the user an opportunity to filter
+or modify the results:
+
+**Filtering Usage Example**
+
+Show all authors, without showing duplicates and output in JSON format.
+
+All authors with duplicates:
+
+```
+$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json '$..author'
+... omitted ...
+["store","book",9,"author"] "James S. A. Corey"
+["store","book",10,"author"] "James S. A. Corey"
+["store","book",11,"author"] "James S. A. Corey"
+... 25 lines of output ...
+```
+
+Use standard unix tools to remove duplicates:
+
+```
+$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json '$..author' \
+ | sort -k2 | uniq -f 1
+... 11 lines of output ...
+```
+
+And pipe (re-inject - 'cos it sounds cool) the output into JSONPath.sh:
+
+```
+$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json '$..author' \
+ | sort -k2 | uniq -f 1 \
+ | ./JSONPath.sh -p
+{
+ "store":
+ {
+ "book":
+ [
+ {
+ "author":"Douglas E. Richards"
+ }
+ ,{
+ "author":"Evelyn Waugh"
+ }
+... JSON output with unique data ...
+```
+
+Use the '-u' option to flatten the output:
+
+```
+$ ./JSONPath.sh -f test/valid/goessner.net.expanded.json \
+ '$..author' \
+ | sort -k2 | uniq -f 1 \
+ | ./JSONPath.sh -p -u
+... JSON flattened output ...
+{
+ "book":
+ [
+ {
+ "author":"Douglas E. Richards"
+ },
+ {
+ "author":"Evelyn Waugh"
+ },
+```
+
+**Filter and Merge Usage Example**
+
+Different parts of JSON input, or entirely different JSON input, can be merged
+together with Unix 'sort' and output in json format.
+
+This is a complex kubernetes example that uses JSONPath.sh and standard Unix
+tools to output just the command, pod mounts, and container mounts (output from
+different parts of the tree) for the first matched kube-proxy pod.
+
+```
+# Get details of all pods
+kubectl get -n kube-system pods -o json >/tmp/kpod
+
+# Get the index of the first pod with name starting 'kube-proxy'
+idx=`JSONPath.sh -f /tmp/kpod '$.items[?(@.metadata.name=="kube-proxy.*")].apiVersion' \
+ | head -n1 | grep -o ',[0-9]\+,' | tr -d ,`
+
+# Get three subtrees using the index and merge them using sort
+# and then output in json format
+( JSONPath.sh -f /tmp/kpod '$.items['$idx'].spec.volumes'; \
+ JSONPath.sh -f /tmp/kpod '$.items['$idx']..volumeMounts'; \
+ JSONPath.sh -f /tmp/kpod '$.items['$idx']..containers[*].command'
+) | sort | JSONPath.sh -p -u
+```
+
+, which produces:
+
+```
+{
+ "containers":
+ [
+ {
+ "command":
+ [
+ "/usr/local/bin/kube-proxy",
+ "--kubeconfig=/var/lib/kube-proxy/kubeconfig.conf"
+ ],
+ "volumeMounts":
+ [
+ {
+ "mountPath":"/var/lib/kube-proxy",
+ "name":"kube-proxy"
+ },
+ {
+ "mountPath":"/var/run/secrets/kubernetes.io/serviceaccount",
+ "name":"kube-proxy-token-m9b6j",
+ "readOnly":true
+ }
+ ]
+ }
+ ],
+ "volumes":
+ [
+ {
+ "configMap":
+ {
+ "defaultMode":420,
+ "name":"kube-proxy"
+ },
+ "name":"kube-proxy"
+ },
+ {
+ "name":"kube-proxy-token-m9b6j",
+ "secret":
+ {
+ "defaultMode":420,
+ "secretName":"kube-proxy-token-m9b6j"
+ }
+ }
+ ]
+}
+```
+
+## Cool Links
+
+* [dominictarr/JSON.sh](https://github.com/dominictarr/JSON.sh) The original, the best, JSON.sh.
+
+## Performance
+
+* Performance is acceptable for small data sizes
+* Worse when using:
+ * large data files (hundreds of kilobytes).
+ * filter (script) expressions (An extra pass is required).
+ * Indexes greater than 9.
+ * Indexes with steps even with indexes less than 10.
+* Better with:
+ * Small data files (A few kilobytes).
+ * Indexes less than 10 (then matching is done by regex, unless a step is used).
+ * No filter (script) expressions (so no extra pass through the data).
+
+## Limitations (todo)
+
+* Only one filter expression, '?(@', per query.
+ Use re-injection, detailed above, to overcome this limitation.
+
+## License
+
+This software is available under the following licenses:
+
+ * MIT
+ * Apache 2
+
diff --git a/deps/jsonpath/_config.yml b/deps/jsonpath/_config.yml
new file mode 100644
index 0000000000..c741881743
--- /dev/null
+++ b/deps/jsonpath/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-slate \ No newline at end of file
diff --git a/deps/jsonpath/all-tests.sh b/deps/jsonpath/all-tests.sh
new file mode 100644
index 0000000000..84f826f75d
--- /dev/null
+++ b/deps/jsonpath/all-tests.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+cd ${0%/*}
+
+#set -e
+fail=0
+tests=0
+#all_tests=${__dirname:}
+#echo PLAN ${#all_tests}
+for test in test/*.sh ;
+do
+ tests=$((tests+1))
+ echo TEST: $test
+ ./$test
+ ret=$?
+ if [ $ret -eq 0 ] ; then
+ echo OK: ---- $test
+ passed=$((passed+1))
+ else
+ echo FAIL: $test $fail
+ fail=$((fail+ret))
+ fi
+done
+
+if [ $fail -eq 0 ]; then
+ echo -n 'SUCCESS '
+ exitcode=0
+else
+ echo -n 'FAILURE '
+ exitcode=1
+fi
+echo $passed / $tests
+exit $exitcode
diff --git a/deps/jsonpath/package.json b/deps/jsonpath/package.json
new file mode 100644
index 0000000000..458b822a53
--- /dev/null
+++ b/deps/jsonpath/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "jsonpath.sh",
+ "version": "0.0.14",
+ "description": "JSONPath implementation written in Bash",
+ "homepage": "http://github.com/mclarkson/JSONPath.sh",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/mclarkson/JSONPath.sh.git"
+ },
+ "bin": {
+ "JSONPath.sh": "./JSONPath.sh"
+ },
+ "dependencies": {},
+ "devDependencies": {},
+ "author": "Mark Clarkson <mark.clarkson@smorg.co.uk>",
+ "scripts": {
+ "test": "./all-tests.sh"
+ }
+}
diff --git a/deps/jsonpath/setup.py b/deps/jsonpath/setup.py
new file mode 100644
index 0000000000..df9863f921
--- /dev/null
+++ b/deps/jsonpath/setup.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from setuptools import setup
+import os
+
+# Allow setup.py to be run from any path
+os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
+
+setup(
+ name='JSONPath.sh',
+ scripts=[
+ 'JSONPath.sh',
+ ],
+ version='0.0.14',
+ description="JSONPath implementation written in Bash",
+ long_description="",
+ author='Mark Clarkson',
+ author_email='mark.clarkson@smorg.co.uk',
+ url='https://github.com/mclarkson/JSONPath.sh',
+ classifiers=[
+ "Programming Language :: Unix Shell",
+ "License :: OSI Approved :: MIT License",
+ "License :: OSI Approved :: Apache Software License",
+ "Intended Audience :: System Administrators",
+ "Intended Audience :: Developers",
+ "Operating System :: POSIX :: Linux",
+ "Topic :: Utilities",
+ "Topic :: Software Development :: Libraries",
+ ],
+)
diff --git a/deps/semver_bash/.gitignore b/deps/semver_bash/.gitignore
new file mode 100644
index 0000000000..5cb19d201a
--- /dev/null
+++ b/deps/semver_bash/.gitignore
@@ -0,0 +1,4 @@
+*~
+*tmp
+*swp
+
diff --git a/deps/semver_bash/LICENSE b/deps/semver_bash/LICENSE
new file mode 100644
index 0000000000..04ac66f8f6
--- /dev/null
+++ b/deps/semver_bash/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2013, Ray Bejjani
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of the FreeBSD Project.
diff --git a/deps/semver_bash/README.md b/deps/semver_bash/README.md
new file mode 100644
index 0000000000..180c368964
--- /dev/null
+++ b/deps/semver_bash/README.md
@@ -0,0 +1,31 @@
+semver_bash is a bash parser for semantic versioning
+====================================================
+
+[Semantic Versioning](http://semver.org/) is a set of guidelines that help keep
+version and version management sane. This is a bash based parser to help manage
+a project's versions. Use it from a Makefile or any scripts you use in your
+project.
+
+Usage
+-----
+semver_bash can be used from the command line as:
+
+ $ ./semver.sh "3.2.1" "3.2.1-alpha"
+ 3.2.1 -> M: 3 m:2 p:1 s:
+ 3.2.1-alpha -> M: 3 m:2 p:1 s:-alpha
+ 3.2.1 == 3.2.1-alpha -> 1.
+ 3.2.1 < 3.2.1-alpha -> 1.
+ 3.2.1 > 3.2.1-alpha -> 0.
+
+
+Alternatively, you can source it from within a script:
+
+ . ./semver.sh
+
+ local MAJOR=0
+ local MINOR=0
+ local PATCH=0
+ local SPECIAL=""
+
+ semverParseInto "1.2.3" MAJOR MINOR PATCH SPECIAL
+ semverParseInto "3.2.1" MAJOR MINOR PATCH SPECIAL
diff --git a/deps/semver_bash/semver.sh b/deps/semver_bash/semver.sh
new file mode 100644
index 0000000000..e5237a4e2e
--- /dev/null
+++ b/deps/semver_bash/semver.sh
@@ -0,0 +1,130 @@
+#!/usr/bin/env sh
+
+function semverParseInto() {
+ local RE='[^0-9]*\([0-9]*\)[.]\([0-9]*\)[.]\([0-9]*\)\([0-9A-Za-z-]*\)'
+ #MAJOR
+ eval $2=`echo $1 | sed -e "s#$RE#\1#"`
+ #MINOR
+ eval $3=`echo $1 | sed -e "s#$RE#\2#"`
+ #MINOR
+ eval $4=`echo $1 | sed -e "s#$RE#\3#"`
+ #SPECIAL
+ eval $5=`echo $1 | sed -e "s#$RE#\4#"`
+}
+
+function semverEQ() {
+ local MAJOR_A=0
+ local MINOR_A=0
+ local PATCH_A=0
+ local SPECIAL_A=0
+
+ local MAJOR_B=0
+ local MINOR_B=0
+ local PATCH_B=0
+ local SPECIAL_B=0
+
+ semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
+ semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
+
+ if [ $MAJOR_A -ne $MAJOR_B ]; then
+ return 1
+ fi
+
+ if [ $MINOR_A -ne $MINOR_B ]; then
+ return 1
+ fi
+
+ if [ $PATCH_A -ne $PATCH_B ]; then
+ return 1
+ fi
+
+ if [[ "_$SPECIAL_A" != "_$SPECIAL_B" ]]; then
+ return 1
+ fi
+
+
+ return 0
+
+}
+
+function semverLT() {
+ local MAJOR_A=0
+ local MINOR_A=0
+ local PATCH_A=0
+ local SPECIAL_A=0
+
+ local MAJOR_B=0
+ local MINOR_B=0
+ local PATCH_B=0
+ local SPECIAL_B=0
+
+ semverParseInto $1 MAJOR_A MINOR_A PATCH_A SPECIAL_A
+ semverParseInto $2 MAJOR_B MINOR_B PATCH_B SPECIAL_B
+
+ if [ $MAJOR_A -lt $MAJOR_B ]; then
+ return 0
+ fi
+
+ if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -lt $MINOR_B ]]; then
+ return 0
+ fi
+
+ if [[ $MAJOR_A -le $MAJOR_B && $MINOR_A -le $MINOR_B && $PATCH_A -lt $PATCH_B ]]; then
+ return 0
+ fi
+
+ if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
+ return 1
+ fi
+ if [[ "_$SPECIAL_A" == "_" ]] && [[ "_$SPECIAL_B" != "_" ]] ; then
+ return 1
+ fi
+ if [[ "_$SPECIAL_A" != "_" ]] && [[ "_$SPECIAL_B" == "_" ]] ; then
+ return 0
+ fi
+
+ if [[ "_$SPECIAL_A" < "_$SPECIAL_B" ]]; then
+ return 0
+ fi
+
+ return 1
+
+}
+
+function semverGT() {
+ semverEQ $1 $2
+ local EQ=$?
+
+ semverLT $1 $2
+ local LT=$?
+
+ if [ $EQ -ne 0 ] && [ $LT -ne 0 ]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+if [ "___semver.sh" == "___`basename $0`" ]; then
+
+MAJOR=0
+MINOR=0
+PATCH=0
+SPECIAL=""
+
+semverParseInto $1 MAJOR MINOR PATCH SPECIAL
+echo "$1 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL"
+
+semverParseInto $2 MAJOR MINOR PATCH SPECIAL
+echo "$2 -> M: $MAJOR m:$MINOR p:$PATCH s:$SPECIAL"
+
+semverEQ $1 $2
+echo "$1 == $2 -> $?."
+
+semverLT $1 $2
+echo "$1 < $2 -> $?."
+
+semverGT $1 $2
+echo "$1 > $2 -> $?."
+
+fi
diff --git a/deps/semver_bash/semver_test.sh b/deps/semver_bash/semver_test.sh
new file mode 100644
index 0000000000..a0ff99461e
--- /dev/null
+++ b/deps/semver_bash/semver_test.sh
@@ -0,0 +1,151 @@
+#!/usr/bin/env bash
+
+. ./semver.sh
+
+semverTest() {
+local A=R1.3.2
+local B=R2.3.2
+local C=R1.4.2
+local D=R1.3.3
+local E=R1.3.2a
+local F=R1.3.2b
+local G=R1.2.3
+
+local MAJOR=0
+local MINOR=0
+local PATCH=0
+local SPECIAL=""
+
+semverParseInto $A MAJOR MINOR PATCH SPECIAL
+echo "$A -> M:$MAJOR m:$MINOR p:$PATCH s:$SPECIAL. Expect M:1 m:3 p:2 s:"
+semverParseInto $E MAJOR MINOR PATCH SPECIAL
+echo "$E -> M:$MAJOR m:$MINOR p:$PATCH s:$SPECIAL. Expect M:1 m:3 p:2 s:a"
+
+echo "Equality comparisions"
+semverEQ $A $A
+echo "$A == $A -> $?. Expect 0."
+
+semverLT $A $A
+echo "$A < $A -> $?. Expect 1."
+
+semverGT $A $A
+echo "$A > $A -> $?. Expect 1."
+
+
+echo "Major number comparisions"
+semverEQ $A $B
+echo "$A == $B -> $?. Expect 1."
+
+semverLT $A $B
+echo "$A < $B -> $?. Expect 0."
+
+semverGT $A $B
+echo "$A > $B -> $?. Expect 1."
+
+semverEQ $B $A
+echo "$B == $A -> $?. Expect 1."
+
+semverLT $B $A
+echo "$B < $A -> $?. Expect 1."
+
+semverGT $B $A
+echo "$B > $A -> $?. Expect 0."
+
+
+echo "Minor number comparisions"
+semverEQ $A $C
+echo "$A == $C -> $?. Expect 1."
+
+semverLT $A $C
+echo "$A < $C -> $?. Expect 0."
+
+semverGT $A $C
+echo "$A > $C -> $?. Expect 1."
+
+semverEQ $C $A
+echo "$C == $A -> $?. Expect 1."
+
+semverLT $C $A
+echo "$C < $A -> $?. Expect 1."
+
+semverGT $C $A
+echo "$C > $A -> $?. Expect 0."
+
+echo "patch number comparisions"
+semverEQ $A $D
+echo "$A == $D -> $?. Expect 1."
+
+semverLT $A $D
+echo "$A < $D -> $?. Expect 0."
+
+semverGT $A $D
+echo "$A > $D -> $?. Expect 1."
+
+semverEQ $D $A
+echo "$D == $A -> $?. Expect 1."
+
+semverLT $D $A
+echo "$D < $A -> $?. Expect 1."
+
+semverGT $D $A
+echo "$D > $A -> $?. Expect 0."
+
+echo "special section vs no special comparisions"
+semverEQ $A $E
+echo "$A == $E -> $?. Expect 1."
+
+semverLT $A $E
+echo "$A < $E -> $?. Expect 1."
+
+semverGT $A $E
+echo "$A > $E -> $?. Expect 0."
+
+semverEQ $E $A
+echo "$E == $A -> $?. Expect 1."
+
+semverLT $E $A
+echo "$E < $A -> $?. Expect 0."
+
+semverGT $E $A
+echo "$E > $A -> $?. Expect 1."
+
+echo "special section vs special comparisions"
+semverEQ $E $F
+echo "$E == $F -> $?. Expect 1."
+
+semverLT $E $F
+echo "$E < $F -> $?. Expect 0."
+
+semverGT $E $F
+echo "$E > $F -> $?. Expect 1."
+
+semverEQ $F $E
+echo "$F == $E -> $?. Expect 1."
+
+semverLT $F $E
+echo "$F < $E -> $?. Expect 1."
+
+semverGT $F $E
+echo "$F > $E -> $?. Expect 0."
+
+echo "Minor and patch number comparisons"
+semverEQ $A $G
+echo "$A == $G -> $?. Expect 1."
+
+semverLT $A $G
+echo "$A < $G -> $?. Expect 1."
+
+semverGT $A $G
+echo "$A > $G -> $?. Expect 0."
+
+semverEQ $G $A
+echo "$G == $A -> $?. Expect 1."
+
+semverLT $G $A
+echo "$G < $A -> $?. Expect 0."
+
+semverGT $G $A
+echo "$G > $A -> $?. Expect 1."
+}
+
+semverTest