diff --git a/resources/config/dnsmasq-external.conf b/resources/network-module/config/dnsmasq-external.conf similarity index 100% rename from resources/config/dnsmasq-external.conf rename to resources/network-module/config/dnsmasq-external.conf diff --git a/resources/config/dnsmasq-internal.conf b/resources/network-module/config/dnsmasq-internal.conf similarity index 100% rename from resources/config/dnsmasq-internal.conf rename to resources/network-module/config/dnsmasq-internal.conf diff --git a/resources/images/Dockerfile.dnsmasq-external b/resources/network-module/images/Dockerfile.dnsmasq-external similarity index 100% rename from resources/images/Dockerfile.dnsmasq-external rename to resources/network-module/images/Dockerfile.dnsmasq-external diff --git a/resources/images/Dockerfile.dnsmasq-internal b/resources/network-module/images/Dockerfile.dnsmasq-internal similarity index 100% rename from resources/images/Dockerfile.dnsmasq-internal rename to resources/network-module/images/Dockerfile.dnsmasq-internal diff --git a/resources/network-module/module.edn b/resources/network-module/module.edn new file mode 100644 index 0000000..f8b3742 --- /dev/null +++ b/resources/network-module/module.edn @@ -0,0 +1,54 @@ +{:include ["config/dnsmasq-external.conf" + "config/dnsmasq-internal.conf" + + "images/Dockerfile.dnsmasq-external" + "images/Dockerfile.dnsmasq-internal"] + + :network {:services {:kl-proxy {:endpoints {:container {:url "http://proxy:8080"}} + :default-endpoint :container}} + + :routes {:kl-proxy {:host "proxy.test" + :service :kl-proxy}}} + + :networks {:kl {:name "kl" + :ipam {:driver "default" + :config [{:subnet "172.5.0.0/24"}]}}} + + :containers + {:dnsmasq-external + {:build {:context "{{DIR}}" + :dockerfile "{{DIR}}/images/Dockerfile.dnsmasq-external"} + :platform "linux/amd64" + :restart "unless-stopped" + :command ["--conf-file=/dnsmasq-config/dnsmasq.conf" + "--except-interface=lo" + "--bind-interfaces" + "--log-queries" + "--log-facility=-"] + :ports ["53:53/udp" + "53:53/tcp"] + :cap_add ["NET_ADMIN"]} + + :dnsmasq-internal + {:build {:context "." + :dockerfile "{{DIR}}/images/Dockerfile.dnsmasq-internal"} + :platform "linux/amd64" + :restart "unless-stopped" + :command ["--conf-file=/dnsmasq-config/dnsmasq.conf" + "--except-interface=lo" + "--bind-interfaces" + "--log-queries" + "--log-facility=-"] + :networks {:kl {:ipv4_address "172.5.0.100"}} + :cap_add ["NET_ADMIN"]} + + :proxy + {:image "traefik:v2.6" + :restart "unless-stopped" + :networks {:kl {:ipv4_address "172.5.0.101"}} + :command ["--api.insecure=true" + "--providers.file.directory=/proxy-config" + "--providers.file.watch=true"] + :ports ["80:80" + "1001:8080"] + :volumes ["~/.config/kl/proxy:/proxy-config"]}}} diff --git a/resources/network.yml b/resources/network.yml deleted file mode 100644 index ceebe4a..0000000 --- a/resources/network.yml +++ /dev/null @@ -1,62 +0,0 @@ -networks: - kl: - name: kl - ipam: - driver: default - config: - - subnet: 172.5.0.0/24 - -services: - dnsmasq-external: - build: - context: . - dockerfile: ./images/Dockerfile.dnsmasq-external - restart: unless-stopped - command: - - --conf-file=/dnsmasq-config/dnsmasq.conf - - --except-interface=lo - - --bind-interfaces - - --log-queries - - --log-facility=- - ports: - - '53:53/udp' - - '53:53/tcp' - cap_add: - - NET_ADMIN - - dnsmasq-internal: - build: - context: . - dockerfile: ./images/Dockerfile.dnsmasq-internal - restart: unless-stopped - command: - - --conf-file=/dnsmasq-config/dnsmasq.conf - - --except-interface=lo - - --bind-interfaces - - --log-queries - - --log-facility=- - networks: - kl: - ipv4_address: 172.5.0.100 - cap_add: - - NET_ADMIN - - proxy: - image: traefik:v2.6 - restart: unless-stopped - networks: - kl: - ipv4_address: 172.5.0.101 - command: - - --api.insecure=true - - --providers.docker - - --providers.docker.network=kl - - --providers.file.directory=/proxy-config - - --providers.file.watch=true - ports: ['80:80', '1001:8080'] - labels: - - traefik.http.routers.proxy.rule=Host(`proxy.test`) - - traefik.http.services.proxy.loadbalancer.server.port=8080 - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ~/.config/kl/proxy:/proxy-config diff --git a/src/k16/kl/api/executor.clj b/src/k16/kl/api/executor.clj index 045c538..4fb0f89 100644 --- a/src/k16/kl/api/executor.clj +++ b/src/k16/kl/api/executor.clj @@ -2,6 +2,7 @@ (:require [babashka.process :as proc] [clj-yaml.core :as yaml] + [clojure.java.io :as io] [k16.kl.api.fs :as api.fs] [meta-merge.core :as metamerge])) @@ -9,7 +10,8 @@ (defn- build-docker-compose [module] (let [base (cond-> {:networks {:kl {:external true}}} - (:volumes module) (assoc :volumes (:volumes module))) + (:volumes module) (assoc :volumes (:volumes module)) + (:networks module) (assoc :networks (:networks module))) containers (->> (:containers module) @@ -26,9 +28,9 @@ (cond-> base (seq containers) (assoc :services containers)))) -(defn- exec-configuration! [{:keys [module-name module direction]}] +(defn run-module-containers! [{:keys [module direction project-name workdir]}] (let [compose-data (build-docker-compose module) - compose-file (api.fs/from-module-work-dir module-name "docker-compose.yaml") + compose-file (io/file workdir "docker-compose.yaml") direction (if (:services compose-data) direction :down) @@ -36,18 +38,19 @@ :up ["-f" (.toString compose-file) "up" "-d" "--remove-orphans"] :down ["down"])] + (io/make-parents compose-file) (spit compose-file (yaml/generate-string compose-data)) (try (proc/shell (concat ["docker" "compose" - "--project-name" (str "kl-" module-name)] + "--project-name" project-name] args)) (catch Exception _)))) -(defn start-configuration! [props] - (exec-configuration! (assoc props :direction :up))) - -(defn stop-configuration! [props] - (exec-configuration! (assoc props :direction :down))) +(defn run-module! [{:keys [module-name module direction]}] + (run-module-containers! {:module module + :direction direction + :project-name (str "kl-" module-name) + :workdir (api.fs/from-module-work-dir module-name)})) diff --git a/src/k16/kl/commands/containers.clj b/src/k16/kl/commands/containers.clj index f9b6fe5..a813047 100644 --- a/src/k16/kl/commands/containers.clj +++ b/src/k16/kl/commands/containers.clj @@ -75,8 +75,9 @@ (let [module (metamerge/meta-merge module updated-state)] (api.proxy/write-proxy-config! {:module-name module-name :module module}) - (api.executor/start-configuration! {:module-name module-name - :module module}))))}) + (api.executor/run-module! {:module-name module-name + :module module + :direction :up}))))}) (def ^:private stop-cmd {:command "down" @@ -90,8 +91,9 @@ (let [module-name (prompt.config/get-module-name props) {:keys [modules]} (api.resolver/pull! module-name {}) module (api.module/get-resolved-module module-name modules)] - (api.executor/stop-configuration! {:module-name module-name - :module module})))}) + (api.executor/run-module! {:module-name module-name + :module module + :direction :down})))}) (def cmd {:command "containers" diff --git a/src/k16/kl/commands/network.clj b/src/k16/kl/commands/network.clj index 3270874..ec0d6a4 100644 --- a/src/k16/kl/commands/network.clj +++ b/src/k16/kl/commands/network.clj @@ -1,50 +1,62 @@ (ns k16.kl.commands.network (:require - [babashka.process :as proc] - [clojure.java.io :as io])) + [clojure.edn :as edn] + [clojure.java.io :as io] + [clojure.string :as str] + [k16.kl.api.executor :as api.executor] + [k16.kl.api.fs :as api.fs] + [k16.kl.api.proxy :as api.proxy])) (defn- gen-hash [n] (->> (repeatedly n #(rand-int 256)) (map #(format "%02x" %)) (apply str))) +(defn- get-tmp-dir [] + (io/file (System/getProperty "java.io.tmpdir") (str "kl-network-" (gen-hash 5)))) + (defn- rm-dir [^java.io.File file] (when (.isDirectory file) (run! rm-dir (.listFiles file))) (io/delete-file file)) -(defn- prepare-config [] - (let [dir (io/file (System/getProperty "java.io.tmpdir") (str "kl-network" (gen-hash 5))) - files ["config/dnsmasq-internal.conf" "config/dnsmasq-external.conf" - "images/Dockerfile.dnsmasq-external" "images/Dockerfile.dnsmasq-internal" - "network.yml"]] +(defn- write-network-module [] + (let [prefix ".kl/network" + module-file (io/resource "network-module/module.edn") + module-raw (-> module-file + slurp + (str/replace "{{DIR}}" (.toString (api.fs/from-config-dir prefix)))) + module (edn/read-string module-raw)] - (->> files - (map (fn [file] - (let [source (io/resource file) - sink (io/file dir file)] - (io/make-parents sink) - (spit sink (slurp source))))) - dorun) + (spit (api.fs/from-config-dir prefix "module.edn") module-raw) - dir)) + (doseq [file (:include module)] + (let [contents (slurp (io/resource (str "network-module/" file)))] + (spit (api.fs/from-config-dir prefix file) contents))) -(defn- start-network! [_] - (let [dir (prepare-config)] - (proc/shell ["docker" "compose" - "-p" "kl" - "-f" (.toString (io/file dir "network.yml")) - "up" "-d" "--remove-orphans"]) + module)) - (rm-dir dir))) +(defn- start-network! [_] + (let [workdir (get-tmp-dir) + module (write-network-module)] + (api.proxy/write-proxy-config! {:module-name "kl" + :module module}) + (api.executor/run-module-containers! {:module module + :direction :up + :project-name "kl" + :workdir workdir}) + (rm-dir workdir))) (defn- stop-network! [_] - (let [dir (prepare-config)] - (proc/shell ["docker" "compose" - "-p" "kl" - "-f" (.toString (io/file dir "network.yml")) - "stop"]) - (rm-dir dir))) + (let [workdir (get-tmp-dir) + module (write-network-module)] + (api.proxy/write-proxy-config! {:module-name "kl" + :module {}}) + (api.executor/run-module-containers! {:module module + :direction :down + :project-name "kl" + :workdir workdir}) + (rm-dir workdir))) (def cmd {:command "network"