Fork me on GitHub
#planck
<
2018-03-06
>
tothda10:03:38

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!

mfikes12:03:18

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

mfikes12:03:53

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

tothda12:03:18

No, without the :env it calls the aws command

tothda12:03:16

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=>

mfikes12:03:18

Hmm, I would try with-sh-env

mfikes12:03:54

As in

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

mfikes13:03:02

this also works

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

mfikes13:03:15

What is up with the launch path error? Hrm.

mfikes13:03:18

@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.

tothda13:03:37

okay, I'll do thanks

mfikes13:03:01

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.

tothda13:03:38

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

mfikes13:03:04

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

mfikes13:03:40

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))))

mfikes13:03:04

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

tothda13:03:19

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

mfikes13:03:19

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

mfikes13:03:37

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

tothda13:03:57

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

mfikes13:03:24

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

mfikes13:03:40

And this only occurs when you actually provide the credentials

tothda13:03:21

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

mfikes13:03:38

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

tothda13:03:08

Thanks a lot @mfikes!

mfikes14:03:34

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

AWS_PROFILE=foo planck

mfikes14:03:53

@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

tothda15:03:26

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

mfikes16:03:08

@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.

tothda16:03:32

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

mfikes16:03:26

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.

tothda16:03:24

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