Clojure - boot compose task - clojure

I am using boot, and I am happy with it so far.
I still have to run two tasks currently, in two different consoles :
boot dev and boot autotest.
Therefore I would like to know it it is feasible/advised to make all boot tasks within the same JVM.
I tried to compose the tasks like so :
(deftask autotest []
(comp
(watch)
(run-tests)))
(deftask dev
"Start the dev env..."
[t run-tests bool "Run the tests continuously"]
(comp
....
(if run-tests (autotest) identity)))
But now when running boot dev -t I get an exception from one of the libraries that I am using, which could mean that I have to isolate it.
Are boot tasks intended to be used like that, and can boot pods solve my problem ?

Answering my own question:
I no longer have this exception
this is one of the strength of boot to use one single JVM (as opposed to leiningen)

Related

How to create unit test cases for Ansible functionalities?

I want to add unit testing for my ansible playbook. I am new to this and have tried few things but didn't understood much. How can I start on this and write a test case properly?
Following is the simple example:
yum:
name: httpd
state: present
Ansible is not a programming language but a tool that will check the state you describe is aligned with the state of the node your run in against. So you cannot unit tests your tasks. They are in a certain way tests by themselves already. The underlying ansible binary that runs those task has unit tests itself used during its development.
Your example above is asking ansible to test if httpd is present on the target machine and will return ok if this is the case, changed if it had to install the package to fulfill the requirement, or error if something went wrong.
Meanwhile, it is not because you cannot unit test your ansible code that no tests are possible at all. You can perform basic static checks with yammlint and ansible-lint. To go further, you will have to run your playbook/role/collection against a test target node.
This has become quite easy with CI that will let you spawn virtual machines or docker container from scratch and run your script to test that no error is fired, the --check option passes successfully, idempotency is obeyed (i.e. nothing should change on a second run with the same parameters), and everything works as expected (e.g. in your above case port 80 is opened and your get the default Apache web page).
You can write those kind of tests yourself (running against localhost in a test vm for example). This Mac Appstore CLI role by Geerlinguy is using such tests through travis-ci as an example.
You can also use existing tools to help you write those tests in a more structured way like molecule. Here are some example roles using it if you are interested:
Redis role by Geerlinguy
nexus3-oss role by ThoTeam [1]
[1] Note for transparency: I am the maintainer of this example repository

Remote REPL no output, how to dublicate output in PrintWriter?(Clojure)

Cannot connect remote REPL properly
Here are the steps I do:
Start local repl instance:
lein repl
Connect to local by remote repl instance(I do it through Intellij IDEA)
After this, every output in code goes only in local repl, in remote one there are nothing
What I need: to see all outputs in both repl instances
I have found partial solution, this code rebinds output of one repl to another. Just run it in remote one, and all output will go to it
(defn rebind-output []
(prn "Rebinding output...")
(System/setOut (PrintStream. (WriterOutputStream. *out*) true))
(System/setErr (PrintStream. (WriterOutputStream. *err*) true))
(alter-var-root #'*out* (fn [_] *out*))
(alter-var-root #'*err* (fn [_] *err*)))
out - is intstance of PrintWriter
However what I need is: see BOTH repls outputing the same, how to do it?
I can't seem to think that you are confused about how to connect to an existing REPL (the one you launch from the command line with lein repl). Did you check the section Remote REPLs in the Cursive manual?
Generally, you want only one of these:
Launch the REPL from Intellij itself on a project that is already managed with Leiningen (eg. it already has a project.clj file), or
Connect to an already running REPL, one that is running on the same host, or in a different machine.
If you are starting lein repl yourself in a console, you'll see that it prints some messages on startup:
$ lein repl
nREPL server started on port 39919 on host 127.0.0.1 - nrepl://127.0.0.1:39919
In this example, the server started listening on my own host (127.0.0.1 or localhost) on port 39919 (this port will change each time you launch the REPL with lein repl). You'll need to enter these values in Intellij to be able to connect to this REPL.

"Missing host to link to! Please provide the :host parameter"... but I _did_ provide it

I've read similar posts from others having the same problem, and most people resolved it by including:
config.action_mailer.default_url_options = { :host => '#.#.#.#'}
in their environment specific config files. I've done this, and I've also restarted my server.
Here's my mystery. When I try to send an email from my app with a link in it, I get the error in my posting title (as have many others). However, this only is an issue on my staging environment (and Engine Yard instance). My development environment (my local machine) works fine.
In both cases, I have configured action mailer to have a default_url_option as above. For my development environment my :host is local:3000, and for my staging environment (Engine Yard), my :host is an IP address.
I wanted to make sure my staging environment actually loaded the preferences into ActionMailer, so I ran this on the rails console on staging:
ActionMailer::Base.default_url_options
which yielded:
{:host=>"[the staging ip address from the config file]"}
so I know it's in there! But I still am getting "Please provide the :host parameter".
Any ideas?
Here's what I learned: restarting the server isn't the same as restarting the Delayed Job process, and thus, any new config settings aren't made available to the Delayed Jobs process unless it is restarted.
After I manually restarted the Delayed Jobs process on my staging server using:
bin/delayed_job restart
the messages started trickling in.
Quick tip: to force a retry of failed messages in your queue, one at a time, run:
Delayed::Job.last.update_attributes(:attempts=>0, :run_at=>Time.now, :failed_at => nil, :locked_by=>nil, :locked_at=>nil)

How to get Clojure Compojure app to run headless via compiled jar within Docker container?

Update: this question has changed since the original set of commenters left responses. Apologies for any confusion.
This is my code repository https://github.com/Integralist/spurious-clojure-example you can use it as an example for what I'm working with.
Note that the above repo relies on a library I've not yet published to Clojars (as I'm still testing it - hence this question opened). You can see the source code of the library here: https://github.com/Integralist/spurious-clojure-aws-sdk-helper
I have a "hello world" Clojure web app written with Compojure that I have working fine when run using lein ring server and lein run (as I have a -main function now created). It also runs to a certain extent when compiled down into a jar and I run java -jar app.jar.
My problem now is that if I try to run the default java -jar app.jar from within a Docker container I get the following error telling me...
spurious-clojure-example is starting
2015-02-14 00:58:03.812:INFO:oejs.Server:jetty-7.x.y-SNAPSHOT
2015-02-14 00:58:03.854:INFO:oejs.AbstractConnector:Started SelectChannelConnector#0.0.0.0:8080
Started server on port 8080
Exception in thread "main" java.awt.HeadlessException:
My code is currently using a -main function like so...
(ns spurious-clojure-example.repl
(:use spurious-clojure-example.handler
ring.server.standalone
[ring.middleware file-info file])
(:gen-class))
(defonce server (atom nil))
(defn get-handler []
(-> #'app
(wrap-file "resources")
(wrap-file-info)))
(defn start-server
"used for starting the server in development mode from REPL"
[& [port]]
(let [port (if port (Integer/parseInt port) 8080)]
(reset! server
(serve (get-handler)
{:port port
:init init
:auto-reload? true
:destroy destroy
:join true}))
(println (str "You can view the site at http://localhost:" port))))
(defn stop-server []
(.stop #server)
(reset! server nil))
(defn -main []
(start-server))
...but how do I get the server to start headless? I can't quite follow the Compojure boilerplate code to decipher where or how it knows when to run headlessly or via browser?
I know that on the command line you can do lein ring server-headless so what's the programmatic equivalent of that?
Because ring-server is primarily meant for development, it tries to open a browser when the server starts. This fails with a java.awt.HeadlessException on platforms without a GUI. You'll want to set the :open-browser? option to false to prevent this.
From the offical Docker docs on EXPOSE
The EXPOSE instructions informs Docker that the container will listen
on the specified network ports at runtime. Docker uses this
information to interconnect containers using links (see the Docker
User Guide) and to determine which ports to expose to the host when
using the -P flag. Note: EXPOSE doesn't define which ports can be
exposed to the host or make ports accessible from the host by default.
To expose ports to the host, at runtime, use the -p flag or the -P flag.
So if you're setting the ring server port manually in your project.clj, ensure that you're using the same port also in your Dockerfile and then provide a mapping via -p or -P when starting docker.
I can't say for sure but I believe that your headless error message doesn't contribute to your problem.

Clojure app not starting on Heroku; Aleph + RedisToGo timing out

My clojure noir app works 100% fine locally and connects to RedisToGo no problem.
The problem is when I deploy to Heroku (git push heroku master), I get a timeout error:
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
Full log is here: https://gist.github.com/1842439
When I remove this redis connection code, it deploys fine:
(:use [aleph.redis :only (redis-client)])
(def r (redis-client {:host redis-url :password redis-pass :port redis-port}))
The weird thing is that when I run "heroku run lein run repl" and paste in the aleph code above, it connects to redis fine and I can read/write data.
So it something about how heroku boots up the app thats breaking the connection to RedisToGo and timing it out.
Doing something side-effecty at the top level is very suspect - that code is executed when compiling as well as when executing, so probably the automatic uberjar Heroku does is failing because redis isn't available at compile time, or something like that.
Instead, initialize your redis client after -main has been called, which will ensure you are in a production environment. You can accomplish this in a number of ways, for example by initially defining it to nil and then performing an alter-var-root in -main. My preferred solution would probably be something like:
(def r (delay (redis-client ...)))
(defn get-stuff []
(let [client #r] ...))
(defn -main [& args]
(get-stuff)
...)
Now the code to connect isn't performed until someone derefs the client, which they should never do until the app is up and running.