planck

Planck ClojureScript REPL
tothda 2018-03-06T10:43:38.000046Z

How can I pass environment variables to shell process? I want to execute this command from planck AWS_PROFILE=foo aws s3 ls. But when I try this way (planck.shell/sh "aws" "s3" "ls" :env {"AWS_PROFILE" "foo"}) I got an error "launch path not accessible". Thanks!

mfikes 2018-03-06T12:26:18.000388Z

@tothda I think this means that aws is not on the path.

mfikes 2018-03-06T12:26:53.000208Z

In other words, I think it would fail without the :env

tothda 2018-03-06T12:56:18.000144Z

No, without the :env it calls the aws command

tothda 2018-03-06T12:57:16.000454Z

cljs.user=> (require 'planck.shell)
nil
cljs.user=> (planck.shell/sh "aws" "s3" "ls")
{:exit 255, :out "", :err "Unable to locate credentials. You can configure credentials by running \"aws configure\".\n"}
cljs.user=>

mfikes 2018-03-06T12:57:18.000544Z

Hmm, I would try with-sh-env

mfikes 2018-03-06T12:58:54.000145Z

As in

(shell/with-sh-env {"FOO" "bar"} (shell/sh "env"))

mfikes 2018-03-06T13:00:02.000507Z

this also works

(shell/sh "env" :env {"FOO" "bar"})

mfikes 2018-03-06T13:00:15.000309Z

What is up with the launch path error? Hrm.

mfikes 2018-03-06T13:04:18.000128Z

@tothda As a sanity check, you could fire up a Clojure REPL and try the same command, but instead using [clojure.java.shell :as shell] to see if it reveals more.

tothda 2018-03-06T13:04:37.000059Z

okay, I'll do thanks

mfikes 2018-03-06T13:08:01.000380Z

If Planck's code sees exit codes of 126 and 127 it throws that exception. I can't recall exactly why, but the goal is to behave like clojure.java.shell.

tothda 2018-03-06T13:15:38.000515Z

strange, but the it works with clojure.java.shell

mfikes 2018-03-06T13:16:01.000431Z

Odd

mfikes 2018-03-06T13:19:04.000360Z

@tothda Well, one cool thing you can do, since Planck is self-hosted, is dynamically re-define the behavior.

mfikes 2018-03-06T13:19:40.000284Z

If you do (in-ns 'planck.shell) in a Planck REPL you can then

(defn- sh-internal
  [& args]
  (let [{:keys [cmd opts cb]} (s/conform ::sh-async-args args)]
    (when (nil? cmd)
      (throw (s/explain ::sh-async-args args)))
    (when-not (s/valid? (s/nilable ::string-string-map?) *sh-env*)
      (throw (js/Error. (s/explain-str ::string-string-map? *sh-env*))))
    (let [{:keys [in in-enc out-enc env dir]}
          (merge {:out-enc nil :in-enc nil :dir (and *sh-dir* [:sh-dir *sh-dir*]) :env *sh-env*}
            (into {} (map (comp (juxt :key :val) second) opts)))
          dir        (and dir (:path (as-file (second dir))))
          async?     (not= cb nil-func)
          translated (translate-result (js/PLANCK_SHELL_SH (clj->js cmd) in in-enc out-enc
                                         (clj->js (seq env)) dir (if async? (assoc-cb cb))))
          {:keys [exit err]} translated]
      (if async? nil translated))))

mfikes 2018-03-06T13:20:04.000147Z

This would get rid of the code that looks at the exit values and it will let you see the true :exit and :err

tothda 2018-03-06T13:26:19.000394Z

when I do this the result is {:exit 127, :out "", :err ""}

mfikes 2018-03-06T13:27:19.000175Z

And clojure.java.shell can find aws and returns an :exit 0. Hrm.

mfikes 2018-03-06T13:28:37.000571Z

I wonder if aws is itself a script that has an interpreter that isn't found with the way Planck launches it.

tothda 2018-03-06T13:31:57.000260Z

aws was installed with brew and the shebang line is #!/usr/local/Cellar/awscli/1.11.170/libexec/bin/python

mfikes 2018-03-06T13:31:59.000125Z

127 means it can't find the command http://tldp.org/LDP/abs/html/exitcodes.html

mfikes 2018-03-06T13:32:24.000017Z

Cool. I'm doing brew install awscli myself to see what's up

mfikes 2018-03-06T13:32:40.000555Z

And this only occurs when you actually provide the credentials

tothda 2018-03-06T13:35:21.000297Z

yes, when I don't pass the AWS_PROFILE then aws is found an it gives an error

mfikes 2018-03-06T13:35:38.000116Z

Cool, I can repro the issue @tothda, will dig into it now and let you know shortly

tothda 2018-03-06T13:36:08.000290Z

Thanks a lot @mfikes!

mfikes 2018-03-06T13:46:28.000582Z

https://github.com/mfikes/planck/issues/672

mfikes 2018-03-06T14:19:34.000123Z

@tothda Still, digging, but a (unsavory) workaround appears to be to set the environment prior to running Planck, as in

AWS_PROFILE=foo planck

mfikes 2018-03-06T14:54:53.000357Z

@tothda Discovered that if you set any env, Planck blows away the needed PATH environment variable. I'm looking into the Java source code to see what it actually does in that case that allows it to succeed. So two more workarounds result from this discovery: 1. Use "/usr/local/bin/aws" as the first parameter to sh 2. If you specify an env map, include a "PATH" key, with "/usr/local/bin" and whatever else might be needed. I'm going to fix the underlying Planck issue to make it behave like clojure.java.shell

tothda 2018-03-06T15:05:26.000179Z

I tried the 2nd workaround and it works indeed. Thx

mfikes 2018-03-06T16:29:08.000789Z

@tothda Was able to fix it. That was a good catch. In summary, Planck needs to ensure that the environment passed is for the child process. It was messing with the parent process, and thus breaking the ability to even find things on the PATH.

tothda 2018-03-06T16:36:32.000259Z

Fantastic! That was fast. Thanks again for you help and for Planck!

mfikes 2018-03-06T16:37:26.000422Z

Cool @tothda my plan is to release Planck when ClojureScript 1.10.x comes out (perhaps in a week). If you need help building it prior to then, let me know.

tothda 2018-03-06T16:38:24.000376Z

Not needed, I'm okay with the adding the PATH to env until the new release is out.

mfikes 2018-03-06T16:38:32.000414Z

Cool 🙂