This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-10-25
Channels
- # aws (1)
- # bangalore-clj (9)
- # boot (97)
- # capetown (1)
- # cider (4)
- # clara (1)
- # cljs-dev (2)
- # cljsrn (109)
- # clojure (258)
- # clojure-finland (3)
- # clojure-greece (2)
- # clojure-italy (1)
- # clojure-russia (33)
- # clojure-spec (41)
- # clojure-uk (46)
- # clojurescript (57)
- # component (17)
- # core-async (6)
- # datomic (13)
- # devcards (10)
- # dirac (2)
- # euroclojure (1)
- # figwheel (1)
- # funcool (1)
- # hoplon (472)
- # luminus (17)
- # off-topic (1)
- # om (16)
- # onyx (40)
- # pedestal (14)
- # proton (12)
- # re-frame (27)
- # reagent (15)
- # ring-swagger (2)
- # specter (5)
- # testing (4)
- # untangled (258)
- # vim (4)
hey guys… I’m trying to get into cljs-repl (start-repl)
is yelling at me
Can't change/establish root binding of: *cljs-repl-env* with set
. What does this mean? I haven’t seen this last weekSo here’s a question w/ my prototype. I’m building up a Dockerfile, with Boot tasks each “supplying” content. My intermediate format is a simple EDN file. But that means each task has to a) read the EDN file b) update it in memory c) create temp directory d) write Dockerfile.edn to it and c) add the temp directory as a resource:
(defn edit
"Edits an EDN Dockerfile using function f to transform it.
The EDN file is read if it exists, and parsed. The function
is applied. The result is written to a` new temp file, and
added to the fileset as a resource."
[fs f & args]
(let [existing (read-edn fs)
updated (apply f existing args)
out-dir (tmp-dir!)
out-tmp (io/file out-dir file-name)]
(->> updated
prn-str
(spit out-tmp))
(-> fs
(add-resource out-dir)
commit!)))
The final step is to convert the Dockerfile.edn to a Dockerfile before building the image:
(deftask build-image
"Runs Docker in a shell to build an image from the fileset."
[i image-name NAME str "Name of the image to build."
v version VERSION str "Version (appended to the image name)"]
(let [work-dir (tmp-dir!)]
(with-pre-wrap [fs]
(let [fs' (commit! fs)
df (-> (df/read-edn fs')
(df/command :files :add "Dockerfile" (str "Dockerfile-" image-name)))]
(apply sync! work-dir (output-dirs fs'))
(df/write df work-dir)
(util/info "Building Docker image %s:%s in folder %s\n"
image-name version (.getPath work-dir))
(util/dosh "docker" "build"
"-t" (str image-name ":" version)
(.getPath work-dir))
fs'))))
So … my question is … would it be outside the orthodoxy of boot to build up the EDN Dockerfile contents in a dynamic var or atom instead, rather than awkwardly using the file system to store the intermediate steps?
this allows boot to provide certain guarantees with respect to how state changes over time
for example, one important guarantee is that no task will see the effects of tasks that succeed it in the pipeline
if, on the other hand, a task that comes after this task can mutate the global environment you now introduce all kind of issues with state
it is Right and Proper to use the fileset to communicate between tasks
This is true … but I have to wonder if there might be room to extend the fileset concept to include some state in-memory; I’d just as soon make changes to the fileset and not go through the motions of committing these files to the file system.
there is nothing preventing you from mutating global env in your tasks, you can use alter-var-root or swap atoms etc
metadata on a file is another option
personally i would factor my hydrate/dehydrate code into a function or macro to make it less cumbersome to grab/mutate/emit the file in the task
if you don't need to be able to have independent composable tasks then there is no reason why you can't swap atoms or whatever
i see. looks excellent :thumbsup:
But I’ll look at the meta data option as well; I could create an empty Dockerfile and attach and edit meta on it instead.
i guess one question is, do you need the dockerfile to be viable in between your modifications?
Right now, the Dockerfile doesn’t exist until the final step; Dockerfile.edn gets create on first step and modified repeatedly.
it makes it possible to compose other tasks that do things to dockerfiles with your tasks then
maybe it would be awesomer to instaparse the real dockerfile?
But, eventually, I’ll be using some of this code for like 15 or 20 Docker images and doing more in parallel would be cool.
seems like what his edn already is?
{:preamble [[:from "anapsix/alpine-java:8"]], :setup [[:maintainer ""] [:run "mkdir -p /user/local/java-agents"]], :files [[:add "launch.sh" "/"]], :postamble [[:run "chmod a+x lau\
nch.sh"]]}
there must be something that people can use to compose with other docker tasks is what i mean
Ah, here’s the delight of working on a specific solution: I don’t have to go generalize everything! Perhaps later, we’ll be ready to clean it up and open source it, but I’ll do that only after I have a fully working solution that includes not just the Docker parts, but the Kubernetes parts.
not sure if it's good, but the name and dog picture are top notch
that's where atoms come in, if you really don't need generality now you can make a more monolithic stack and use atoms or whatever
that's the problem with this channel and boot in genera, we're always coercing people to abstract things
we have a plan to do better exception notification and it's based on the idea of tucking an atom into the fileset
i can imagine using the same idea to fuse together a bunch of dependent tasks to make a monolithic thing
On another subject … is there anything in the task options to mark an option as required, to do declarative validation, or to supply an explicit default?
(deftask foo
[b bar bool "a flag"
z baz COUNT int "how many bazes (required)"
c car NAME str "name of the car (default 'baby')"]
(assert baz "you must provide the number of bazes")
(let [car (or car "baby")]
...
the DSL is already hairy enough, i couldn't figure out how to accomodate those features without making things more insane
and the assertions etc are very straightforward and easy to reason about when they're explicit
looks like there's still plenty of room to innovate with macros there too
Back to meta; feels like the meta support is really there just to support the by-meta
filter; there isn’t a sanctioned way to get the meta for a particular file back out. What would be the repercussions of just storing what I want as a namespaced key on the fileset itself?
I’m feeling like the namespaced key directly on the fileset is the way to go; it seems to work quite nicely and simplified my code quite a bit.
So far, I’ve been launching boot from the command line. I’m trying to work w/ REPL inside Cursive now.
(defproject gleam "0.0.1"
; A placeholer to allow Cursive to edit the project
:dependencies [[org.clojure/clojure "1.8.0"]
[boot/core "2.6.0" :scope "compile"]])
What am I missing here? boot.App doesn’t seem to be anywhere. https://github.com/boot-clj/boot/wiki/For-Cursive-Users wasn’t helpful here.
Well, I’m trying to run inside Cursive so that is a bit of a challenge. I haven’t played with Cursive connecting to a REPL it didn’t start.
the idea i believe is to use the lein-generate task to generate a project.clj for cursive just so cursive has the classpath and whatnot
but to clarify about boot.App, boot relies on having all clojure runtimes created via boot.App.newPod() or whatever
i use vim with vim-fireplace, and what i do is just start boot repl
in a tmux tab separately from my vim tmux screen
vim-fireplace won't start its own repl if there is already a repl server that's running
so that way the editor doesn't need to be very clever, it just connects to the repl port that's in the .nrepl-port file