Refactored cleanup to not use deprecated methods anymore (#66)

This commit is contained in:
Tim Zöller 2022-11-16 22:46:41 +01:00
parent 94e582a1aa
commit 667a2d0850
2 changed files with 139 additions and 119 deletions

View file

@ -1,9 +1,11 @@
# Change Log # Change Log
All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/).
## [0.7.4] - 22-11-16 ## [0.7.4] - 2022-11-16
### Changed ### Changed
- [#64](https://github.com/javahippie/clj-test-containers/pull/64): Fix container path parameter for copy-file-to-container! in README
- [#65](https://github.com/javahippie/clj-test-containers/issues/65): Upgrade to testcontainers-java 1.17.6 - [#65](https://github.com/javahippie/clj-test-containers/issues/65): Upgrade to testcontainers-java 1.17.6
- [#66](https://github.com/javahippie/clj-test-containers/issues/66): Remove usage of deprecated API calls for cleanup
## [0.7.3] - 2202-09-30 ## [0.7.3] - 2202-09-30
### Changed ### Changed

View file

@ -1,28 +1,28 @@
(ns clj-test-containers.core (ns clj-test-containers.core
(:require (:require
[clj-test-containers.spec.core :as cs] [clj-test-containers.spec.core :as cs]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[clojure.string]) [clojure.string])
(:import (:import
(java.nio.file (java.nio.file
Paths) Paths)
(java.time (java.time
Duration) Duration)
(org.testcontainers.containers (org.testcontainers DockerClientFactory)
BindMode (org.testcontainers.containers
GenericContainer BindMode
Network) GenericContainer
(org.testcontainers.containers.output Network)
BaseConsumer (org.testcontainers.containers.output
OutputFrame BaseConsumer
ToStringConsumer) OutputFrame
(org.testcontainers.containers.wait.strategy ToStringConsumer)
Wait) (org.testcontainers.containers.wait.strategy
(org.testcontainers.images.builder Wait)
ImageFromDockerfile) (org.testcontainers.images.builder
(org.testcontainers.utility ImageFromDockerfile)
MountableFile (org.testcontainers.utility
ResourceReaper))) MountableFile)))
(defn- resolve-bind-mode (defn- resolve-bind-mode
(^BindMode [bind-mode] (^BindMode [bind-mode]
@ -30,71 +30,69 @@
BindMode/READ_WRITE BindMode/READ_WRITE
BindMode/READ_ONLY))) BindMode/READ_ONLY)))
(defn- reaper-instance (defonce started-instances (atom #{}))
[]
(ResourceReaper/instance))
(defmulti wait (defmulti wait
"Sets a wait strategy to the container. Supports :http, :health and :log as "Sets a wait strategy to the container. Supports :http, :health and :log as
strategies. strategies.
## HTTP Strategy ## HTTP Strategy
The :http strategy will only accept the container as initialized if it can be The :http strategy will only accept the container as initialized if it can be
accessed via HTTP. It accepts a path, a port, a vector of status codes, a accessed via HTTP. It accepts a path, a port, a vector of status codes, a
boolean that specifies if TLS is enabled, a read timeout in seconds and a map boolean that specifies if TLS is enabled, a read timeout in seconds and a map
with basic credentials, containing username and password. Only the path is with basic credentials, containing username and password. Only the path is
required, all others are optional. required, all others are optional.
Example: Example:
```clojure ```clojure
(wait {:wait-strategy :http (wait {:wait-strategy :http
:port 80 :port 80
:path \"/\" :path \"/\"
:status-codes [200 201] :status-codes [200 201]
:tls true :tls true
:read-timeout 5 :read-timeout 5
:basic-credentials {:username \"user\" :basic-credentials {:username \"user\"
:password \"password\" :password \"password\"
:startup-timeout 60}} :startup-timeout 60}}
container) container)
``` ```
## Health Strategy ## Health Strategy
The :health strategy enables support for Docker's healthcheck feature, The :health strategy enables support for Docker's healthcheck feature,
whereby you can directly leverage the healthy state of your container as your wait condition. whereby you can directly leverage the healthy state of your container as your wait condition.
Example: Example:
```clojure ```clojure
(wait {:wait-strategy :health (wait {:wait-strategy :health
:startup-timeout 60} container) :startup-timeout 60} container)
``` ```
## Log Strategy ## Log Strategy
The :log strategy accepts a message which simply causes the output of your The :log strategy accepts a message which simply causes the output of your
container's log to be used in determining if the container is ready or not. container's log to be used in determining if the container is ready or not.
The output is `grepped` against the log message. The output is `grepped` against the log message.
Example: Example:
```clojure ```clojure
(wait {:wait-strategy :log (wait {:wait-strategy :log
:message \"accept connections\" :message \"accept connections\"
:startup-timeout 60} container) :startup-timeout 60} container)
``` ```
## Port Strategy ## Port Strategy
The port strategy waits for the first of the mapped ports to be opened. It only accepts the startup-timeout The port strategy waits for the first of the mapped ports to be opened. It only accepts the startup-timeout
value as a parameter. value as a parameter.
Example: Example:
```clojure ```clojure
(wait {:wait-strategy :port (wait {:wait-strategy :port
:startup-timeout 60} container :startup-timeout 60} container
```" ```"
:wait-strategy) :wait-strategy)
(defmethod wait :http (defmethod wait :http
[{:keys [path [{:keys [path
@ -237,11 +235,11 @@
[{:keys [^GenericContainer container] :as container-config} [{:keys [^GenericContainer container] :as container-config}
{:keys [^String resource-path ^String container-path mode]}] {:keys [^String resource-path ^String container-path mode]}]
(assoc container-config (assoc container-config
:container :container
(.withClasspathResourceMapping container (.withClasspathResourceMapping container
resource-path resource-path
container-path container-path
(resolve-bind-mode mode)))) (resolve-bind-mode mode))))
(defn bind-filesystem! (defn bind-filesystem!
"Binds a source from the filesystem to the given container path. Should be "Binds a source from the filesystem to the given container path. Should be
@ -249,11 +247,11 @@
[{:keys [^GenericContainer container] :as container-config} [{:keys [^GenericContainer container] :as container-config}
{:keys [^String host-path ^String container-path mode]}] {:keys [^String host-path ^String container-path mode]}]
(assoc container-config (assoc container-config
:container :container
(.withFileSystemBind container (.withFileSystemBind container
host-path host-path
container-path container-path
(resolve-bind-mode mode)))) (resolve-bind-mode mode))))
(defn copy-file-to-container! (defn copy-file-to-container!
"If a container is not yet started, adds a mapping from mountable file to "If a container is not yet started, adds a mapping from mountable file to
@ -270,10 +268,10 @@
(.copyFileToContainer container mountable-file container-path) (.copyFileToContainer container mountable-file container-path)
container-config) container-config)
(assoc container-config (assoc container-config
:container :container
(.withCopyFileToContainer container (.withCopyFileToContainer container
mountable-file mountable-file
container-path))))) container-path)))))
(defn execute-command! (defn execute-command!
"Executes a command in the container, and returns the result" "Executes a command in the container, and returns the result"
@ -284,39 +282,39 @@
:stderr (.getStderr result)})) :stderr (.getStderr result)}))
(defmulti log (defmulti log
"Sets a log strategy on the container as a means of accessing the container logs. "Sets a log strategy on the container as a means of accessing the container logs.
## String Strategy ## String Strategy
The `:string` strategy sets up a function in the returned map, under the The `:string` strategy sets up a function in the returned map, under the
`string-log` key. This function enables the dumping of the logs when passed to `string-log` key. This function enables the dumping of the logs when passed to
the `dump-logs` function. the `dump-logs` function.
Example: Example:
```clojure ```clojure
{:log-strategy :string} {:log-strategy :string}
``` ```
Then, later in your program, you can access the logs thus: Then, later in your program, you can access the logs thus:
```clojure ```clojure
(def container-config (tc/start! container)) (def container-config (tc/start! container))
(tc/dump-logs container-config) (tc/dump-logs container-config)
``` ```
## Function Strategy ## Function Strategy
The `:fn` strategy accepts an additional parameter `:function` in the configuration The `:fn` strategy accepts an additional parameter `:function` in the configuration
map, which allows you to pass a function to the Testcontainers log mechanism map, which allows you to pass a function to the Testcontainers log mechanism
which accepts a single String parameter and gets called for every log line. This which accepts a single String parameter and gets called for every log line. This
way you can pass the container logging on to the logging library of your choice. way you can pass the container logging on to the logging library of your choice.
Example: Example:
```clojure ```clojure
{:log-strategy :fn {:log-strategy :fn
:function (fn [log-line] (println \"From Container: \" log-line)} :function (fn [log-line] (println \"From Container: \" log-line)}
``` ```
" "
:log-strategy) :log-strategy)
(defmethod log :string (defmethod log :string
[_ ^GenericContainer container] [_ ^GenericContainer container]
@ -352,9 +350,7 @@
container-id ^String (.getContainerId container) container-id ^String (.getContainerId container)
image-name ^String (.getDockerImageName container) image-name ^String (.getDockerImageName container)
logger (log log-to container)] logger (log log-to container)]
(.registerContainerForCleanup ^ResourceReaper (reaper-instance) (swap! started-instances conj {:type :container :id container-id})
container-id
image-name)
(-> container-config (-> container-config
(merge {:id container-id (merge {:id container-id
:mapped-ports mapped-ports :mapped-ports mapped-ports
@ -388,7 +384,7 @@
(let [network (.build builder) (let [network (.build builder)
network-name (.getName network)] network-name (.getName network)]
(.registerNetworkIdForCleanup ^ResourceReaper (reaper-instance) network-name) (swap! started-instances conj {:type :network :id :network-name})
{:network network {:network network
:name network-name :name network-name
:ipv6 (.getEnableIpv6 network) :ipv6 (.getEnableIpv6 network)
@ -396,10 +392,32 @@
(def ^:deprecated init-network create-network) (def ^:deprecated init-network create-network)
(defn- remove-network! [instance]
(-> (DockerClientFactory/instance)
(.client)
(.removeNetworkCmd (:id instance))
(.exec))
instance)
(defn- stop-and-remove-container! [instance]
(let [docker-client (DockerClientFactory/instance)]
(-> docker-client
(.client)
(.stopContainerCmd (:id instance))
(.exec))
(-> docker-client
(.client)
(.removeContainerCmd (:id instance))
(.exec)))
instance)
(defn perform-cleanup! (defn perform-cleanup!
"Stops and removes all container instances which were created in the active JVM or REPL session" "Stops and removes all container instances which were created in the active JVM or REPL session"
[] []
(.performCleanup ^ResourceReaper (reaper-instance))) (for [instance @started-instances]
(swap! started-instances disj (case (:type instance)
:container (stop-and-remove-container! instance)
:network (remove-network! instance)))))
;; REPL Helpers ;; REPL Helpers