puppetlabs/trapperkeeper

Regression in 1.4.0 when loading bootstrap.cfg from resources/ classpath?

Closed this issue · 8 comments

Just updated our TK app to version 1.4.0 and now we're seeing the following exception on app startup:

Caused by: java.io.FileNotFoundException: /var/app/current/revcaster-shopper.jar!/bootstrap.cfg (No such file or directory) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.(FileInputStream.java:138) at clojure.java.io$fn__9524.invokeStatic(io.clj:238) at clojure.java.io$fn__9524.invoke(io.clj:235) at clojure.java.io$fn__9433$G__9426__9440.invoke(io.clj:69) at clojure.java.io$fn__9528.invokeStatic(io.clj:248) at clojure.java.io$fn__9528.invoke(io.clj:248) at clojure.java.io$fn__9433$G__9426__9440.invoke(io.clj:69) at clojure.java.io$fn__9494.invokeStatic(io.clj:165) at clojure.java.io$fn__9494.invoke(io.clj:165) at clojure.java.io$fn__9446$G__9422__9453.invoke(io.clj:69) at clojure.java.io$reader.invokeStatic(io.clj:102) at clojure.java.io$reader.doInvoke(io.clj:86) at clojure.lang.RestFn.invoke(RestFn.java:410) at puppetlabs.trapperkeeper.bootstrap$eval14711$read_config__14716$fn__14717.invoke(bootstrap.clj:144) ... 31 more
Exception in thread "main" java.lang.IllegalArgumentException: Specified bootstrap config file does not exist: 'file:/var/app/current/revcaster-shopper.jar!/bootstrap.cfg' at puppetlabs.trapperkeeper.bootstrap$eval14688$wrap_uri_error__14693$fn__14694.invoke(bootstrap.clj:131) at puppetlabs.trapperkeeper.bootstrap$eval14688$wrap_uri_error__14693.invoke(bootstrap.clj:127) at puppetlabs.trapperkeeper.bootstrap$eval14711$read_config__14716$fn__14717.invoke(bootstrap.clj:153) at puppetlabs.trapperkeeper.bootstrap$eval14711$read_config__14716.invoke(bootstrap.clj:134) at puppetlabs.trapperkeeper.bootstrap$eval14734$get_annotated_bootstrap_entries__14739$fn__14740$iter__14741__14747$fn__14748.invoke(bootstrap.clj:160) at clojure.lang.LazySeq.sval(LazySeq.java:40) at clojure.lang.LazySeq.seq(LazySeq.java:49) at clojure.lang.RT.seq(RT.java:521) at clojure.core$seq__4357.invokeStatic(core.clj:137) at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:24) at clojure.core.protocols$fn__6738.invokeStatic(protocols.clj:75) at clojure.core.protocols$fn__6738.invoke(protocols.clj:75) at clojure.core.protocols$fn__6684$G__6679__6697.invoke(protocols.clj:13) at clojure.core$reduce.invokeStatic(core.clj:6545) at clojure.core$reduce.invoke(core.clj:6527) at puppetlabs.trapperkeeper.bootstrap$eval14974$remove_duplicate_entries__14979$fn__14980.invoke(bootstrap.clj:284) at puppetlabs.trapperkeeper.bootstrap$eval14974$remove_duplicate_entries__14979.invoke(bootstrap.clj:263) at puppetlabs.trapperkeeper.bootstrap$eval15000$parse_bootstrap_configs_BANG___15007$fn__15008.invoke(bootstrap.clj:304) at puppetlabs.trapperkeeper.bootstrap$eval15000$parse_bootstrap_configs_BANG___15007.invoke(bootstrap.clj:293) at puppetlabs.trapperkeeper.core$eval15288$boot_with_cli_data__15295$fn__15296.invoke(core.clj:129) at puppetlabs.trapperkeeper.core$eval15288$boot_with_cli_data__15295.invoke(core.clj:95) at puppetlabs.trapperkeeper.core$eval15317$run__15322$fn__15323.invoke(core.clj:151) at puppetlabs.trapperkeeper.core$eval15317$run__15322.invoke(core.clj:145) at puppetlabs.trapperkeeper.core$main.invokeStatic(core.clj:173) at puppetlabs.trapperkeeper.core$main.doInvoke(core.clj:159) at clojure.lang.RestFn.invoke(RestFn.java:421) at clojure.lang.Var.invoke(Var.java:383) at clojure.lang.AFn.applyToHelper(AFn.java:156) at clojure.lang.Var.applyTo(Var.java:700) at clojure.core$apply.invokeStatic(core.clj:646) at clojure.core$apply.invoke(core.clj:641) at puppetlabs.trapperkeeper.main$_main.doInvoke(main.clj:7) at clojure.lang.RestFn.applyTo(RestFn.java:137) at puppetlabs.trapperkeeper.main.main(Unknown Source)

For now we're able to work around it successfully by adding the --bootstrap-config option to our startup script and deploying the bootstrap.cfg file along with our jar.

@jpinsonault can you take a look at this on Monday and throw a Jira ticket up if you know what's going on?

@cprice404 Looking into it

@dparis Did you have the --bootstrap-config option set prior to upgrading? If so, what did it look like.

In the stack trace, it looks like TK is trying to open 'file:/var/app/current/revcaster-shopper.jar!/bootstrap.cfg' That wouldn't be a valid jar URI I believe, it would need to look like 'jar:file:/var/app/current/revcaster-shopper.jar!/bootstrap.cfg'.

If you didn't have the --bootstrap-config option set previously, then we must have messed up how TK gets paths from jar files. I'll keep looking into it.

Thanks for reporting this

@jpinsonault No, I didn't have --bootstrap-config set up before, I was just relying trapperkeeper to find bootstrap.cfg on the class path. We only stubbed our toes on this in production, when launching from an uberjar directly. At the REPL, we're loading the system using the following init function:

(defn init
  []
  (alter-var-root
   #'system
   (fn [_] (tk/build-app
            (tkb/parse-bootstrap-config! "./dev-resources/bootstrap.cfg")
            (tkc/load-config "./dev-resources/config.edn"))))
  (alter-var-root #'system tka/init)
  (tka/check-for-errors! system))

This function did not require any changes when we upgraded from 1.3.x to 1.4.x. Given that it can load successfully when calling parse-bootstrap-config! and passing that value directly to build-app, I'd guess that your hunch about JAR-file path breakage is accurate.

Happy hunting! If there's anything I can do to assist in reproducing or testing, let me know.

@dparis so in production you just had the single uberjar on the classpath, with bootstrap.cfg packaged as a resource at the root of the jar, and you weren't passing any value for --bootstrap-config, and it would just find it properly?

That seems like desirable behavior and if it was working before we will see if we can fix it, just making 100% sure that I understand your scenario. Thanks for the bug report.

@cprice404 Yup, that's exactly what we were doing. According to the TK bootstrapping docs, this is the suggested approach for "normal use cases", but our CD workflow supports both approaches so we're fine either way. Thank you for looking into it!

@dparis We've just done a bugfix release, 1.4.1, which should fix the issue you're having

Closing this, should be fixed in 1.4.1. Feel free to re-open if it's still an issue!