diff --git a/gnscli.sh b/gnscli.sh index 2d1aad8..8082139 100755 --- a/gnscli.sh +++ b/gnscli.sh @@ -2,17 +2,17 @@ ## todo # start/stop/del with multiple args broken - # rename node issue when matching multiple # rename project # node stop givesjq error - -# connect xxx & [opens iterm (or whatever)] +# configure docker node IP/mask/gateway +# configure docker node /etc/hosts +# configure docker node env vars VER=1.0 # helper function to turn a directory of scripts into inline -## defaults at the end of this script +# defaults at the end of this script function scriptstoinline() { local outfile files echo "About to convert scripts from $SCRIPTDIR to inline format:" @@ -318,6 +318,13 @@ function harddebug() { echo -e "${YELLOW}${BOLD}$*${PLAIN}" >/dev/stderr } +function harddebug_v() { # varname + local varname str + varname="$1" + eval "str=\"$varname is [\$$varname]\"" + harddebug "$str" +} + function debug() { local force=0 if [[ $1 == "-f" ]]; then @@ -1098,6 +1105,7 @@ function getgnsmethod() { add) echo "";; del) echo "";; mv) echo "";; + dupe) echo "duplicate";; #migrate) echo "migrate";; *) echo @@ -1127,6 +1135,18 @@ function makejson() { # makejson key1:val1^key2:val2^... printf "%s\n" '}' } + +function action_needs_curldata() { # actionname + local a + a="$1" + case $a in + add) return 0;; + mv) return 0;; + dupe) return 0;; + esac + return 1; +} + function runaction_loc() { # runaction_loc syd|etc api_endpoint action_name ob_uuid ob_name "extra info" [options] local thisgrid thisauthdom thisurl thisauthstr curlres loc u p local api_endpoint jq_obj opts opts_arr deffield epidx r1 r2 rv @@ -1155,13 +1175,19 @@ debug -f "arglist - epidx: $epidx" debug -f "arglist - actionname: $actionname" debug -f "arglist - obuuid: $obuuid" debug -f "arglist - obname: $obname" -debug -f "arglist - extrainfo : $extrainfo" +debug -f "arglist - extrainfo: $extrainfo" debug -f "arglist: remaining opts: $opts" - if [[ $actionname == "add" || $actionname == "mv" ]]; then + + + + + if action_needs_curldata $actionname; then + debug -f "action '$actionname' needs curldata" if [[ -n $RAWJSONPOSTDATA ]]; then -debug -f "using RAWJSONPOSTDATA for curldata" + debug -f "-->using RAWJSONPOSTDATA for curldata" curldata="${RAWJSONPOSTDATA}" else + debug -f "-->making curldata from [$extrainfo]" curldata=$(makejson "$extrainfo") fi fi @@ -1726,11 +1752,15 @@ debug -f "--> extrainfo = $extrainfo" elif [[ $actionname == "add" && $endpoint == "link" ]]; then local id # hack: local ID won't be generated ubtil we - # recache, but weknow ot will be the last current + # recache, but we know it will be the last current # id plus one. id=$(get_next_linkid) allgoodresults="Server,${objecttype},Predicted_ID" jqf="[ \"_DC_\", .link_id, \"${id}\" ] | @csv" + elif [[ $actionname == "dupe" && $endpoint == "project" ]]; then + allgoodresults="Server,${objecttype},New_Project_ID" + # return name of NEW object, not old one. + jqf='[ "_DC_", .name, .project_id ] | @csv' elif [[ $actionname == "del" ]]; then allgoodresults="" jqf='' @@ -2236,10 +2266,12 @@ function expand_cmdalias() { # expand_cmdalias "cmd" newcmd_var newargs_var "ar if [[ -n $args ]]; then newargs="$repl_args $args" else + local rawdefarg str + rawdefarg=${cmdalias_defaultarg[$x]} debug "using default arg $defarg" - defarg=${cmdalias_defaultarg[$x]} - defarg=${defarg/_CURPROJECT_/$curproj} - debug " default arg is: [$defarg]" + defarg=${rawdefarg/_CURPROJECT_/$curproj} + [[ $defarg == $rawdefarg ]] && str="$defarg" || str="$rawdefarg ($defarg)" + [[ -n $defarg ]] && warn "Using default object: ^b${str}^p" newargs="$repl_args $defarg" fi changed=1 @@ -2408,6 +2440,7 @@ function action_triggers_recache() { add) trigger=1;; del) trigger=1;; mv) trigger=1;; + dupe) trigger=1;; esac return $((1 - $trigger)) } @@ -2442,6 +2475,8 @@ function addline() { # varname "string_to_append" eval "$varname=\"${newstr}\"" } + + function processcmd() { local cmd arg newarg rv newlocs x err admin idx opts pipe gotargs local whattolist actionname="" actionfilter="" @@ -2525,8 +2560,10 @@ debug "post replacedargs is [$replacedargs]" fi gotargs=$( printf %d $(wc -w <<< "$arg")) - if [[ $cmd == "action" && $arg == "node connect" ]]; then - debug "special case - ignoring arg count for conne t action" + if [[ $cmd == "action" && $arg == "node connect" && $gotargs -eq 2 ]]; then + debug "special case - ignoring arg count for connect action" + elif [[ $cmd == "action" && $arg == "node start" && $gotargs -eq 2 ]]; then + debug "special case - ignoring arg count for connect action" elif [[ $gotargs -lt ${cmd_minargs[$idx]} || $gotargs -gt ${cmd_maxargs[$idx]} ]]; then error "${cmd_name[$idx]} requires ${cmd_needargs[$idx]} arguments (got $gotargs)" return 1 @@ -2557,7 +2594,7 @@ debug "post replacedargs is [$replacedargs]" if [[ $actionname == "add" ]]; then newname=${arg_array[2]} if [[ -z $newname ]]; then - error "Name of new $whattolist not provided." + error "Name of new $whattolist to add not provided." return 1 fi if [[ $endpoint == "node" ]]; then @@ -2598,10 +2635,11 @@ debug "post replacedargs is [$replacedargs]" error "Don't know how to add a $endpoint yet" return 1 fi - elif [[ $actionname == "mv" ]]; then + elif [[ $actionname == "mv" || $actionname == "dupe" ]]; then oldname=${arg_array[2]} newname=${arg_array[3]} - actionfilter="-f.*${oldname}.*" + actionfilter="-f${oldname}" + obname="$oldname" else # start/stop/del/etc # oooo does thiss work with multi args? @@ -2609,9 +2647,16 @@ debug "post replacedargs is [$replacedargs]" convert_link_ids $endpoint "${arg_array[@]}" || return 1 actionfilter="-f${CLIDS_RES}" obname="${CLIDS_RES}" - elif [[ $cmd != "action" || $arg != "node connect" ]]; then - error "Name of $whattolist not provided." - return 1 + else + if [[ $cmd == "action" || $arg == "node connect" ]]; then + debug "connect with no arg - will just resume session" + elif [[ $cmd == "action" || $arg =~ \ start$ ]]; then + debug "start node with no arg - will start all nodes" + actionfilter="-f*" + else + error "Name of $whattolist not provided. cmd is $cmd, arg is $arg" + return 1 + fi fi fi fi @@ -2827,8 +2872,20 @@ debug "adapnumlist is $adapnumlist" else textdata="$data" fi + + if [[ ${actionname} == "dupe" ]]; then + if [[ ${endpoint} == "project" ]]; then + if [[ -z $newname ]]; then + newname="${oldname}2" + warn "Using default new name: ^b$newname^p " + fi + fi + fi + + cecho "$INFORMCOL" "$INFORMCOLB" "About to run '^b$actionname^p' on ^b${nobs}^p ${whattolist}${ob_ess} on ^b${ndcs}^p server${dc_ess}:" - echo -e "$textdata" | awk -F, -v EP="$endpoint" "BEGIN {lastdc=\"\"} { if (\$1 != lastdc) { print \" ${YELLOW}- ${BOLD}\" \$1 (EP == \"project\") ? \"\" : \" -> project=${curproj}${PLAIN}\"; lastdc=\$1; } print \" ${YELLOW}- \" \$2 \"${PLAIN}\"}" + echo -e "$textdata" | awk -F, -v NN="$newname" -v EP="$endpoint" "BEGIN {lastdc=\"\"} { if (\$1 != lastdc) { print \" ${YELLOW}- ${BOLD}\" \$1 (EP == \"project\") ? \"\" : \" -> project=${curproj}${PLAIN}\"; lastdc=\$1; } if (NN) { moreinfo = sprintf(\" (new name: ${BOLD}%s${PLAIN}${YELLOW})\",NN); } print \" ${YELLOW}- \" \$2 moreinfo \"${PLAIN}\"}" + echo if [[ $ndcs -le 1 ]]; then @@ -2893,7 +2950,7 @@ debug "adapnumlist is $adapnumlist" postdata="name:$newname" actiontargets="$curlocs,$newname,,$postdata" fi - elif [[ $actionname == "mv" ]]; then + elif [[ $actionname == "mv" || $actionname == "dupe" ]]; then oldname=$(echo "$data" | awk -F, '{ print $2 }' | sort -u) olduuid=$(echo "$data" | awk -F, '{ print $3 }' | sort -u) @@ -2901,6 +2958,7 @@ debug "adapnumlist is $adapnumlist" else actiontargets=$(echo "$data") fi + if [[ $actionname == "connect" ]]; then local devname sevname srvport if [[ -z $data ]]; then @@ -2958,12 +3016,10 @@ debug " outputfile = ${TMPFILE}" fi if [[ $rv -eq 0 ]]; then - - if [[ $actionname =~ ^add|del$ && $endpoint == "project" ]]; then - loadprojectlist || exit 1 - fi - if action_triggers_recache $actionname; then + if [[ $endpoint == "project" ]]; then + loadprojectlist + fi start_recache fi fi @@ -3245,7 +3301,12 @@ addendpoint projects projects project project_id name addepalias projects p addeptitles projects "Project " "UUID" "Status " addepfields projects ".name" ".project_id" ".status" - addepactions projects open close add del + addepactions projects open close add del dupe + addepactionusage projects "add" "new_projectname" + addepactionusage projects "del" "existing_projectname" + addepactionusage projects "open" "[existing_projectname]" + addepactionusage projects "close" "[existing_projectname]" + addepactionusage projects "dupe" "existing_projectname new_projectname" addendpoint nodes projects/_CURPROJECT_/nodes node node_id name addepalias nodes n @@ -3322,14 +3383,15 @@ addcmdalias "mv" "action node mv" "" addcmdalias "link" "action link add" "" addcmdalias "unlink" "action link del" "" addcmdalias "delink" "action link del" "" -addcmdalias "addp" "action project add" "" -addcmdalias "delp" "action project del" "" +addcmdalias "padd" "action project add" "" +addcmdalias "pdel" "action project del" "" +addcmdalias "pdupe" "action project dupe" "_CURPROJECT_" addcmd help "List regular commands" 0 "?" "h" addcmd exit "Exit from gnscli" 0 quit addcmd -a help "List admin commands" 0 "?" "h" addcmd -a la "List command aliases" 0 -addcmd -a lp "List GNS3 projects on current server(s)" 0 listprojects +addcmd -a lp "List locally known GNS3 projects on current server(s)" 0 listprojects addcmd -a ls "List GNS3 servers" 0 listservers l addcmd -a c "Re-cache UUIDs for current projects" 0 cache addcmd -a sc "Show cached name for given UUID (or all UUIDs if none provided)." 0-1 showcache