Skip to content

Commit 72e0fa3

Browse files
committed
Parse docker-stack-exe and docker-database-path into their proper types ASAP
This entails a behavior change when the argument to the 'docker-stack-exe' option cannot be parsed: Previously the option was ignored in this case, now an exception is thrown. Side effects of this change: * StackDockerException is moved to Stack.Types.Docker, so parseDockerStackExe can throw a proper exception * Stack.Nix.CannotDetermineProjectRootException is renamed because Stack.Types.Docker.CannotDetermineProjectRootException has moved into the same scope.
1 parent 82b7e8d commit 72e0fa3

7 files changed

Lines changed: 198 additions & 184 deletions

File tree

src/Options/Applicative/Builder/Extra.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Options.Applicative.Builder.Extra
1616
,relFileOption
1717
,absDirOption
1818
,relDirOption
19+
,eitherReader'
1920
) where
2021

2122
import Control.Monad (when)

src/Stack/Config/Docker.hs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
module Stack.Config.Docker where
55

66
import Control.Exception.Lifted
7-
import Control.Monad
8-
import Control.Monad.Catch (throwM, MonadThrow)
7+
import Control.Monad.Catch (MonadThrow)
98
import Data.List (find)
109
import Data.Maybe
1110
import Data.Monoid.Extra
@@ -73,17 +72,8 @@ dockerOptsFromMonoid mproject stackRoot maresolver DockerOptsMonoid{..} = do
7372
dockerSetUser = getFirst dockerMonoidSetUser
7473
dockerRequireDockerVersion =
7574
simplifyVersionRange (getIntersectingVersionRange dockerMonoidRequireDockerVersion)
76-
dockerDatabasePath <-
77-
case getFirst dockerMonoidDatabasePath of
78-
Nothing -> return $ stackRoot </> $(mkRelFile "docker.db")
79-
Just fp ->
80-
case parseAbsFile fp of
81-
Left e -> throwM (InvalidDatabasePathException e)
82-
Right p -> return p
83-
dockerStackExe <-
84-
case getFirst dockerMonoidStackExe of
85-
Just e -> liftM Just (parseDockerStackExe e)
86-
Nothing -> return Nothing
75+
dockerDatabasePath = fromFirst (stackRoot </> $(mkRelFile "docker.db")) dockerMonoidDatabasePath
76+
dockerStackExe = getFirst dockerMonoidStackExe
8777
return DockerOpts{..}
8878
where emptyToNothing Nothing = Nothing
8979
emptyToNothing (Just s) | null s = Nothing

src/Stack/Constants.hs-boot

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module Stack.Constants where
2+
3+
stackProgName :: String

src/Stack/Docker.hs

Lines changed: 0 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,7 @@ import Data.Text (Text)
4848
import qualified Data.Text as T
4949
import qualified Data.Text.Encoding as T
5050
import Data.Time (UTCTime,LocalTime(..),diffDays,utcToLocalTime,getZonedTime,ZonedTime(..))
51-
import Data.Typeable (Typeable)
5251
import Data.Version (showVersion)
53-
import Distribution.System (Platform (Platform),Arch (X86_64),OS (Linux))
54-
import Distribution.Text (display)
5552
import GHC.Exts (sortWith)
5653
import Network.HTTP.Client.Conduit (HasHttpManager)
5754
import Path
@@ -881,29 +878,6 @@ fromMaybeProjectRoot = fromMaybe (throw CannotDetermineProjectRootException)
881878
oldSandboxIdEnvVar :: String
882879
oldSandboxIdEnvVar = "DOCKER_SANDBOX_ID"
883880

884-
-- | Command-line argument for "docker"
885-
dockerCmdName :: String
886-
dockerCmdName = "docker"
887-
888-
dockerHelpOptName :: String
889-
dockerHelpOptName = dockerCmdName ++ "-help"
890-
891-
-- | Command-line argument for @docker pull@.
892-
dockerPullCmdName :: String
893-
dockerPullCmdName = "pull"
894-
895-
-- | Command-line argument for @docker cleanup@.
896-
dockerCleanupCmdName :: String
897-
dockerCleanupCmdName = "cleanup"
898-
899-
-- | Command-line option for @--internal-re-exec-version@.
900-
reExecArgName :: String
901-
reExecArgName = "internal-re-exec-version"
902-
903-
-- | Platform that Docker containers run
904-
dockerContainerPlatform :: Platform
905-
dockerContainerPlatform = Platform X86_64 Linux
906-
907881
-- | Options for 'cleanup'.
908882
data CleanupOpts = CleanupOpts
909883
{ dcAction :: !CleanupAction
@@ -951,135 +925,6 @@ instance FromJSON ImageConfig where
951925
<$> fmap join (o .:? "Env") .!= []
952926
<*> fmap join (o .:? "Entrypoint") .!= []
953927

954-
-- | Exceptions thrown by Stack.Docker.
955-
data StackDockerException
956-
= DockerMustBeEnabledException
957-
-- ^ Docker must be enabled to use the command.
958-
| OnlyOnHostException
959-
-- ^ Command must be run on host OS (not in a container).
960-
| InspectFailedException String
961-
-- ^ @docker inspect@ failed.
962-
| NotPulledException String
963-
-- ^ Image does not exist.
964-
| InvalidCleanupCommandException String
965-
-- ^ Input to @docker cleanup@ has invalid command.
966-
| InvalidImagesOutputException String
967-
-- ^ Invalid output from @docker images@.
968-
| InvalidPSOutputException String
969-
-- ^ Invalid output from @docker ps@.
970-
| InvalidInspectOutputException String
971-
-- ^ Invalid output from @docker inspect@.
972-
| PullFailedException String
973-
-- ^ Could not pull a Docker image.
974-
| DockerTooOldException Version Version
975-
-- ^ Installed version of @docker@ below minimum version.
976-
| DockerVersionProhibitedException [Version] Version
977-
-- ^ Installed version of @docker@ is prohibited.
978-
| BadDockerVersionException VersionRange Version
979-
-- ^ Installed version of @docker@ is out of range specified in config file.
980-
| InvalidVersionOutputException
981-
-- ^ Invalid output from @docker --version@.
982-
| HostStackTooOldException Version (Maybe Version)
983-
-- ^ Version of @stack@ on host is too old for version in image.
984-
| ContainerStackTooOldException Version Version
985-
-- ^ Version of @stack@ in container/image is too old for version on host.
986-
| CannotDetermineProjectRootException
987-
-- ^ Can't determine the project root (where to put docker sandbox).
988-
| DockerNotInstalledException
989-
-- ^ @docker --version@ failed.
990-
| UnsupportedStackExeHostPlatformException
991-
-- ^ Using host stack-exe on unsupported platform.
992-
deriving (Typeable)
993-
994-
-- | Exception instance for StackDockerException.
995-
instance Exception StackDockerException
996-
997-
-- | Show instance for StackDockerException.
998-
instance Show StackDockerException where
999-
show DockerMustBeEnabledException =
1000-
"Docker must be enabled in your configuration file to use this command."
1001-
show OnlyOnHostException =
1002-
"This command must be run on host OS (not in a Docker container)."
1003-
show (InspectFailedException image) =
1004-
concat ["'docker inspect' failed for image after pull: ",image,"."]
1005-
show (NotPulledException image) =
1006-
concat ["The Docker image referenced by your configuration file"
1007-
," has not\nbeen downloaded:\n "
1008-
,image
1009-
,"\n\nRun '"
1010-
,unwords [stackProgName, dockerCmdName, dockerPullCmdName]
1011-
,"' to download it, then try again."]
1012-
show (InvalidCleanupCommandException line) =
1013-
concat ["Invalid line in cleanup commands: '",line,"'."]
1014-
show (InvalidImagesOutputException line) =
1015-
concat ["Invalid 'docker images' output line: '",line,"'."]
1016-
show (InvalidPSOutputException line) =
1017-
concat ["Invalid 'docker ps' output line: '",line,"'."]
1018-
show (InvalidInspectOutputException msg) =
1019-
concat ["Invalid 'docker inspect' output: ",msg,"."]
1020-
show (PullFailedException image) =
1021-
concat ["Could not pull Docker image:\n "
1022-
,image
1023-
,"\nThere may not be an image on the registry for your resolver's LTS version in\n"
1024-
,"your configuration file."]
1025-
show (DockerTooOldException minVersion haveVersion) =
1026-
concat ["Minimum docker version '"
1027-
,versionString minVersion
1028-
,"' is required by "
1029-
,stackProgName
1030-
," (you have '"
1031-
,versionString haveVersion
1032-
,"')."]
1033-
show (DockerVersionProhibitedException prohibitedVersions haveVersion) =
1034-
concat ["These Docker versions are incompatible with "
1035-
,stackProgName
1036-
," (you have '"
1037-
,versionString haveVersion
1038-
,"'): "
1039-
,intercalate ", " (map versionString prohibitedVersions)
1040-
,"."]
1041-
show (BadDockerVersionException requiredRange haveVersion) =
1042-
concat ["The version of 'docker' you are using ("
1043-
,show haveVersion
1044-
,") is outside the required\n"
1045-
,"version range specified in stack.yaml ("
1046-
,T.unpack (versionRangeText requiredRange)
1047-
,")."]
1048-
show InvalidVersionOutputException =
1049-
"Cannot get Docker version (invalid 'docker --version' output)."
1050-
show (HostStackTooOldException minVersion (Just hostVersion)) =
1051-
concat ["The host's version of '"
1052-
,stackProgName
1053-
,"' is too old for this Docker image.\nVersion "
1054-
,versionString minVersion
1055-
," is required; you have "
1056-
,versionString hostVersion
1057-
,"."]
1058-
show (HostStackTooOldException minVersion Nothing) =
1059-
concat ["The host's version of '"
1060-
,stackProgName
1061-
,"' is too old.\nVersion "
1062-
,versionString minVersion
1063-
," is required."]
1064-
show (ContainerStackTooOldException requiredVersion containerVersion) =
1065-
concat ["The Docker container's version of '"
1066-
,stackProgName
1067-
,"' is too old.\nVersion "
1068-
,versionString requiredVersion
1069-
," is required; the container has "
1070-
,versionString containerVersion
1071-
,"."]
1072-
show CannotDetermineProjectRootException =
1073-
"Cannot determine project root directory for Docker sandbox."
1074-
show DockerNotInstalledException =
1075-
"Cannot find 'docker' in PATH. Is Docker installed?"
1076-
show UnsupportedStackExeHostPlatformException = concat
1077-
[ "Using host's "
1078-
, stackProgName
1079-
, " executable in Docker container is only supported on "
1080-
, display dockerContainerPlatform
1081-
, " platform" ]
1082-
1083928
-- | Function to get command and arguments to run in Docker container
1084929
type GetCmdArgs env m
1085930
= M env m

src/Stack/Nix.hs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import qualified Paths_stack as Meta
3535
import Prelude hiding (mapM) -- Fix redundant import warnings
3636
import Stack.Config.Nix (nixCompiler)
3737
import Stack.Constants (stackProgName,platformVariantEnvVar)
38-
import Stack.Docker (reExecArgName)
3938
import Stack.Exec (exec)
4039
import Stack.Types
4140
import Stack.Types.Internal
@@ -126,7 +125,7 @@ escape str = "'" ++ foldr (\c -> if c == '\'' then
126125

127126
-- | Fail with friendly error if project root not set.
128127
fromMaybeProjectRoot :: Maybe (Path Abs Dir) -> Path Abs Dir
129-
fromMaybeProjectRoot = fromMaybe (throw CannotDetermineProjectRootException)
128+
fromMaybeProjectRoot = fromMaybe (throw CannotDetermineProjectRoot)
130129

131130
-- | 'True' if we are currently running inside a Nix.
132131
getInShell :: (MonadIO m) => m Bool
@@ -147,14 +146,14 @@ nixHelpOptName = nixCmdName ++ "-help"
147146

148147
-- | Exceptions thrown by "Stack.Nix".
149148
data StackNixException
150-
= CannotDetermineProjectRootException
149+
= CannotDetermineProjectRoot
151150
-- ^ Can't determine the project root (location of the shell file if any).
152151
deriving (Typeable)
153152

154153
instance Exception StackNixException
155154

156155
instance Show StackNixException where
157-
show CannotDetermineProjectRootException =
156+
show CannotDetermineProjectRoot =
158157
"Cannot determine project root directory."
159158

160159
type M env m =

src/Stack/Options.hs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -545,11 +545,12 @@ dockerOptsParser hide0 =
545545
metavar "NAME=VALUE" <>
546546
help ("Set environment variable in container " ++
547547
"(may specify multiple times)")))
548-
<*> firstStrOption (long (dockerOptName dockerDatabasePathArgName) <>
549-
hide <>
550-
metavar "PATH" <>
551-
help "Location of image usage tracking database")
552-
<*> firstStrOption
548+
<*> optionalFirst (absFileOption
549+
(long (dockerOptName dockerDatabasePathArgName) <>
550+
hide <>
551+
metavar "PATH" <>
552+
help "Location of image usage tracking database"))
553+
<*> optionalFirst (option (eitherReader' parseDockerStackExe)
553554
(long(dockerOptName dockerStackExeArgName) <>
554555
hide <>
555556
metavar (intercalate "|"
@@ -559,7 +560,7 @@ dockerOptsParser hide0 =
559560
, "PATH" ]) <>
560561
help (concat [ "Location of "
561562
, stackProgName
562-
, " executable used in container" ]))
563+
, " executable used in container" ])))
563564
<*> firstBoolFlags (dockerOptName dockerSetUserArgName)
564565
"setting user in container to match host"
565566
hide

0 commit comments

Comments
 (0)