Skip to content

Commit

Permalink
Split into deps and lein projects, Makefile -> bb.edn
Browse files Browse the repository at this point in the history
  • Loading branch information
adrech committed Nov 16, 2023
1 parent ef87c71 commit 92c9694
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 63 deletions.
45 changes: 0 additions & 45 deletions dev/tramp-sample-project/Dockerfile

This file was deleted.

43 changes: 43 additions & 0 deletions dev/tramp-sample-project/Dockerfile.template
@@ -0,0 +1,43 @@
# Use an official Clojure image as parent
FROM {{container/parent}}

# PATH "hardening"
#
# Upstream does not install the jdk via apt, but (1) copies it to /opt and
# (2) adds it to PATH in an ENV directive. These are available when using docker
# commands like run or exec, but will not propagate through ssh.
#
# Moreover, when executing a shell-command via tramp, it won't lookup the user-specific
# PATH by default. Instead, it searches for the executable in conventional directories
# like /usr/bin and the remotes initial `getconf PATH`.
#
# Lastly, in the case of running a login shell, PATH will be overwritten by /etc/profile
# with a hardcoded value.
#
# To circumvent these and other potential issues, we ensure that java
# is symlinked to the expected places.
RUN ln -sv $JAVA_HOME/bin/* /usr/bin/

# Persisting upstreams other envars to /etc/environment ensures that they are available
# from *everywhere* unless overwritten.
RUN echo JAVA_HOME=$JAVA_HOME >> /etc/environment && \
echo CLOJURE_VERSION=$CLOJURE_VERSION >> /etc/environment

# SSH server setup
RUN apt-get update && apt-get install -y \
openssh-server && \
# Start as a service once, to init necessary runtime state
service ssh start && \
# ! Allow remote root access !
# ! password: cider !
sed -i 's/^#* *PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
echo 'root:cider' | chpasswd
EXPOSE 22

# Project folder initialization
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN {{project/init-cmd}}

# Run the ssh server. [-D]on't be a daemon. Log to std[-e]rr.
ENTRYPOINT ["/usr/sbin/sshd","-De"]
10 changes: 0 additions & 10 deletions dev/tramp-sample-project/Makefile

This file was deleted.

18 changes: 18 additions & 0 deletions dev/tramp-sample-project/Makefile.template
@@ -0,0 +1,18 @@
build: remove-from-known-hosts
docker build -t {{container/name}} .

run: build
docker run -p {{container/ssh-port}}:22 {{container/name}}

remove-from-known-hosts:
ssh-keygen -R '[localhost]:{{container/ssh-port}}'

ssh-login:
echo "Password is: cider"
ssh root@localhost -p {{container/ssh-port}}

stop:
docker stop `(docker ps --quiet --filter ancestor={{container/name}})` || exit 0

cleanup: stop
docker remove `(docker ps --all --quiet --filter ancestor={{container/name}})`
15 changes: 10 additions & 5 deletions dev/tramp-sample-project/README.md
Expand Up @@ -6,13 +6,17 @@ This way, for development purposes, we can SSH into it with TRAMP and exercise C

## Some ways to get started:

### `cider-jack-in` from a tramp buffer
* `M-:` `(async-shell-command "make run")` to run the Docker image
* `M-:` `(find-file "/sshx:root@localhost#8022:/usr/src/app/src/foo.clj")`
* `M-x` `cider-jack-in`
* Enter password: `cider`
### Using babashka

* Use `bb run lein` or `bb run tools-deps` to start a container
* Follow the on screen instructions
* Stop the container[s] with `bb stop lein`, `bb stop tools-deps`
* Remove them with `bb clean lein`, `bb clean tools-deps`
* See `bb.edn` for all commands and how this is wired up


### Manually create a remote repl and connect to it
* cd to `./lein`
* In one terminal tab, run `make run` to run the Docker image
* Once it's ready, from another tab, run `make ssh` and start a repl manually from there
* The password is `cider`
Expand All @@ -24,3 +28,4 @@ Now, from emacs you can `cider-connect` to localhost.
* `M-x cider-connect` (choose `localhost`, `7888`)

NOTE: Do not visit `foo.clj` directly - do it from dired instead.

55 changes: 55 additions & 0 deletions dev/tramp-sample-project/bb.edn
@@ -0,0 +1,55 @@
;; TODO Troubleshooting and explainers:
;; - provide a better fix for the ssh-key problem
;; - ! (nrepl-use-ssh-fallback-for-remote-hosts t) has to be t
;; - vterm will fail with /usr/bin/bash, there's only /bin/bash
;; - explain unsafe autosafe names
;; - ! message how to connect
;; - ! password? and fingerprint?
;; - check if already running and stop it

{:paths ["."]
:tasks
{build {:depends [-dockerfile]
:task (bash "docker build -t {{container/name}} ./{{project/dir}}")}
start {:depends [build]
:task
(do (echo "\n--------------------------------------------------------------------------------\n"
"Get started:\n"
" (1) M-x find-file \"ssh:/root@localhost#{{container/ssh-port}}:/usr/src/app/src/foo.clj\""
" (2) Accept the host key [on xfirst run only]"
" (3) Enter password: \"cider\""
" (4) M-x cider-jack-in-clj"
"\n--------------------------------------------------------------------------------\n")
(bash "docker run -p {{container/ssh-port}}:22 {{container/name}}"))}
stop (bash "docker stop $(docker ps --quiet --filter ancestor={{container/name}}) || exit 0")
cleanup {:depends [stop -remove-from-known-hosts]
:task (bash "docker remove `(docker ps --all --quiet --filter ancestor={{container/name}})`")}
list (bash "docker ps --filter ancestor={{container/name}}")

-remove-from-known-hosts (bash "ssh-keygen -R \"[localhost]:{{container/ssh-port}}\"")
;; TODO stop if already running

-dockerfile (spit (str (:project/dir target) "Dockerfile") (selmer/render-file "Dockerfile.template" target))
-makefile (spit (str (:project/dir target) "Makefile") (selmer/render-file "Makefile.template" target))

:init
(do (def config
{:lein {:project/dir "lein-app/"
:project/init-cmd "lein deps"
:container/ssh-port "8022"
:container/name "cider-tramp-dev-lein"
:container/parent "clojure:temurin-17-lein-bullseye"}
:tools-deps {:project/dir "tools-deps-app/"
:project/init-cmd "clojure -P"
:container/ssh-port "9022"
:container/name "cider-tramp-dev-tools-deps"
:container/parent "clojure:temurin-17-tools-deps-bullseye"}})

(def target (config (or (keyword (first *command-line-args*)) :tools-deps)))
(defn bash [s] (shell (str "bash -c '" (selmer/render s target) "'")))
(defn echo [& lines] (println (selmer/render (str/join "\n" lines) target)))
;; Print the shell-command that's executed. From https://clojurians.slack.com/archives/CLX41ASCS/p1693517240805539?thread_ts=1693515381.686759&cid=CLX41ASCS
(alter-var-root (var babashka.process/*defaults*) assoc :pre-start-fn (fn [m] (apply println ">" (:cmd m)))))
:leave (println "Finished task:" (:name (current-task)))
:requires ([selmer.parser :as selmer]
[clojure.string :as str])}}
43 changes: 43 additions & 0 deletions dev/tramp-sample-project/lein-app/Dockerfile
@@ -0,0 +1,43 @@
# Use an official Clojure image as parent
FROM clojure:temurin-17-lein-bullseye

# PATH "hardening"
#
# Upstream does not install the jdk via apt, but (1) copies it to /opt and
# (2) adds it to PATH in an ENV directive. These are available when using docker
# commands like run or exec, but will not propagate through ssh.
#
# Moreover, when executing a shell-command via tramp, it won't lookup the user-specific
# PATH by default. Instead, it searches for the executable in conventional directories
# like /usr/bin and the remotes initial `getconf PATH`.
#
# Lastly, in the case of running a login shell, PATH will be overwritten by /etc/profile
# with a hardcoded value.
#
# To circumvent these and other potential issues, we ensure that java
# is symlinked to the expected places.
RUN ln -sv $JAVA_HOME/bin/* /usr/bin/

# Persisting upstreams other envars to /etc/environment ensures that they are available
# from *everywhere* unless overwritten.
RUN echo JAVA_HOME=$JAVA_HOME >> /etc/environment && \
echo CLOJURE_VERSION=$CLOJURE_VERSION >> /etc/environment

# SSH server setup
RUN apt-get update && apt-get install -y \
openssh-server && \
# Start as a service once, to init necessary runtime state
service ssh start && \
# ! Allow remote root access !
# ! password: cider !
sed -i 's/^#* *PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
echo 'root:cider' | chpasswd
EXPOSE 22

# Project folder initialization
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN lein deps

# Run the ssh server. [-D]on't be a daemon. Log to std[-e]rr.
ENTRYPOINT ["/usr/sbin/sshd","-De"]
18 changes: 18 additions & 0 deletions dev/tramp-sample-project/lein-app/Makefile
@@ -0,0 +1,18 @@
build: remove-from-known-hosts
docker build -t cider-tramp-dev-lein .

run: build
docker run -p 8022:22 cider-tramp-dev-lein

remove-from-known-hosts:
ssh-keygen -R '[localhost]:8022'

ssh-login:
echo "Password is: cider"
ssh root@localhost -p 8022

stop:
docker stop `(docker ps --quiet --filter ancestor=cider-tramp-dev-lein)` || exit 0

cleanup: stop
docker remove `(docker ps --all --quiet --filter ancestor=cider-tramp-dev-lein)`
File renamed without changes.
7 changes: 7 additions & 0 deletions dev/tramp-sample-project/lein-app/src/foo.clj
@@ -0,0 +1,7 @@
(ns foo
(:require
[clj-http.client :as client]))

(def home (client/get "http://www.clojure.org"))

(sort-by second > (frequencies (:body home)))
3 changes: 0 additions & 3 deletions dev/tramp-sample-project/src/foo.clj

This file was deleted.

43 changes: 43 additions & 0 deletions dev/tramp-sample-project/tools-deps-app/Dockerfile
@@ -0,0 +1,43 @@
# Use an official Clojure image as parent
FROM clojure:temurin-17-tools-deps-bullseye

# PATH "hardening"
#
# Upstream does not install the jdk via apt, but (1) copies it to /opt and
# (2) adds it to PATH in an ENV directive. These are available when using docker
# commands like run or exec, but will not propagate through ssh.
#
# Moreover, when executing a shell-command via tramp, it won't lookup the user-specific
# PATH by default. Instead, it searches for the executable in conventional directories
# like /usr/bin and the remotes initial `getconf PATH`.
#
# Lastly, in the case of running a login shell, PATH will be overwritten by /etc/profile
# with a hardcoded value.
#
# To circumvent these and other potential issues, we ensure that java
# is symlinked to the expected places.
RUN ln -sv $JAVA_HOME/bin/* /usr/bin/

# Persisting upstreams other envars to /etc/environment ensures that they are available
# from *everywhere* unless overwritten.
RUN echo JAVA_HOME=$JAVA_HOME >> /etc/environment && \
echo CLOJURE_VERSION=$CLOJURE_VERSION >> /etc/environment

# SSH server setup
RUN apt-get update && apt-get install -y \
openssh-server && \
# Start as a service once, to init necessary runtime state
service ssh start && \
# ! Allow remote root access !
# ! password: cider !
sed -i 's/^#* *PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config && \
echo 'root:cider' | chpasswd
EXPOSE 22

# Project folder initialization
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN clojure -P

# Run the ssh server. [-D]on't be a daemon. Log to std[-e]rr.
ENTRYPOINT ["/usr/sbin/sshd","-De"]
18 changes: 18 additions & 0 deletions dev/tramp-sample-project/tools-deps-app/Makefile
@@ -0,0 +1,18 @@
build: remove-from-known-hosts
docker build -t cider-tramp-dev-tools-deps .

run: build
docker run -p 9022:22 cider-tramp-dev-tools-deps

remove-from-known-hosts:
ssh-keygen -R '[localhost]:9022'

ssh-login:
echo "Password is: cider"
ssh root@localhost -p 9022

stop:
docker stop `(docker ps --quiet --filter ancestor=cider-tramp-dev-tools-deps)` || exit 0

cleanup: stop
docker remove `(docker ps --all --quiet --filter ancestor=cider-tramp-dev-tools-deps)`
1 change: 1 addition & 0 deletions dev/tramp-sample-project/tools-deps-app/deps.edn
@@ -0,0 +1 @@
{}
7 changes: 7 additions & 0 deletions dev/tramp-sample-project/tools-deps-app/src/foo.clj
@@ -0,0 +1,7 @@
(ns foo
(:require
[clj-http.client :as client]))

(def home (client/get "http://www.clojure.org"))

(sort-by second > (frequencies (:body home)))

0 comments on commit 92c9694

Please sign in to comment.