Skip to content

Commit

Permalink
add :stdin option to shell module - #98
Browse files Browse the repository at this point in the history
  • Loading branch information
retrogradeorbit committed Jun 27, 2020
1 parent 2c6c7c8 commit 4807ca4
Showing 1 changed file with 58 additions and 30 deletions.
88 changes: 58 additions & 30 deletions src/clj/spire/module/shell.clj
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
(ns spire.module.shell
(:require [spire.state :as state]
[spire.facts :as facts]
[spire.ssh :as ssh]
[spire.remote :as remote]
[spire.utils :as utils]
[spire.module.rm :as rm]
[spire.module.upload :as upload]
[clojure.string :as string]))

(def failed-result {:exit 1 :out "" :err "" :result :failed})
Expand All @@ -25,7 +27,7 @@

#_ (make-exists-string ["privatekey" "public\"key"])

(utils/defmodule shell* [{:keys [env dir shell out opts cmd creates]
(utils/defmodule shell* [{:keys [env dir shell out opts cmd creates stdin]
:or {env {}
dir "."
shell "bash"}
Expand All @@ -35,40 +37,58 @@
(or (preflight opts)
(let [{:keys [agent-forwarding]} (state/get-host-config)
shell-path (facts/get-fact [:paths (keyword shell)])
remote-script-file (remote/make-temp-filename {:prefix "spire-shell-"
:extension "sh"})
default-env (if shell-path
{:SHELL shell-path}
{})
env-string (->> env
(merge default-env)
make-env-string)
{:keys [exit out err] :as result}
(exec-fn session
;; command
(shell-fn shell)

;; stdin
(stdin-fn
(if creates
(format "cd \"%s\"\nif [ %s ]; then\nexit 0\nelse\nexport %s; set -e; %s\nexit -1\nfi\n"
dir (make-exists-string creates)
env-string cmd)
(format "cd \"%s\"; export %s; %s" dir env-string cmd)))

;; output format
(or out "UTF-8")

;; options
(into {:agent-forwarding agent-forwarding}
(or opts {})))]

(assoc result
:out-lines (string/split-lines out)

:result
(cond
(zero? exit) :ok
(= 255 exit) :changed
:else :failed)))))
script (if creates
(format "cd \"%s\"\nif [ %s ]; then\nexit 0\nelse\nexport %s; set -e; %s\nexit -1\nfi\n"
dir (make-exists-string creates)
env-string cmd)
(format "cd \"%s\"; export %s; %s" dir env-string cmd))]

;; if stdin is specified we create a remote script to execute
;; and pass in out stdin to it. We delete this file after execution
(when stdin (upload/upload* nil nil nil {:content script :dest remote-script-file}))

;; if stdin is not specified, we feed the script directly to the
;; process as stdin
(try
(let [{:keys [exit out err] :as result}
(exec-fn session
;; command
(shell-fn
(if stdin
(format "%s %s" shell remote-script-file)
shell))

;; stdin
(stdin-fn
(if stdin
stdin
script))

;; output format
(or out "UTF-8")

;; options
(into {:agent-forwarding agent-forwarding}
(or opts {})))]
(assoc result
:out-lines (string/split-lines out)

:result
(cond
(zero? exit) :ok
(= 255 exit) :changed
:else :failed)))
(finally
(when stdin (rm/rm* remote-script-file)))
))))

(defmacro shell
"run commands and shell snippets on the remote hosts.
Expand All @@ -87,6 +107,9 @@
on a remote system, and relative to the execution that was the
current working directory when spire was executed.
`:stdin` supply a string argument to pass to the executing script as
its standard input
`:env` a hashmap of environment variables to set before executing
the command. Environment variable names (the hashmap keys) can be
keywords or strings.
Expand Down Expand Up @@ -124,6 +147,11 @@
:type :string
:required false}]

[:stdin
{:description ["Supply a string argument to pass to the executing script as its standard input"]
:type :string
:required :false}]

[:dir
{:description ["Execute the command from within the specified directory."
"Path can be relative or absolute."
Expand Down

0 comments on commit 4807ca4

Please sign in to comment.