From bd1390bfc2f49d97cd3802f1887df39ce560990d Mon Sep 17 00:00:00 2001 From: Juerg Lang Date: Sat, 16 Sep 2023 21:04:11 +0200 Subject: [PATCH] enhanced docker module with some utility functions --- .../modules/ModuleDockerSection.java | 4 +- .../venice/impl/functions/TimeFunctions.java | 30 ++++-- .../com/github/jlangch/venice/docker.venice | 97 ++++++++++++++++--- 3 files changed, 111 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/github/jlangch/venice/impl/docgen/cheatsheet/modules/ModuleDockerSection.java b/src/main/java/com/github/jlangch/venice/impl/docgen/cheatsheet/modules/ModuleDockerSection.java index 98ec95f7c..a17a62427 100644 --- a/src/main/java/com/github/jlangch/venice/impl/docgen/cheatsheet/modules/ModuleDockerSection.java +++ b/src/main/java/com/github/jlangch/venice/impl/docgen/cheatsheet/modules/ModuleDockerSection.java @@ -78,13 +78,15 @@ public DocSection section() { final DocSection utils = new DocSection("Utils", id()); all.addSection(utils); + utils.addItem(diBuilder.getDocItem("docker/images-query-by-repo", false)); utils.addItem(diBuilder.getDocItem("docker/container-find-by-name", false)); utils.addItem(diBuilder.getDocItem("docker/container-exists-with-name?", false)); utils.addItem(diBuilder.getDocItem("docker/container-running-with-name?", false)); utils.addItem(diBuilder.getDocItem("docker/container-start-by-name", false)); utils.addItem(diBuilder.getDocItem("docker/container-stop-by-name", false)); - utils.addItem(diBuilder.getDocItem("docker/container-exec-by-name", false)); utils.addItem(diBuilder.getDocItem("docker/container-status-by-name", false)); + utils.addItem(diBuilder.getDocItem("docker/container-exec-by-name", false)); + utils.addItem(diBuilder.getDocItem("docker/container-has-log-msg", false)); return section; } diff --git a/src/main/java/com/github/jlangch/venice/impl/functions/TimeFunctions.java b/src/main/java/com/github/jlangch/venice/impl/functions/TimeFunctions.java index 2613d1376..b566c131a 100644 --- a/src/main/java/com/github/jlangch/venice/impl/functions/TimeFunctions.java +++ b/src/main/java/com/github/jlangch/venice/impl/functions/TimeFunctions.java @@ -872,12 +872,21 @@ else if (date1 instanceof LocalDate && date2 instanceof LocalDate) { "time/plus", VncFunction .meta() - .arglists("(time/plus date unit n)") - .doc("Adds the n units to the date. Units: {:years :months :weeks :days :hours :minutes :seconds :milliseconds}") + .arglists( + "(time/plus date unit n)", + "(time/minus plus temporal)") + .doc( + "Adds the n units to the date. Units: {:years :months :weeks " + + ":days :hours :minutes :seconds :milliseconds}\n\n" + + "In the two argument version add a :java.time.Temporal (Period, Duration) " + + "to the date.") .examples( "(time/plus (time/local-date) :days 2)", "(time/plus (time/local-date-time) :days 2)", - "(time/plus (time/zoned-date-time) :days 2)") + "(time/plus (time/zoned-date-time) :days 2)", + "(time/plus (time/local-date) (. :java.time.Period :ofDays 2))", + "(time/plus (time/local-date-time) (. :java.time.Period :ofDays 2))", + "(time/plus (time/zoned-date-time) (. :java.time.Period :ofDays 2))") .seeAlso( "time/minus") .build() @@ -914,12 +923,21 @@ public VncVal apply(final VncList args) { "time/minus", VncFunction .meta() - .arglists("(time/minus date unit n)") - .doc("Subtracts the n units from the date. Units: {:years :months :weeks :days :hours :minutes :seconds :milliseconds}") + .arglists( + "(time/minus date unit n)", + "(time/minus date temporal)") + .doc( + "Subtracts the n units from the date. Units: {:years :months :weeks " + + ":days :hours :minutes :seconds :milliseconds}\n\n" + + "In the two argument version subtracts a :java.time.Temporal (Period, Duration) " + + "from the date.") .examples( "(time/minus (time/local-date) :days 2)", "(time/minus (time/local-date-time) :days 2)", - "(time/minus (time/zoned-date-time) :days 2)") + "(time/minus (time/zoned-date-time) :days 2)", + "(time/minus (time/local-date) (. :java.time.Period :ofDays 2))", + "(time/minus (time/local-date-time) (. :java.time.Period :ofDays 2))", + "(time/minus (time/zoned-date-time) (. :java.time.Period :ofDays 2))") .seeAlso( "time/plus") .build() diff --git a/src/main/resources/com/github/jlangch/venice/docker.venice b/src/main/resources/com/github/jlangch/venice/docker.venice index ef0a72d2d..5e8752f3a 100644 --- a/src/main/resources/com/github/jlangch/venice/docker.venice +++ b/src/main/resources/com/github/jlangch/venice/docker.venice @@ -331,7 +331,8 @@ Options: | :detach {true, false} | Run container in background and return container ID | - | :publish port | Publish a container's port(s) to the host | + | :attach {stdin, stdout, stderr} | Attach to STDIN, STDOUT or STDERR | + | :publish port | Publish a container's port to the host. To expose port 8080 inside the container to port 3000 outside the container, pass "3000:8080" | | :envs vars | Set environment variable (a sequence of env var defs) | | :memory limit | Memory limit | | :name name | Assign a name to the container | @@ -355,18 +356,19 @@ """, """ ;; Run an ArangoDB container (use docker volume, faster than bind mount) - (docker/volume-create "arangodb-db") - (docker/volume-create "arangodb-apps") - (docker/run "arangodb/arangodb:3.10.10" - :name "myapp" - :publish "8529:8529" - :detach true - :envs ["ARANGO_ROOT_PASSWORD=xxxxxx" - "ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY=8G" - "ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES=1"] - :volumes ["arangodb-db:/var/lib/arangodb3" - "arangodb-apps:/var/lib/arangodb3-apps"] - :args ["--database.auto-upgrade"]) + (do + (docker/volume-create "arangodb-db") + (docker/volume-create "arangodb-apps") + (docker/run "arangodb/arangodb:3.10.10" + :name "myapp" + :publish "8529:8529" + :detach true + :envs ["ARANGO_ROOT_PASSWORD=xxxxxx" + "ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY=8G" + "ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES=1"] + :volumes ["arangodb-db:/var/lib/arangodb3" + "arangodb-apps:/var/lib/arangodb3-apps"] + :args ["--database.auto-upgrade"])) """ ) :see-also '( "docker/images" "docker/ps" @@ -383,6 +385,7 @@ "docker/container-status-by-name" "docker/container-exec-by-name" ) :spec { :options { :detach [:optional #{true, false}] + :attach [:optional #{:stdin, :stdout, :stderr}] :publish [:optional #(and (long? %) (pos? %))] :envs [:optional #(and (vector? %) (every? string? %))] :memory [:optional #(string? %)] @@ -399,6 +402,7 @@ (let [opts (apply hash-map options) _ (validate-map "option" opts (-> docker/run meta :spec :options)) detach (:detach opts false) + attach (:attach opts nil) publish (:publish opts nil) envs (:envs opts []) memory (:memory opts 0) @@ -409,6 +413,7 @@ args (:args opts []) cmdargs* ["run"] cmdargs* (if detach (conj cmdargs* "--detach") cmdargs*) + cmdargs* (if attach (conj cmdargs* "--attach" (name attach)) cmdargs*) cmdargs* (if quiet (conj cmdargs* "--quiet") cmdargs*) cmdargs* (if (some? publish) (conj cmdargs* "--publish" publish) cmdargs*) cmdargs* (if (pos? memory) (conj cmdargs* "--memory" memory) cmdargs*) @@ -1009,6 +1014,8 @@ ;; ----------------------------------------------------------------------------- ;; Utility functions +;; - docker/images-query-by-repo +;; - docker/container-find-by-name ;; - docker/container-find-by-name ;; - docker/container-exists-with-name? ;; - docker/container-running-with-name? @@ -1016,8 +1023,35 @@ ;; - docker/container-stop-by-name ;; - docker/container-status-by-name ;; - docker/container-exec-by-name +;; - docker/container-has-log-msg ;; ----------------------------------------------------------------------------- + +(defn + ^{ :arglists '("(docker/images-query-by-repo repo)") + :doc """ + Returns all pulled images for a given repo. + """ + :examples '( + """ + (docker/images-query-by-repo "arangodb/arangodb") + """, + """ + ;; return a list of ids for "arangodb/arangodb" images + (->> (query-images-by-repo "arangodb/arangodb") + (map #(get % "ID"))) + """ ) + :see-also '( + "docker/images" ) } + + images-query-by-repo [repo] + + { :pre [(string? name)] } + + (->> (docker/images :format :json) + (filter #(== repor (get % "Repository"))))) + + (defn ^{ :arglists '("(docker/container-find-by-name name)") :doc """ @@ -1043,6 +1077,7 @@ (->> (docker/ps :all true :format :json) (filter #(== name (get % "Names"))))) + (defn ^{ :arglists '("(docker/container-exists-with-name? name)") :doc """ @@ -1229,6 +1264,42 @@ (exec c command))) +(defn + ^{ :arglists '( + "(docker/container-has-log-msg id msg)" + "(docker/container-has-log-msg id msg since)") + :doc """ + Returns true if the container logs has message that matches the + regex 'msg' and is newer than the optional 'since' timestamp. + """ + :examples '( + """ + (docker/container-has-log-msg "0c08e164e6cf" + #".*is ready for business. Have fun.*" + (time/minus (time/local-date-time) :minutes 2)) + """ ) + :see-also '( + "docker/run" + "docker/container-exists-with-name?" + "docker/container-running-with-name?" + "docker/container-start-by-name" + "docker/container-stop-by-name" + "docker/container-status-by-name" + "docker/container-exec-by-name" ) } + + container-has-log-msg + + ([id msg] + (container-has-log-msg id msg nil)) + + ([id msg since] + (->> (if (nil? since) (docker/logs id) (docker/logs id :since since)) + (str/split-lines) + (filter #(match? % msg)) + (count) + (pos?)))) + + ;; ----------------------------------------------------------------------------- ;; Private helpers