Add name option for project/composition name

This commit is contained in:
Robert Hensing 2020-10-10 22:04:52 +02:00
parent 427a3b0e3c
commit df0ec2eb50
7 changed files with 84 additions and 30 deletions

View file

@ -49,6 +49,7 @@ library
exposed-modules: Arion.Nix exposed-modules: Arion.Nix
Arion.Aeson Arion.Aeson
Arion.DockerCompose Arion.DockerCompose
Arion.ExtendedInfo
Arion.Images Arion.Images
Arion.Services Arion.Services
other-modules: Paths_arion_compose other-modules: Paths_arion_compose

View file

@ -1,5 +1,6 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
config.name = "webapp";
config.services = { config.services = {
webserver = { webserver = {

View file

@ -10,6 +10,7 @@ import Arion.Aeson
import Arion.Images (loadImages) import Arion.Images (loadImages)
import qualified Arion.DockerCompose as DockerCompose import qualified Arion.DockerCompose as DockerCompose
import Arion.Services (getDefaultExec) import Arion.Services (getDefaultExec)
import Arion.ExtendedInfo (loadExtendedInfoFromPath, ExtendedInfo(images, name))
import Options.Applicative import Options.Applicative
import Control.Monad.Fail import Control.Monad.Fail
@ -142,20 +143,24 @@ runDC cmd (DockerComposeArgs args) _opts = do
runBuildAndDC :: Text -> DockerComposeArgs -> CommonOptions -> IO () runBuildAndDC :: Text -> DockerComposeArgs -> CommonOptions -> IO ()
runBuildAndDC cmd dopts opts = do runBuildAndDC cmd dopts opts = do
withBuiltComposeFile opts $ \path -> do withBuiltComposeFile opts $ callDC cmd dopts True
loadImages path
DockerCompose.run DockerCompose.Args
{ files = [path]
, otherArgs = [cmd] ++ unDockerComposeArgs dopts
}
runEvalAndDC :: Text -> DockerComposeArgs -> CommonOptions -> IO () runEvalAndDC :: Text -> DockerComposeArgs -> CommonOptions -> IO ()
runEvalAndDC cmd dopts opts = do runEvalAndDC cmd dopts opts = do
withComposeFile opts $ \path -> withComposeFile opts $ callDC cmd dopts False
DockerCompose.run DockerCompose.Args
{ files = [path] callDC :: Text -> DockerComposeArgs -> Bool -> FilePath -> IO ()
, otherArgs = [cmd] ++ unDockerComposeArgs dopts callDC cmd dopts shouldLoadImages path = do
} extendedInfo <- loadExtendedInfoFromPath path
when shouldLoadImages $ loadImages (images extendedInfo)
let firstOpts =
do
n <- toList (name extendedInfo)
["--project-name", n]
DockerCompose.run DockerCompose.Args
{ files = [path]
, otherArgs = firstOpts ++ [cmd] ++ unDockerComposeArgs dopts
}
withBuiltComposeFile :: CommonOptions -> (FilePath -> IO r) -> IO r withBuiltComposeFile :: CommonOptions -> (FilePath -> IO r) -> IO r
withBuiltComposeFile opts cont = case prebuiltComposeFile opts of withBuiltComposeFile opts cont = case prebuiltComposeFile opts of

View file

@ -0,0 +1,37 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-
Parses the x-arion field in the generated compose file.
-}
module Arion.ExtendedInfo where
import Prelude()
import Protolude
import Data.Aeson as Aeson
import Arion.Aeson
import Control.Lens
import Data.Aeson.Lens
data Image = Image
{ image :: Maybe Text -- ^ image tar.gz file path
, imageExe :: Maybe Text -- ^ path to exe producing image tar
, imageName :: Text
, imageTag :: Text
} deriving (Eq, Show, Generic, Aeson.ToJSON, Aeson.FromJSON)
data ExtendedInfo = ExtendedInfo {
name :: Maybe Text,
images :: [Image]
} deriving (Eq, Show)
loadExtendedInfoFromPath :: FilePath -> IO ExtendedInfo
loadExtendedInfoFromPath fp = do
v <- decodeFile fp
pure ExtendedInfo {
-- TODO: use aeson derived instance?
name = v ^? key "x-arion" . key "name" . _String,
images = (v :: Aeson.Value) ^.. key "x-arion" . key "images" . _Array . traverse . _JSON
}

View file

@ -8,38 +8,23 @@ module Arion.Images
import Prelude() import Prelude()
import Protolude hiding (to) import Protolude hiding (to)
import qualified Data.Aeson as Aeson
import Arion.Aeson (decodeFile)
import qualified System.Process as Process import qualified System.Process as Process
import qualified Data.Text as T import qualified Data.Text as T
import Control.Lens import Arion.ExtendedInfo (Image(..))
import Data.Aeson.Lens
data Image = Image
{ image :: Maybe Text -- ^ image tar.gz file path
, imageExe :: Maybe Text -- ^ path to exe producing image tar
, imageName :: Text
, imageTag :: Text
} deriving (Generic, Aeson.ToJSON, Aeson.FromJSON, Show)
type TaggedImage = Text type TaggedImage = Text
-- | Subject to change -- | Subject to change
loadImages :: FilePath -> IO () loadImages :: [Image] -> IO ()
loadImages fp = do loadImages requestedImages = do
v <- decodeFile fp
loaded <- getDockerImages loaded <- getDockerImages
let let
images :: [Image]
images = (v :: Aeson.Value) ^.. key "x-arion" . key "images" . _Array . traverse . _JSON
isNew i = (imageName i <> ":" <> imageTag i) `notElem` loaded isNew i = (imageName i <> ":" <> imageTag i) `notElem` loaded
traverse_ loadImage . filter isNew $ images traverse_ loadImage . filter isNew $ requestedImages
loadImage :: Image -> IO () loadImage :: Image -> IO ()
loadImage (Image { image = Just imgPath, imageName = name }) = loadImage (Image { image = Just imgPath, imageName = name }) =

View file

@ -4,4 +4,5 @@
./modules/composition/images.nix ./modules/composition/images.nix
./modules/composition/service-info.nix ./modules/composition/service-info.nix
./modules/composition/arion-base-image.nix ./modules/composition/arion-base-image.nix
./modules/composition/composition.nix
] ]

View file

@ -0,0 +1,24 @@
{ config, lib, ... }:
let
inherit (lib) types mkOption;
link = url: text:
''link:${url}[${text}]'';
in
{
options = {
name = mkOption {
description = ''
Name of the project.
See ${link "https://docs.docker.com/compose/reference/envvars/#compose_project_name" "COMPOSE_PROJECT_NAME"}
'';
type = types.nullOr types.str;
default = null;
};
};
config = {
docker-compose.extended.name = config.name;
};
}