Ashwin
Ashwin

Reputation: 13527

Loading environment variables temporarily on nrepl start up

I have a clojure project using leiningen. I want to load environment variables from a file on nrepl start. I only want this to run on repl start because these environment variables are configured for local development.

The reason I don't want to use default params in edn config is that the environment variables can contain some sensitive info (even for local development) like API TOKENS which will differ for every developer. I do not want this to be commited. There will be a file "repl_env" which will contain all the development evn variables. This file will be added to .gitignore thus making sure that these are never commited.

I see there is :init under :repl-options but I am not sure how I can leverage it to load environment variables. Any suggestions?

Upvotes: 0

Views: 279

Answers (2)

ybrajim
ybrajim

Reputation: 112

The repl will load the environment variables from the current shell session, what you need to do is to load all those environment variables when the user starts a new session, I'm assuming you are using a *nix based OS, you can achieve this by exporting the variables inside the *rc file.

At this point you have at least two flavors: bash or zsh, for both you use the same syntax but in different files, for zsh you can add your variables into $HOME/.zshrc:

# my awesome zshrc file
export MY_SUPER_SECRET_KEY=THISISASECRETKEY
export MY_SUPER_SECRET_VALUE=THISISASECRETVALUE

Now, every time the user starts a shell session, those values will be available for repl, of course each developer should add those values on theirs own file.

I'm using environ library, loading the library into the repl and asking to resolve those variables I got:

enter image description here

I guess you should have similar results using #env from aero.

Upvotes: 0

Rulle
Rulle

Reputation: 4901

Can you use System properties instead of environment variables? If so, here is how you can do it. System properties can be set using command line arguments to the JVM, so it is possible to do it using Leiningen.

Here is how I did it. I created a new project lein new syspropdemo och edited the following files:

Added the line :profiles {:repl {:jvm-opts ["@sysprops.txt"]}} to project.clj and set the main namespace. The string @sysprops.txt means that I want to read additional command line arguments from a file sysprops.txt:

(defproject syspropdemo "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :profiles {:repl {:jvm-opts ["@sysprops.txt"]}}
  :main syspropdemo.core
  :dependencies [[org.clojure/clojure "1.11.1"]]
  :repl-options {:init-ns syspropdemo.core})

Created a basic -main function in src/syspropdemo/core.clj:

(ns syspropdemo.core)

(defn -main [& _args]
  (println "The api key is" (System/getProperty "api_key")))

and also added a file sysprops.txt in the project root that lists options to be used by the JVM:

-Dapi_key=xyz

where I use the -D option to set a system property with key api_key to have value xyz.

$ lein run
The api key is nil
$ lein repl
nREPL server started on port 38171 on host 127.0.0.1
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e

syspropdemo.core=> (-main)
The api key is xyz
nil

In addition to the :repl profile, there are other profiles too, such as :dev, :test, :production, :uberjar.

Upvotes: 0

Related Questions