WIP podman
This commit is contained in:
parent
01f359b8f6
commit
3dcadd5e40
8 changed files with 67 additions and 26 deletions
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
deployment.technology = "podman";
|
||||
|
||||
services.webserver = { pkgs, lib, ... }: {
|
||||
nixos.useSystemd = true;
|
||||
nixos.configuration.boot.tmpOnTmpfs = true;
|
||||
|
|
|
@ -48,6 +48,8 @@ in
|
|||
haskellPkgs.ghcid
|
||||
haskellPkgs.haskell-language-server
|
||||
super.docker-compose
|
||||
super.podman
|
||||
super.podman-compose
|
||||
self.niv
|
||||
self.releaser
|
||||
];
|
||||
|
|
|
@ -10,7 +10,7 @@ import Arion.Aeson
|
|||
import Arion.Images (loadImages)
|
||||
import qualified Arion.DockerCompose as DockerCompose
|
||||
import Arion.Services (getDefaultExec)
|
||||
import Arion.ExtendedInfo (loadExtendedInfoFromPath, ExtendedInfo(images, projectName))
|
||||
import Arion.ExtendedInfo (loadExtendedInfoFromPath, ExtendedInfo(images, projectName), technology, Technology(..))
|
||||
|
||||
import Options.Applicative
|
||||
import Control.Monad.Fail
|
||||
|
@ -147,6 +147,7 @@ runDC cmd (DockerComposeArgs args) _opts = do
|
|||
DockerCompose.run DockerCompose.Args
|
||||
{ files = []
|
||||
, otherArgs = [cmd] ++ args
|
||||
, isPodman = True -- FIXME
|
||||
}
|
||||
|
||||
runBuildAndDC :: Text -> DockerComposeArgs -> CommonOptions -> IO ()
|
||||
|
@ -160,11 +161,13 @@ runEvalAndDC cmd dopts opts = do
|
|||
callDC :: Text -> DockerComposeArgs -> CommonOptions -> Bool -> FilePath -> IO ()
|
||||
callDC cmd dopts opts shouldLoadImages path = do
|
||||
extendedInfo <- loadExtendedInfoFromPath path
|
||||
when shouldLoadImages $ loadImages (images extendedInfo)
|
||||
let is_podman = technology extendedInfo == Podman
|
||||
when shouldLoadImages $ loadImages is_podman (images extendedInfo)
|
||||
let firstOpts = projectArgs extendedInfo <> commonArgs opts
|
||||
DockerCompose.run DockerCompose.Args
|
||||
{ files = [path]
|
||||
, otherArgs = firstOpts ++ [cmd] ++ unDockerComposeArgs dopts
|
||||
, isPodman = is_podman
|
||||
}
|
||||
|
||||
projectArgs :: ExtendedInfo -> [Text]
|
||||
|
@ -299,6 +302,7 @@ runExec detach privileged user noTTY index envs workDir service commandAndArgs o
|
|||
[] -> ["/bin/sh"]
|
||||
x -> x
|
||||
|
||||
let is_podman = technology extendedInfo == Podman
|
||||
let args = concat
|
||||
[ ["exec"]
|
||||
, ("--detach" <$ guard detach :: [Text])
|
||||
|
@ -314,6 +318,7 @@ runExec detach privileged user noTTY index envs workDir service commandAndArgs o
|
|||
DockerCompose.run DockerCompose.Args
|
||||
{ files = [path]
|
||||
, otherArgs = projectArgs extendedInfo <> commonArgs opts <> args
|
||||
, isPodman = is_podman
|
||||
}
|
||||
|
||||
main :: IO ()
|
||||
|
|
|
@ -8,6 +8,7 @@ import System.Process
|
|||
data Args = Args
|
||||
{ files :: [FilePath]
|
||||
, otherArgs :: [Text]
|
||||
, isPodman :: Bool
|
||||
}
|
||||
|
||||
run :: Args -> IO ()
|
||||
|
@ -15,9 +16,9 @@ run args = do
|
|||
let fileArgs = files args >>= \f -> ["--file", f]
|
||||
allArgs = fileArgs ++ map toS (otherArgs args)
|
||||
|
||||
procSpec = proc "docker-compose" allArgs
|
||||
|
||||
-- hPutStrLn stderr ("Running docker-compose with " <> show allArgs :: Text)
|
||||
exeName = if isPodman args then "podman-compose" else "docker-compose"
|
||||
procSpec =
|
||||
proc exeName allArgs
|
||||
|
||||
withCreateProcess procSpec $ \_in _out _err procHandle -> do
|
||||
|
||||
|
@ -27,4 +28,4 @@ run args = do
|
|||
ExitSuccess -> pass
|
||||
ExitFailure 1 -> exitFailure
|
||||
ExitFailure {} -> do
|
||||
throwIO $ FatalError $ "docker-compose failed with " <> show exitCode
|
||||
throwIO $ FatalError $ toS exeName <> " failed with status " <> show exitCode
|
||||
|
|
|
@ -22,9 +22,13 @@ data Image = Image
|
|||
, imageTag :: Text
|
||||
} deriving (Eq, Show, Generic, Aeson.ToJSON, Aeson.FromJSON)
|
||||
|
||||
data Technology = Docker | Podman
|
||||
deriving (Eq, Show)
|
||||
|
||||
data ExtendedInfo = ExtendedInfo {
|
||||
projectName :: Maybe Text,
|
||||
images :: [Image]
|
||||
images :: [Image],
|
||||
technology :: Technology
|
||||
} deriving (Eq, Show)
|
||||
|
||||
loadExtendedInfoFromPath :: FilePath -> IO ExtendedInfo
|
||||
|
@ -33,5 +37,10 @@ loadExtendedInfoFromPath fp = do
|
|||
pure ExtendedInfo {
|
||||
-- TODO: use aeson derived instance?
|
||||
projectName = v ^? key "x-arion" . key "project" . key "name" . _String,
|
||||
images = (v :: Aeson.Value) ^.. key "x-arion" . key "images" . _Array . traverse . _JSON
|
||||
images = (v :: Aeson.Value) ^.. key "x-arion" . key "images" . _Array . traverse . _JSON,
|
||||
technology =
|
||||
case v ^? key "x-arion" . key "technology" . _String of
|
||||
Just "podman" -> Podman
|
||||
Just "docker" -> Docker
|
||||
_ -> panic "Unknown x-arion.technology" -- Shouldn't happen
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ import Arion.ExtendedInfo (Image(..))
|
|||
type TaggedImage = Text
|
||||
|
||||
-- | Subject to change
|
||||
loadImages :: [Image] -> IO ()
|
||||
loadImages requestedImages = do
|
||||
loadImages :: Bool -> [Image] -> IO ()
|
||||
loadImages isPodman requestedImages = do
|
||||
|
||||
loaded <- getDockerImages
|
||||
loaded <- getDockerImages isPodman
|
||||
|
||||
let
|
||||
isNew i =
|
||||
|
@ -28,23 +28,28 @@ loadImages requestedImages = do
|
|||
-- -- On podman, you automatically get a localhost prefix
|
||||
&& ("localhost/" <> imageName i <> ":" <> imageTag i) `notElem` loaded
|
||||
|
||||
traverse_ loadImage . filter isNew $ requestedImages
|
||||
traverse_ (loadImage isPodman) . filter isNew $ requestedImages
|
||||
|
||||
loadImage :: Image -> IO ()
|
||||
loadImage Image { image = Just imgPath, imageName = name } =
|
||||
exeName :: IsString p => Bool -> p
|
||||
exeName _isPodman@True = "podman"
|
||||
exeName _isPodman@False = "docker"
|
||||
|
||||
loadImage :: Bool -> Image -> IO ()
|
||||
loadImage isPodman Image { image = Just imgPath, imageName = name } =
|
||||
withFile (toS imgPath) ReadMode $ \fileHandle -> do
|
||||
let procSpec = (Process.proc "docker" [ "load" ]) {
|
||||
let procSpec = (Process.proc (exeName isPodman) [ "load" ]) {
|
||||
Process.std_in = Process.UseHandle fileHandle
|
||||
}
|
||||
print procSpec
|
||||
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
|
||||
panic $ exeName isPodman <> " 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 }
|
||||
loadImage isPodman Image { imageExe = Just imgExe, imageName = name } = do
|
||||
let loadSpec = (Process.proc (exeName isPodman) [ "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 ->
|
||||
|
@ -57,15 +62,15 @@ loadImage Image { imageExe = Just imgExe, imageName = name } = do
|
|||
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
|
||||
ExitFailure code -> panic $ exeName isPodman <> " load failed with exit code " <> show code <> " for image " <> name <> " produced by executable " <> imgExe
|
||||
_ -> pass
|
||||
pass
|
||||
|
||||
loadImage Image { imageName = name } = do
|
||||
loadImage _isPodman 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}}" ]
|
||||
getDockerImages :: Bool -> IO [TaggedImage]
|
||||
getDockerImages isPodman = do
|
||||
let procSpec = Process.proc (exeName isPodman) [ "images", "--filter", "dangling=false", "--format", "{{.Repository}}:{{.Tag}}" ]
|
||||
map toS . T.lines . toS <$> Process.readCreateProcess procSpec ""
|
||||
|
|
|
@ -4,4 +4,7 @@
|
|||
./modules/composition/images.nix
|
||||
./modules/composition/service-info.nix
|
||||
./modules/composition/composition.nix
|
||||
]
|
||||
./modules/composition/deployment.nix
|
||||
./modules/composition/deployment/docker.nix
|
||||
./modules/composition/deployment/podman.nix
|
||||
]
|
||||
|
|
|
@ -29,6 +29,20 @@ let
|
|||
config.service.name = name;
|
||||
};
|
||||
|
||||
json.type = with lib.types; let
|
||||
valueType = nullOr (oneOf [
|
||||
bool
|
||||
int
|
||||
float
|
||||
str
|
||||
path # extra
|
||||
package # extra
|
||||
(attrsOf valueType)
|
||||
(listOf valueType)
|
||||
]) // {
|
||||
description = "JSON value";
|
||||
};
|
||||
in valueType;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
|
@ -52,11 +66,11 @@ in
|
|||
readOnly = true;
|
||||
};
|
||||
docker-compose.raw = lib.mkOption {
|
||||
type = lib.types.attrs;
|
||||
type = json.type;
|
||||
description = "Attribute set that will be turned into the docker-compose.yaml file, using Nix's toJSON builtin.";
|
||||
};
|
||||
docker-compose.extended = lib.mkOption {
|
||||
type = lib.types.attrs;
|
||||
type = json.type;
|
||||
description = "Attribute set that will be turned into the x-arion section of the docker-compose.yaml file.";
|
||||
};
|
||||
services = lib.mkOption {
|
||||
|
|
Loading…
Reference in a new issue