diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b00d6e..f84bcc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Revision history for testcontainer-hs -## 0.4.0.0 -- 2023-02-20 +## 0.5.0.0 -- 2023-02-20 * BREAKING: Refined lifecycle management. testcontainers is now using testcontainers/ryuk resource reaper to cleanup containers, networks and volumes. Release keys for containers are deprecated. (@alexbiehl, https://github.com/testcontainers/testcontainers-hs/pull/33) diff --git a/src/TestContainers/Config.hs b/src/TestContainers/Config.hs index 49580fa..3a0e580 100644 --- a/src/TestContainers/Config.hs +++ b/src/TestContainers/Config.hs @@ -11,7 +11,7 @@ import TestContainers.Monad (Config (..)) -- | Default configuration. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 defaultConfig :: Config defaultConfig = Config diff --git a/src/TestContainers/Docker.hs b/src/TestContainers/Docker.hs index 761bf7f..5fca94c 100644 --- a/src/TestContainers/Docker.hs +++ b/src/TestContainers/Docker.hs @@ -280,7 +280,7 @@ data ContainerRequest = ContainerRequest -- | Parameters for a naming a Docker container. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 data NamingStrategy = RandomName | FixedName Text @@ -319,7 +319,7 @@ setName = setFixedName -- | Set the name of a Docker container. This is equivalent to invoking @docker run@ -- with the @--name@ parameter. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 setFixedName :: Text -> ContainerRequest -> ContainerRequest setFixedName newName req = -- TODO error on empty Text @@ -328,7 +328,7 @@ setFixedName newName req = -- | Set the name randomly given of a Docker container. This is equivalent to omitting -- the @--name@ parameter calling @docker run@. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 setRandomName :: ContainerRequest -> ContainerRequest setRandomName req = -- TODO error on empty Text @@ -337,7 +337,7 @@ setRandomName req = -- | Set the name randomly suffixed of a Docker container. This is equivalent to invoking -- @docker run@ with the @--name@ parameter. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 setSuffixedName :: Text -> ContainerRequest -> ContainerRequest setSuffixedName preffix req = -- TODO error on empty Text @@ -376,7 +376,7 @@ setEnv newEnv req = -- | Set the network the container will connect to. This is equivalent to passing -- @--network network_name@ to @docker run@. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 withNetwork :: Network -> ContainerRequest -> ContainerRequest withNetwork network req = req {network = Just (Left network)} @@ -384,14 +384,14 @@ withNetwork network req = -- | Set the network alias for this container. This is equivalent to passing -- @--network-alias alias@ to @docker run@. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 withNetworkAlias :: Text -> ContainerRequest -> ContainerRequest withNetworkAlias alias req = req {networkAlias = Just alias} -- | Sets labels for a container -- --- @since 0.4.0.0 +-- @since 0.5.0.0 withLabels :: [(Text, Text)] -> ContainerRequest -> ContainerRequest withLabels xs request = request {labels = xs} @@ -406,7 +406,7 @@ setLink newLink req = -- | Forwards container logs to the given 'LogConsumer' once ran. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 withFollowLogs :: LogConsumer -> ContainerRequest -> ContainerRequest withFollowLogs logConsumer request = request {followLogs = Just logConsumer} @@ -434,14 +434,14 @@ data Port = Port defaultProtocol :: Text defaultProtocol = "tcp" --- @since 0.4.0.0 +-- @since 0.5.0.0 instance Show Port where show Port {port, protocol} = show port <> "/" <> unpack protocol -- | A cursed but handy instance supporting literal 'Port's. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 instance Num Port where fromInteger x = Port {port = fromIntegral x, protocol = defaultProtocol} @@ -454,7 +454,7 @@ instance Num Port where -- | A cursed but handy instance supporting literal 'Port's of them -- form @"8080"@, @"8080/udp"@, @"8080/tcp"@. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 instance IsString Port where fromString input = case splitOn "/" (pack input) of [numberish] @@ -586,7 +586,7 @@ run request = do -- | Sets up a Ryuk 'Reaper'. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 createRyukReaper :: TestContainer Reaper createRyukReaper = do ryukContainer <- @@ -768,11 +768,11 @@ data WaitUntilReady -- Next check WaitUntilReady --- | @since 0.4.0.0 +-- | @since 0.5.0.0 instance Semigroup WaitUntilReady where (<>) = WaitMany --- | @since 0.4.0.0 +-- | @since 0.5.0.0 instance Monoid WaitUntilReady where mempty = WaitReady mempty @@ -813,7 +813,7 @@ instance Exception InvalidStateException -- | @waitForState@ waits for a certain state of the container. If the container reaches a terminal -- state 'InvalidStateException' will be thrown. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 waitForState :: (State -> Bool) -> WaitUntilReady waitForState isReady = WaitReady $ \Container {id} -> do let wait = do @@ -841,7 +841,7 @@ waitForState isReady = WaitReady $ \Container {id} -> do -- | @successfulExit@ is supposed to be used in conjunction with 'waitForState'. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 successfulExit :: State -> Bool successfulExit state = stateStatus state == Exited && stateExitCode state == Just 0 @@ -857,7 +857,7 @@ waitUntilTimeout = WaitUntilTimeout -- | Waits for a specific http status code. -- This combinator should always be used with `waitUntilTimeout`. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 waitForHttp :: -- | Port Port -> @@ -1097,7 +1097,7 @@ internalContainerIp Container {id, inspectOutput} = -- | Get the container's network alias. -- Takes the first alias found. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 containerAlias :: Container -> Text containerAlias Container {id, inspectOutput} = case inspectOutput @@ -1120,7 +1120,7 @@ containerAlias Container {id, inspectOutput} = -- | Get the IP address for the container's gateway, i.e. the host. -- Takes the first gateway address found. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 containerGateway :: Container -> Text containerGateway Container {id, inspectOutput} = case inspectOutput @@ -1174,7 +1174,7 @@ containerPort Container {id, inspectOutput} Port {port, protocol} = -- domain and port if the program is running in the same network. Otherwise, -- 'containerAddress' will use the exposed port on the Docker host. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 containerAddress :: Container -> Port -> (Text, Int) containerAddress container Port {port, protocol} = let inDocker = unsafePerformIO isRunningInDocker diff --git a/src/TestContainers/Docker/Internal.hs b/src/TestContainers/Docker/Internal.hs index b88913b..c414920 100644 --- a/src/TestContainers/Docker/Internal.hs +++ b/src/TestContainers/Docker/Internal.hs @@ -42,7 +42,7 @@ import TestContainers.Trace (Trace (..), Tracer, withTrace) -- | Identifies a network within the Docker runtime. Assigned by @docker network create@ -- --- @since 0.4.0.0 +-- @since 0.5.0.0 type NetworkId = Text -- | Identifies a container within the Docker runtime. Assigned by @docker run@. @@ -132,12 +132,12 @@ data Pipe -- | An abstraction for forwarding logs. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 type LogConsumer = Pipe -> ByteString -> IO () -- | A simple 'LogConsumer' that writes log lines to stdout and stderr respectively. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 consoleLogConsumer :: LogConsumer consoleLogConsumer pipe line = do case pipe of @@ -150,7 +150,7 @@ consoleLogConsumer pipe line = do -- | Forwards container logs to a 'LogConsumer'. This is equivalent of calling @docker logs containerId --follow@ -- --- @since 0.4.0.0 +-- @since 0.5.0.0 dockerFollowLogs :: (MonadResource m) => Tracer -> ContainerId -> LogConsumer -> m () dockerFollowLogs tracer containerId logConsumer = do let dockerArgs = diff --git a/src/TestContainers/Docker/Network.hs b/src/TestContainers/Docker/Network.hs index 93be58e..d18663e 100644 --- a/src/TestContainers/Docker/Network.hs +++ b/src/TestContainers/Docker/Network.hs @@ -29,20 +29,20 @@ import Prelude hiding (id) -- | Handle to a Docker network. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 newtype Network = Network { id :: NetworkId } -- | Returns the id of the network. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 networkId :: Network -> NetworkId networkId Network {id} = id -- | Parameters for creating a new Docker network. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 data NetworkRequest = NetworkRequest { ipv6 :: Bool, driver :: Maybe Text, @@ -51,7 +51,7 @@ data NetworkRequest = NetworkRequest -- | Default parameters for creating a new Docker network. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 networkRequest :: NetworkRequest networkRequest = NetworkRequest @@ -62,21 +62,21 @@ networkRequest = -- | Enable IPv6 for the Docker network. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 withIpv6 :: NetworkRequest -> NetworkRequest withIpv6 request = request {ipv6 = True} -- | Driver to manage the Network (default "bridge"). -- --- @since 0.4.0.0 +-- @since 0.5.0.0 withDriver :: Text -> NetworkRequest -> NetworkRequest withDriver driver request = request {driver = Just driver} -- | Creates a new 'Network' from a 'NetworkRequest'. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 createNetwork :: NetworkRequest -> TestContainer Network createNetwork NetworkRequest {..} = do Config {..} <- ask diff --git a/src/TestContainers/Docker/Reaper.hs b/src/TestContainers/Docker/Reaper.hs index 2674164..69abf5d 100644 --- a/src/TestContainers/Docker/Reaper.hs +++ b/src/TestContainers/Docker/Reaper.hs @@ -24,7 +24,7 @@ import qualified System.Random as Random -- | Reaper for safe resource cleanup. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 data Reaper = Reaper { -- | @runReaper label value@ reaps Docker any Docker resource with a matching -- label. @@ -37,33 +37,33 @@ data Reaper = Reaper -- | Additional labels to add to any Docker resource on creation. Adding the -- labels is necessary in order for the 'Reaper' to find resources for cleanup. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 reaperLabels :: Reaper -> [(Text, Text)] reaperLabels Reaper {labels} = labels -- | Ryuk based resource reaper -- --- @since 0.4.0.0 +-- @since 0.5.0.0 newtype Ryuk = Ryuk {ryukSocket :: Socket.Socket} -- | Tag for the ryuk image -- --- @since 0.4.0.0 +-- @since 0.5.0.0 ryukImageTag :: Text ryukImageTag = "docker.io/testcontainers/ryuk:0.3.4" -- | Exposed port for the ryuk reaper. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 ryukPort :: (Num a) => a ryukPort = 8080 -- | Creates a new 'Reaper' from a host and port. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 newRyukReaper :: (MonadResource m) => -- | Host diff --git a/src/TestContainers/Docker/State.hs b/src/TestContainers/Docker/State.hs index 97990bb..a2b911a 100644 --- a/src/TestContainers/Docker/State.hs +++ b/src/TestContainers/Docker/State.hs @@ -27,7 +27,7 @@ import TestContainers.Docker.Internal (InspectOutput) -- | An exception thrown in case the State object is invalid and couldn't be parsed. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 data StateInvalidException = StateInvalidException deriving stock (Eq, Show) @@ -35,7 +35,7 @@ instance Exception StateInvalidException -- | Status of a Docker container. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 data Status = Created | Running @@ -49,12 +49,12 @@ data Status -- | State of a Docker container. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 newtype State = State Value -- | Extract the 'State' of a Docker container from an 'InspectOutput'. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 containerState :: InspectOutput -> State containerState inspectOutput = case inspectOutput ^? Optics.key "State" of @@ -63,7 +63,7 @@ containerState inspectOutput = -- | Returns the 'Status' of container. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 stateStatus :: State -> Status stateStatus (State value) = case value @@ -81,7 +81,7 @@ stateStatus (State value) = -- | Whether a container was killed by the OOM killer. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 stateOOMKilled :: State -> Bool stateOOMKilled (State value) = case value @@ -92,7 +92,7 @@ stateOOMKilled (State value) = -- | -- --- @since 0.4.0.0 +-- @since 0.5.0.0 statePid :: State -> Maybe Int statePid (State value) = case value @@ -103,7 +103,7 @@ statePid (State value) = -- | -- --- @since 0.4.0.0 +-- @since 0.5.0.0 stateExitCode :: State -> Maybe Int stateExitCode (State value) = case value @@ -114,7 +114,7 @@ stateExitCode (State value) = -- | -- --- @since 0.4.0.0 +-- @since 0.5.0.0 stateError :: State -> Maybe Text stateError (State value) = case value @@ -125,7 +125,7 @@ stateError (State value) = -- | -- --- @since 0.4.0.0 +-- @since 0.5.0.0 stateStartedAt :: State -> Maybe Text stateStartedAt (State value) = case value @@ -136,7 +136,7 @@ stateStartedAt (State value) = -- | -- --- @since 0.4.0.0 +-- @since 0.5.0.0 stateFinishedAt :: State -> Maybe Text stateFinishedAt (State value) = case value diff --git a/src/TestContainers/Monad.hs b/src/TestContainers/Monad.hs index 724043d..86eaf11 100644 --- a/src/TestContainers/Monad.hs +++ b/src/TestContainers/Monad.hs @@ -39,7 +39,7 @@ newtype TestContainerEnv = TestContainerEnv -- | The heart and soul of the testcontainers library. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 newtype TestContainer a = TestContainer {unTestContainer :: ReaderT TestContainerEnv (ResourceT IO) a} deriving newtype ( Functor, @@ -78,7 +78,7 @@ instance (Monoid a) => Monoid (TestContainer a) where -- | Run a 'TestContainer' action. Any container spun up during the computation are guaranteed -- to be shutdown and cleaned up once this function returns. -- --- @since 0.4.0.0 +-- @since 0.5.0.0 runTestContainer :: Config -> TestContainer a -> IO a runTestContainer config action = do -- Ensure through caching that there is only ever exactly @@ -106,7 +106,7 @@ runTestContainer config action = do ) ) --- | Docker related functionality is parameterized over this `Monad`. Since 0.4.0.0 this is +-- | Docker related functionality is parameterized over this `Monad`. Since 0.5.0.0 this is -- just a type alias for @m ~ 'TestContainer'@. -- -- @since 0.1.0.0 diff --git a/testcontainers.cabal b/testcontainers.cabal index 2cb4090..01dd6cc 100644 --- a/testcontainers.cabal +++ b/testcontainers.cabal @@ -1,6 +1,6 @@ cabal-version: >=1.10 name: testcontainers -version: 0.4.0.0 +version: 0.5.0.0 synopsis: Docker containers for your integration tests. description: testcontainers is a Haskell library that provides a friendly API to