Added :fn log strategy (#41)

This commit is contained in:
Tim Zöller 2022-03-26 11:54:28 +01:00
parent a53cf9e271
commit c42886ba56
6 changed files with 155 additions and 90 deletions

View file

@ -1,6 +1,13 @@
# 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.6.0] - 2022-03-26
### Changed
- [#55](https://github.com/javahippie/clj-test-containers/issues/55): Upgrade to latest Testcontainers version
### Added
- [#42](https://github.com/javahippie/clj-test-containers/issues/42): Extend wait strategies
## [0.5.0] - 2021-08-18 ## [0.5.0] - 2021-08-18
### Changed ### Changed
- [#49](https://github.com/javahippie/clj-test-containers/issues/49): Updated to latest Testcontainers version - [#49](https://github.com/javahippie/clj-test-containers/issues/49): Updated to latest Testcontainers version

View file

@ -69,15 +69,15 @@ Creates a testcontainers instance from a given Docker label and returns them
#### Config parameters: #### Config parameters:
| Key | Type | Description | | Key | Type | Description |
| ------------- | :------------- | :----- | | ------------- | :------------- |:----------------------------------------------------------------------------------------------------|
| `:image-name` | String, mandatory | The name and label of an image, e.g. `postgres:12.2` | | `:image-name` | String, mandatory | The name and label of an image, e.g. `postgres:12.2` |
| `:exposed-ports` | Vector with ints, mandatory | All ports which should be exposed and mapped to a local port | | `:exposed-ports` | Vector with ints, mandatory | All ports which should be exposed and mapped to a local port |
| `:env-vars` | Map | A map with environment variables | | `:env-vars` | Map | A map with environment variables |
| `:command` | Vector with strings | The start command of the container | | `:command` | Vector with strings | The start command of the container |
| `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network`) | | `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network`) |
| `:network-aliases` | Map | A list of alias names for the container on the network | | `:network-aliases` | Map | A list of alias names for the container on the network |
| `:wait-for` | Map | A map containing the wait strategy to use and the condition to check for | | `:wait-for` | Map | A map containing the [wait strategy](docs/wait-strategies.md) to use and the condition to check for |
| `:log-to` | Map | A map containing the log strategy to use, e.g. {:log-strategy string} | | `:log-to` | Map | A map containing the [log strategy](docs/log-strategies.md) to use, e.g. {:log-strategy string} |
#### Result: #### Result:
@ -124,21 +124,21 @@ Initializes a given Testcontainer, which was e.g. provided by a library
#### Config parameters: #### Config parameters:
| Key | Type | Description | | Key | Type | Description |
| ------------- | :------------- | :----- | | ------------- | :------------- |:----------------------------------------------------------------------------------------------------|
| `:container` | `org.testcontainers.containers.GenericContainer`, mandatory | The name and label of an image, e.g. `postgres:12.2` | | `:container` | `org.testcontainers.containers.GenericContainer`, mandatory | The name and label of an image, e.g. `postgres:12.2` |
| `:exposed-ports` | Vector with ints, mandatory | All ports which should be exposed and mapped to a local port | | `:exposed-ports` | Vector with ints, mandatory | All ports which should be exposed and mapped to a local port |
| `:env-vars` | Map | A map with environment variables | | `:env-vars` | Map | A map with environment variables |
| `:command` | Vector with strings | The start command of the container | | `:command` | Vector with strings | The start command of the container |
| `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network`) | | `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network`) |
| `:network-aliases` | Map | A list of alias names for the container on the network | | `:network-aliases` | Map | A list of alias names for the container on the network |
| `:wait-for` | Map | A map containing the wait strategy to use and the condition to check for | | `:wait-for` | Map | A map containing the [wait strategy](docs/wait-strategies.md) to use and the condition to check for |
| `:log-to` | Map | A map containing the log strategy to use, e.g. {:log-strategy string} | | `:log-to` | Map | A map containing the [log strategy](docs/log-strategies.md) to use, e.g. {:log-strategy string} |
| | | | | | | |
#### Result: #### Result:
| Key | Type | Description | | Key | Type | Description |
| ------------- | :------------- | :----- | | ------------- | :------------- |:------------------------------------------------------------------------------------------|
| `:container` | `org.testcontainers.containers.Container` | The Testcontainers instance, accessible for everything this library doesn't provide (yet) | | `:container` | `org.testcontainers.containers.Container` | The Testcontainers instance, accessible for everything this library doesn't provide (yet) |
| `:exposed-ports` | Vector with ints | Value of the same input parameter | | `:exposed-ports` | Vector with ints | Value of the same input parameter |
| `:env-vars` | Map | Value of the same input parameter | | `:env-vars` | Map | Value of the same input parameter |
@ -185,8 +185,8 @@ Creates a testcontainer from a Dockerfile
| `:command` | Vector with strings | The start command of the container | | `:command` | Vector with strings | The start command of the container |
| `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network`) | | `:network` | Map | A map containing the configuration of a Docker Network (see: `create-network`) |
| `:network-aliases` | Map | A list of alias names for the container on the network | | `:network-aliases` | Map | A list of alias names for the container on the network |
| `:wait-for` | Map | A map containing the wait strategy to use and the condition to check for | | `:wait-for` | Map | A map containing the [wait strategy](docs/wait-strategies.md) to use and the condition to check for |
| `:log-to` | Map | A map containing the log strategy to use, e.g. {:log-strategy string} | | `:log-to` | Map | A map containing the [log strategy](docs/log-strategies.md) to use, e.g. {:log-strategy string} |
| | | | | | | |
#### Result: #### Result:

34
doc/log-strategies.md Normal file
View file

@ -0,0 +1,34 @@
# Log strategies
This library offers two ways to access the logs of the running container: The :string strategy and the :fn strategy.
## String Strategy
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 the `dump-logs` function.
Example:
```clojure
{:log-strategy :string}
```
Then, later in your program, you can access the logs thus:
```clojure
(def container-config (tc/start! container))
(tc/dump-logs container-config)
```
## Function Strategy
The `:fn` strategy accepts an additional parameter `:function` in the configuration 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 way you can pass the container logging on to the logging library of your choice.
Example:
```clojure
{:log-strategy :fn
:function (fn [log-line] (println "From Container: " log-line)}
```

View file

@ -23,7 +23,8 @@
[orchestra "2021.01.01-1"] [orchestra "2021.01.01-1"]
[org.clojure/tools.namespace "1.2.0"] [org.clojure/tools.namespace "1.2.0"]
[org.testcontainers/postgresql "1.16.3"] [org.testcontainers/postgresql "1.16.3"]
[com.fzakaria/slf4j-timbre "0.3.21"]] [com.fzakaria/slf4j-timbre "0.3.21"]
[nrepl "0.9.0"]]
:source-paths ["dev-src"]}} :source-paths ["dev-src"]}}
:target-path "target/%s") :target-path "target/%s")

View file

@ -13,6 +13,8 @@
GenericContainer GenericContainer
Network) Network)
(org.testcontainers.containers.output (org.testcontainers.containers.output
BaseConsumer
OutputFrame
ToStringConsumer) ToStringConsumer)
(org.testcontainers.containers.wait.strategy (org.testcontainers.containers.wait.strategy
Wait) Wait)
@ -278,11 +280,10 @@
:stderr (.getStderr result)})) :stderr (.getStderr result)}))
(defmulti log (defmulti log
"Sets a log strategy on the container as a means of accessing the container "Sets a log strategy on the container as a means of accessing the container logs.
logs. It currently only supports a :string as the strategy to use.
## 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.
@ -297,6 +298,18 @@
```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
The `:fn` strategy accepts an additional parameter `:function` in the configuration
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
way you can pass the container logging on to the logging library of your choice.
Example:
```clojure
{:log-strategy :fn
:function (fn [log-line] (println \"From Container: \" log-line)}
``` ```
" "
:log-strategy) :log-strategy)
@ -309,9 +322,12 @@
(-> (.toUtf8String to-string-consumer) (-> (.toUtf8String to-string-consumer)
(clojure.string/replace #"\n+" "\n")))})) (clojure.string/replace #"\n+" "\n")))}))
(defmethod log :slf4j [_ _] nil) ; Not yet implemented (defmethod log :fn [{:keys [function]} ^GenericContainer container]
(.followOutput container (proxy [BaseConsumer] []
(^void accept [^OutputFrame frame]
(function (.getUtf8String frame))))))
(defmethod log :default [_ _] nil) ; Not yet implemented (defmethod log :default [_ _] nil)
(defn dump-logs (defn dump-logs
"Dumps the logs found by invoking the function on the :string-log key" "Dumps the logs found by invoking the function on the :string-log key"

View file

@ -20,13 +20,20 @@
(is (nil? (:id stopped-container))) (is (nil? (:id stopped-container)))
(is (nil? (:mapped-ports stopped-container))))) (is (nil? (:mapped-ports stopped-container)))))
(testing "Testing log access to the container" (testing "Testing log access to the container with string logs"
(let [container (sut/init {:container (PostgreSQLContainer. "postgres:12.2") (let [container (sut/init {:container (PostgreSQLContainer. "postgres:12.2")
:log-to {:log-strategy :string}}) :log-to {:log-strategy :string}})
initialized-container (sut/start! container)] initialized-container (sut/start! container)]
(Thread/sleep 500) (Thread/sleep 500)
(is (includes? (sut/dump-logs initialized-container) "database system is ready to accept connections")))) (is (includes? (sut/dump-logs initialized-container) "database system is ready to accept connections"))))
(testing "Testing log access to the container with function logs"
(let [logs (atom [])]
(sut/start! (sut/init {:container (PostgreSQLContainer. "postgres:12.2")
:log-to {:log-strategy :fn
:function #(swap! logs conj %)}}))
(is (filter #(includes? "database system is ready to accept connections" %) @logs))))
(testing "Testing basic testcontainer generic image initialisation with wait for log message" (testing "Testing basic testcontainer generic image initialisation with wait for log message"
(let [container (sut/create {:image-name "postgres:12.2" (let [container (sut/create {:image-name "postgres:12.2"
:exposed-ports [5432] :exposed-ports [5432]