Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Enchancement proposal] Support for optional inclusions using #opt-include reader tag #48

Closed
titonbarua opened this issue Aug 7, 2017 · 1 comment

Comments

@titonbarua
Copy link

titonbarua commented Aug 7, 2017

It is a common pattern to include a default configuration with your application and then override those defaults from other sources(if found) during deployment. Aero'r #include tag seems particularly useful in such situations. The problem is, it does not handle missing files gracefully. Also, the course of action taken for a missing file varies greatly depending on the resolver in use.

After some discussion in clojure slack, someone suggested that a custom reader tag would do the job and it would be trivial to implement. As such, here's an implementation of the #opt-include tag,
which takes a filename along with a default value(which is used if the file is missing), passed as a 2-element vector:

(require 'clojure.java.io)
(require 'clojure.string)
(require 'aero.core)
(import [java.io])

(defn missing?
  "Missing file detection, compatible with relative-resolver."
  [file]
  (or (nil? file)
      (and (= (type file) java.io.StringReader)
           (clojure.string/includes? (slurp file) "missing-include"))))

(defmethod aero.core/reader 'opt-include
  [{:keys [resolver source] :as opts} tag [filename default-val]]
  (try
    (let [f (if (map? resolver)
              (get resolver filename)
              (resolver source filename))]
      (if (missing? f)
        default-val
        (aero.core/read-config f)))
    (catch java.io.FileNotFoundException e
      default-val)))

Example configuration file using #opt-include:

#merge [
   {:host "localhost"}
   #opt-include ["opt-config.edn" {:port 8080}]
]

I plan to submit a pull request later.

@malcolmsparks
Copy link
Contributor

I think this is better to be done in user-code and not Aero. As you say, Aero:

it does not handle missing files gracefully

which is sort of the point. Aero sticks to the principle of zero overrides - the absence of a config file shouldn't cause a change to the config. Instead, it should cause the config loading to fail.

I realise current resolvers' behaviours vary, and that isn't ideal. However, I think we should still preserve the philosophy of Aero in this regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants