Refactored cleanup to not use deprecated methods anymore (#66)
This commit is contained in:
parent
94e582a1aa
commit
667a2d0850
2 changed files with 139 additions and 119 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue