-
Notifications
You must be signed in to change notification settings - Fork 51
/
Copy pathImages.hs
65 lines (58 loc) · 2.82 KB
/
Images.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
module Arion.Images
( loadImages,
)
where
import Arion.ExtendedInfo (Image (..))
import qualified Data.Text as T
import Protolude hiding (to)
import qualified System.Process as Process
import Prelude ()
type TaggedImage = Text
-- | Subject to change
loadImages :: [Image] -> IO ()
loadImages requestedImages = do
loaded <- getDockerImages
let isNew :: Image -> Bool
isNew i =
-- On docker, the image name is unmodified
(i.imageName <> ":" <> i.imageTag) `notElem` loaded
-- On podman, you used to automatically get a localhost prefix
-- however, since NixOS 22.05, this expected to be part of the name instead
&& ("localhost/" <> i.imageName <> ":" <> i.imageTag) `notElem` loaded
traverse_ loadImage . filter isNew $ requestedImages
loadImage :: Image -> IO ()
loadImage Image {image = Just imgPath, imageName = name} =
withFile (toS imgPath) ReadMode $ \fileHandle -> do
let procSpec =
(Process.proc "docker" ["load"])
{ Process.std_in = Process.UseHandle fileHandle
}
Process.withCreateProcess procSpec $ \_in _out _err procHandle -> do
e <- Process.waitForProcess procHandle
case e of
ExitSuccess -> pass
ExitFailure code ->
panic $ "docker load failed with exit code " <> show code <> " for image " <> name <> " from path " <> imgPath
loadImage Image {imageExe = Just imgExe, imageName = name} = do
let loadSpec = (Process.proc "docker" ["load"]) {Process.std_in = Process.CreatePipe}
Process.withCreateProcess loadSpec $ \(Just inHandle) _out _err loadProcHandle -> do
let streamSpec = Process.proc (toS imgExe) []
Process.withCreateProcess streamSpec {Process.std_out = Process.UseHandle inHandle} $ \_ _ _ streamProcHandle ->
withAsync (Process.waitForProcess loadProcHandle) $ \loadExitAsync ->
withAsync (Process.waitForProcess streamProcHandle) $ \streamExitAsync -> do
r <- waitEither loadExitAsync streamExitAsync
case r of
Right (ExitFailure code) -> panic $ "image producer for image " <> name <> " failed with exit code " <> show code <> " from executable " <> imgExe
Right ExitSuccess -> pass
Left _ -> pass
loadExit <- wait loadExitAsync
case loadExit of
ExitFailure code -> panic $ "docker load failed with exit code " <> show code <> " for image " <> name <> " produced by executable " <> imgExe
_ -> pass
pass
loadImage Image {imageName = name} = do
panic $ "image " <> name <> " doesn't specify an image file or imageExe executable"
getDockerImages :: IO [TaggedImage]
getDockerImages = do
let procSpec = Process.proc "docker" ["images", "--filter", "dangling=false", "--format", "{{.Repository}}:{{.Tag}}"]
map toS . T.lines . toS <$> Process.readCreateProcess procSpec ""