@@ -12,7 +12,8 @@ import Control.Lens ((^.), (^?))
12import Control.Monad.IO.Class
12import Control.Monad.IO.Class
13import Control.Monad.Trans.Class (lift)
13import Control.Monad.Trans.Class (lift)
14import qualified Data.Aeson as JSON
14import qualified Data.Aeson as JSON
15−import Data.Aeson.Lens (key, _Object, _String, _Value)
15+import Data.Aeson.Lens (key, _Array, _Null, _Object,
16import qualified Data.ByteString as B
17import qualified Data.ByteString as B
17import qualified Data.ByteString.Char8 as C
18import qualified Data.ByteString.Char8 as C
18import qualified Data.ByteString.Lazy as BL
19import qualified Data.ByteString.Lazy as BL
@@ -22,6 +23,7 @@ import qualified Data.Map as M
22import Data.Maybe (fromJust, isJust)
23import Data.Maybe (fromJust, isJust)
23import Data.Monoid
24import Data.Monoid
24import Data.Text (Text, unpack)
25import Data.Text (Text, unpack)
26+import qualified Data.Vector as V
25import Network.Connection (TLSSettings (..))
27import Network.Connection (TLSSettings (..))
26import Network.HTTP.Client (newManager)
28import Network.HTTP.Client (newManager)
27import Network.HTTP.Client.TLS
29import Network.HTTP.Client.TLS
@@ -31,113 +33,158 @@ import System.Process (system)
31import Docker.Client
33import Docker.Client
33-- opts = defaultClientOpts
35-- opts = defaultClientOpts
35testImageName = "docker-hs-test"
36testImageName = "docker-hs-test"
37toStrict1 = B.concat . BL.toChunks
38toStrict1 = B.concat . BL.toChunks
39−runDocker f = do
40+runDocker f
40− -- let opts = defaultClientOpts {baseUrl = "https://127.0.0.1:2376/"}
41+ -- let opts = defaultClientOpts {baseUrl = "https://127.0.0.1:2376/"}
41− -- params' <- clientParamsWithClientAuthentication "127.0.0.1" 2376 "~/.docker/test-client-key.pem" "~/.docker/test-client-cert.pem" >>= fromRight
42+ -- params' <- clientParamsWithClientAuthentication "127.0.0.1" 2376 "~/.docker/test-client-key.pem" "~/.docker/test-client-cert.pem" >>= fromRight
42− -- params <- clientParamsSetCA params' "~/.docker/test-ca.pem"
43+ -- params <- clientParamsSetCA params' "~/.docker/test-ca.pem"
43− -- let settings = mkManagerSettings (TLSSettings params) Nothing
44+ -- let settings = mkManagerSettings (TLSSettings params) Nothing
44− -- mgr <- newManager settings
45+ -- mgr <- newManager settings
45− h <- defaultHttpHandler
47+ h <- defaultHttpHandler
46− runDockerT (defaultClientOpts, h) f
48+ runDockerT (defaultClientOpts, h) f
48testDockerVersion :: IO ()
50testDockerVersion :: IO ()
49−testDockerVersion = runDocker $ do
51+testDockerVersion =
50− v <- getDockerVersion
53+ do v <- getDockerVersion
51− lift $ assert $ isRight v
54+ lift $ assert $ isRight v
53testFindImage :: IO ()
56testFindImage :: IO ()
54−testFindImage = runDocker $ do
57+testFindImage =
55− images <- listImages defaultListOpts >>= fromRight
59+ do images <- listImages defaultListOpts >>= fromRight
56− let xs = filter ((== [imageFullName]) . imageRepoTags) images
60+ let xs = filter ((== [imageFullName]) . imageRepoTags) images
57− lift $ assert $ length xs == 1
61+ lift $ assert $ length xs == 1
58− where imageFullName = testImageName <> ":latest"
63+ imageFullName = testImageName <> ":latest"
60testRunAndReadLog :: IO ()
65testRunAndReadLog :: IO ()
61−testRunAndReadLog = runDocker $ do
66+testRunAndReadLog =
62− containerId <- createContainer (defaultCreateOpts (testImageName <> ":latest")) Nothing
68+ do containerId <- createContainer (defaultCreateOpts (testImageName <> ":latest")) Nothing
63− c <- fromRight containerId
69+ c <- fromRight containerId
64− status1 <- startContainer defaultStartOpts c
70+ status1 <- startContainer defaultStartOpts c
65− _ <- inspectContainer c >>= fromRight
71+ _ <- inspectContainer c >>= fromRight
66− lift $ threadDelay 300000 -- give 300ms for the application to finish
72+ lift $ threadDelay 300000 -- give 300ms for the application to finish
67− lift $ assert $ isRightUnit status1
73+ lift $ assert $ isRightUnit status1
68− status2 <- killContainer SIGTERM c
74+ status2 <- killContainer SIGTERM c
69− logs <- getContainerLogs defaultLogOpts c >>= fromRight
75+ logs <- getContainerLogs defaultLogOpts c >>= fromRight
70− lift $ assert $ isRightUnit status2
76+ lift $ assert $ isRightUnit status2
71− lift $ assert $ (C.pack "123") `C.isInfixOf` (toStrict1 logs)
77+ lift $ assert $ (C.pack "123") `C.isInfixOf` (toStrict1 logs)
72− status3 <- deleteContainer (DeleteOpts True True) c
78+ status3 <- deleteContainer (DeleteOpts True True) c
73− lift $ assert $ isRightUnit status3
79+ lift $ assert $ isRightUnit status3
76− isRightUnit (Right ()) = True
81+ isRightUnit (Right ()) = True
77− isRightUnit _ = False
82+ isRightUnit _ = False
79testLogDriverOptionsJson :: TestTree
84testLogDriverOptionsJson :: TestTree
80−testLogDriverOptionsJson = testGroup "Testing LogDriverOptions JSON" [ test1, test2, test3 ]
85+testLogDriverOptionsJson = testGroup "Testing LogDriverOptions JSON" [test1, test2, test3]
82− test1 = testCase "Driver option 1" $ assert $ JSON.toJSON sample ^. key key1 . _String == val1
87+ test1 = testCase "Driver option 1" $ assert $ JSON.toJSON sample ^. key key1 . _String == val1
83− test2 = testCase "Driver option 2" $ assert $ JSON.toJSON sample ^. key key2 . _String == val2
88+ test2 = testCase "Driver option 2" $ assert $ JSON.toJSON sample ^. key key2 . _String == val2
84− test3 = testCase "Test override" $ assert $ JSON.toJSON sample2 ^. key key1 . _String == "override"
90+ testCase "Test override" $ assert $ JSON.toJSON sample2 ^. key key1 . _String == "override"
85− sample = [LogDriverOption key1 val1, LogDriverOption key2 val2]
91+ sample = [LogDriverOption key1 val1, LogDriverOption key2 val2]
86− sample2 = [LogDriverOption key1 val1, LogDriverOption key1 "override"]
92+ sample2 = [LogDriverOption key1 val1, LogDriverOption key1 "override"]
87− key1 = "some-key"
93+ key1 = "some-key"
88− val1 = "some-val"
94+ val1 = "some-val"
89− key2 = "some-key2"
95+ key2 = "some-key2"
90− val2 = "some-key2"
96+ val2 = "some-key2"
92testExposedPortsJson :: TestTree
98testExposedPortsJson :: TestTree
93−testExposedPortsJson = testGroup "Testing ExposedPorts JSON" [ testTCP, testUDP ]
99+testExposedPortsJson = testGroup "Testing ExposedPorts JSON" [testTCP, testUDP]
95− testTCP = testCase "tcp port" $ assert $ JSON.toJSON sampleEP ^. key "80/tcp" . _Object == HM.empty
101+ testTCP = testCase "tcp port" $ assert $ JSON.toJSON sampleEP ^. key "80/tcp" . _Object == HM.empty
96− testUDP = testCase "udp port" $ assert $ JSON.toJSON sampleEP ^. key "1337/tcp" . _Object == HM.empty
103+ testCase "udp port" $ assert $ JSON.toJSON sampleEP ^. key "1337/tcp" . _Object == HM.empty
97− sampleEP = [ExposedPort 80 TCP, ExposedPort 1337 UDP]
104+ sampleEP = [ExposedPort 80 TCP, ExposedPort 1337 UDP]
99testLabelsJson :: TestTree
106testLabelsJson :: TestTree
100−testLabelsJson = testGroup "Testing Labels JSON" [ testLS1, testLS2, testOverride ]
107+testLabelsJson = testGroup "Testing Labels JSON" [testLS1, testLS2, testOverride]
102− testLS1 = testCase "test label key1" $ assert $ JSON.toJSON sampleLS ^. key key1 . _String == val1
109+ testLS1 = testCase "test label key1" $ assert $ JSON.toJSON sampleLS ^. key key1 . _String == val1
103− testLS2 = testCase "test label key2" $ assert $ JSON.toJSON sampleLS ^. key key2 . _String == val2
110+ testLS2 = testCase "test label key2" $ assert $ JSON.toJSON sampleLS ^. key key2 . _String == val2
104− testOverride = testCase "test label override" $ assert $ JSON.toJSON [Label key1 val1, Label key1 "override"] ^. key key1 . _String == "override"
112+ testCase "test label override" $ assert $ JSON.toJSON [Label key1 val1, Label key1 "override"] ^.
105− sampleLS = [Label key1 val1, Label key2 val2]
116+ sampleLS = [Label key1 val1, Label key2 val2]
106− key1 = "com.example.some-label"
117+ key1 = "com.example.some-label"
107− val1 = "some-value"
118+ val1 = "some-value"
108− key2 = "something"
119+ key2 = "something"
109− val2 = "value"
120+ val2 = "value"
111testVolumesJson :: TestTree
122testVolumesJson :: TestTree
112−testVolumesJson = testGroup "Testing Volumes JSON" [ testSample1, testSample2 ]
123+testVolumesJson = testGroup "Testing Volumes JSON" [testSample1, testSample2]
114− testSample1 = testCase "Test exposing volume: /tmp" $ assert $ JSON.toJSON sampleVolumes ^. key "/tmp" . _Object == HM.empty
126+ testCase "Test exposing volume: /tmp" $ assert $ JSON.toJSON sampleVolumes ^. key "/tmp" . _Object ==
115− testSample2 = testCase "Test exposing volume: /opt" $ assert $ JSON.toJSON sampleVolumes ^. key "/opt" . _Object == HM.empty
129+ testCase "Test exposing volume: /opt" $ assert $ JSON.toJSON sampleVolumes ^. key "/opt" . _Object ==
116− sampleVolumes = [Volume "/tmp", Volume "/opt"]
131+ sampleVolumes = [Volume "/tmp", Volume "/opt"]
133+testEntrypointJson :: TestTree
134+testEntrypointJson = testGroup "Testing ContainerConfig JSON" [testSample1, testSample2, testSample3, testSample4, testSample5]
137+ testCase "Test toJSON with empty entrypoint (null)" $ assert $ JSON.toJSON (Entrypoint []) ^. _Null == ()
139+ testCase "Test toJSON with entrypoint as Array" $ assert $
140+ JSON.toJSON (Entrypoint sampleEntrypointArr) ==
141+ JSON.toJSON sampleEntrypointArr
143+ testCase "Test decoding entrypoint as string" $ assert $ (JSON.decode "\"cmd\"") ==
144+ Just (Entrypoint ["cmd"])
146+ testCase "Test decoding as null" $ assert $ (JSON.decode "null" :: Maybe Entrypoint) ==
147+ Just (Entrypoint [])
149+ testCase "Test decoding as array" $ assert $ (JSON.decode (JSON.encode sampleEntrypointArr) :: Maybe Entrypoint) ==
150+ Just (Entrypoint sampleEntrypointArr)
151+ sampleEntrypointArr = ["cmd", "--some-flag", "--some-flag2"]
118integrationTests :: TestTree
153integrationTests :: TestTree
119−integrationTests = testGroup "Integration Tests" [
154+integrationTests =
120− testCase "Get docker version" testDockerVersion,
157+ [ testCase "Get docker version" testDockerVersion
121− testCase "Find image by name" testFindImage,
158+ , testCase "Find image by name" testFindImage
122− testCase "Run a dummy container and read its log" testRunAndReadLog]
159+ , testCase "Run a dummy container and read its log" testRunAndReadLog
124jsonTests :: TestTree
162jsonTests :: TestTree
125−jsonTests = testGroup "JSON Tests" [testExposedPortsJson, testVolumesJson, testLabelsJson, testLogDriverOptionsJson]
163+jsonTests =
166+ [ testExposedPortsJson
169+ , testLogDriverOptionsJson
170+ , testEntrypointJson
127setup :: IO ()
173setup :: IO ()
128−setup = system ("docker build -t "++unpack testImageName++" tests") >> return ()
174+setup = system ("docker build -t " ++ unpack testImageName ++ " tests") >> return ()
130−isRight (Left _) = False
176+isRight (Left _) = False
131isRight (Right _) = True
177isRight (Right _) = True
133−fromRight :: (MonadIO m, Show l) => Either l r -> m r
180+ :: (MonadIO m, Show l)
181+ => Either l r -> m r
134fromRight (Left l) = do
182fromRight (Left l) = do
135− liftIO $ assertFailure $ "Left: " ++ show l
183+ liftIO $ assertFailure $ "Left: " ++ show l
136− undefined
184+ undefined
137fromRight (Right r) = return r
185fromRight (Right r) = return r
139main :: IO ()
187main :: IO ()
142 defaultMain $ testGroup "Tests" [jsonTests, integrationTests]
190 defaultMain $ testGroup "Tests" [jsonTests, integrationTests]