Commit a0c7e701 authored by Valentin Reis's avatar Valentin Reis

Merge branch 'experiment-commands' into 'master'

Experiment commands

See merge request argo/argotest!14
parents a2b60e73 014360e9
Pipeline #4864 passed with stage
in 11 seconds
...@@ -112,34 +112,6 @@ There are a few things one has to be aware of using this workflow: ...@@ -112,34 +112,6 @@ There are a few things one has to be aware of using this workflow:
minutes by default. Use a local checkout if you need to modify some of these minutes by default. Use a local checkout if you need to modify some of these
sources on the fly. sources on the fly.
### Example CI setup
``` {.yml}
integration.test:
stage: test
script:
- nix-shell -E '{ argotest ? (builtins.fetchGit {
url = https://xgitlab.cels.anl.gov/argo/argotest.git;
ref="master";})
}:
(import argotest { containers-src = ./. ; }).test' \
--run 'argotk.hs TestHello'
artifacts:
paths:
- argotest/_output/cmd_err.log
- argotest/_output/cmd_out.log
- argotest/_output/daemon_out.log
- argotest/_output/daemon_out.log
- argotest/_output/nrm.log
- argotest/_output/time.log
expire_in: 1 week
except:
- /^wip\/.*/
- /^WIP\/.*/
tags:
- integration
```
### Hacking ### Hacking
- edit `.README.md` in place of README.md. - edit `.README.md` in place of README.md.
......
...@@ -3,3 +3,10 @@ _output ...@@ -3,3 +3,10 @@ _output
result result
.shake .shake
*.log *.log
*/build
*/new-build
*/dist
*/new-dist
*/result
_output
*/_output
...@@ -12,6 +12,6 @@ library ...@@ -12,6 +12,6 @@ library
exposed-Modules: Argo.Stack exposed-Modules: Argo.Stack
Argo.Utils Argo.Utils
Argo.Args Argo.Args
build-depends: base >=4 && <=8, turtle, data-default, managed, ansi-terminal, unix, system-filepath, async, process, text, optparse-applicative, extra, foldl, conduit,conduit-extra, bytestring, stm build-depends: base >=4 && <=8, turtle, data-default, managed, ansi-terminal, unix, system-filepath, async, process, text, optparse-applicative, extra, foldl, conduit,conduit-extra, bytestring, stm, pretty-show
hs-source-dirs: src hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010
{-# LANGUAGE {-# LANGUAGE OverloadedStrings, ApplicativeDo, GeneralizedNewtypeDeriving, RecordWildCards #-}
OverloadedStrings,
ApplicativeDo,
RecordWildCards #-}
module Argo.Args where module Argo.Args where
import Options.Applicative as OA import Options.Applicative as OA
import Options.Applicative.Types
import Options.Applicative.Builder ( option )
import Data.Default import Data.Default
import Data.Text as T import Data.Text as T
hiding ( empty ) hiding ( empty )
import Turtle import Turtle hiding ( option )
import Prelude hiding ( FilePath ) import Prelude hiding ( FilePath )
import System.Process hiding ( shell )
data OutputFiles = OutputFiles FilePath FilePath data OutputFiles = OutputFiles FilePath FilePath
data StackArgs = StackArgs data StackArgs = StackArgs
{ app :: Text { verbosity :: Verbosity
, args :: [Text] , app :: AppName
, containerName :: Text , args :: AppArgs
, workingDirectory :: FilePath , containerName :: ContainerName
, manifestDir :: FilePath , workingDirectory :: WorkingDirectory
, manifestName :: FilePath , manifestDir :: ManifestDir
, cmd_run_out :: FilePath , manifestName :: ManifestName
, cmd_run_err :: FilePath , daemon :: ProcessBehavior
, cmd_listen_out :: FilePath , cmdrun :: ProcessBehavior
, cmd_listen_err :: FilePath , cmdlisten :: ProcessBehavior
, daemon_out :: FilePath , cmdlistenprogress :: ProcessBehavior
, daemon_err :: FilePath , cmdlistenpower :: ProcessBehavior
, nrm_log :: FilePath
, messageDaemonOut :: Maybe Text
, messageDaemonErr :: Maybe Text
, messageCmdRunOut :: Maybe Text
, messageCmdRunErr :: Maybe Text
, messageCmdListenOut :: Maybe Text
, messageCmdListenErr :: Maybe Text
} }
data Verbosity = Normal | Verbose deriving (Show,Read,Eq)
newtype AppArgs = AppArgs [Text] deriving (Show, Read)
newtype WorkingDirectory = WorkingDirectory FilePath deriving (IsString, Show)
newtype AppName = AppName Text deriving (IsString, Show, Read)
newtype ContainerName = ContainerName Text deriving (IsString, Show, Read)
newtype ManifestDir = ManifestDir FilePath deriving (IsString, Show)
newtype ManifestName = ManifestName FilePath deriving (IsString, Show)
newtype StdOutLog = StdOutLog Text deriving (Show, Read)
newtype StdErrLog = StdErrLog Text deriving (Show, Read)
newtype TestText = TestText Text deriving (Show, Read)
data ProcessBehavior =
SucceedTestOnMessage TestText StdOutLog StdErrLog
| JustRun StdOutLog StdErrLog
| DontRun deriving (Show,Read)
behavior :: ReadM ProcessBehavior
behavior = read <$> readerAsk
behaviorOption :: Mod OptionFields ProcessBehavior -> Parser ProcessBehavior
behaviorOption = option behavior
instance Default StackArgs where instance Default StackArgs where
def = StackArgs def = StackArgs
{ app = "echo" { verbosity = Verbose
, args = ["foobar"] , app = AppName "ls"
, containerName = "testContainer" , args = AppArgs []
, workingDirectory = "_output" , containerName = ContainerName "testContainer"
, manifestDir = "manifests" , workingDirectory = WorkingDirectory "_output"
, manifestName = "basic.json" , manifestDir = ManifestDir "manifests"
, cmd_run_out = "cmd_run_out.log" , manifestName = ManifestName "basic.json"
, cmd_run_err = "cmd_run_err.log" , daemon = DontRun
, cmd_listen_out = "cmd_listen_out.log" , cmdrun = DontRun
, cmd_listen_err = "cmd_listen_err.log" , cmdlisten = DontRun
, daemon_out = "daemon_out.log" , cmdlistenprogress = DontRun
, daemon_err = "daemon_err.log" , cmdlistenpower = DontRun
, nrm_log = "nrm.log"
, messageDaemonOut = Nothing
, messageDaemonErr = Nothing
, messageCmdRunOut = Nothing
, messageCmdRunErr = Nothing
, messageCmdListenOut = Nothing
, messageCmdListenErr = Nothing
} }
parseExtendStackArgs :: StackArgs -> Parser StackArgs parseExtendStackArgs :: StackArgs -> Parser StackArgs
parseExtendStackArgs StackArgs {..} = do parseExtendStackArgs StackArgs {..} = do
verbosity <- flag
Normal
Verbose
(long "verbose" <> short 'v' <> help "Enable verbose mode")
app <- strOption app <- strOption
( long "application" ( long "application"
<> metavar "APP" <> metavar "APP"
...@@ -97,113 +109,39 @@ parseExtendStackArgs StackArgs {..} = do ...@@ -97,113 +109,39 @@ parseExtendStackArgs StackArgs {..} = do
<> showDefault <> showDefault
<> value manifestName <> value manifestName
) )
cmd_run_out <- strOption daemon <- behaviorOption
( long "cmd_run_out" ( long "daemon"
<> metavar "FILENAME" <> metavar "BEHAVIOR"
<> help "Output file (relative to --output_dir), \"cmd run\" stdout" <> help "`daemon` behavior"
<> showDefault
<> value cmd_run_out
)
cmd_run_err <- strOption
( long "cmd_run_err"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), \"cmd run\" stderr"
<> showDefault
<> value cmd_run_err
)
cmd_listen_out <- strOption
( long "cmd_listen_out"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), \"cmd listen\" stdout"
<> showDefault
<> value cmd_listen_out
)
cmd_listen_err <- strOption
( long "cmd_listen_err"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), \"cmd listen\" stderr"
<> showDefault
<> value cmd_listen_err
)
daemon_out <- strOption
( long "daemon_out"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), daemon stdout"
<> showDefault
<> value daemon_out
)
daemon_err <- strOption
( long "daemon_err"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), daemon stderr"
<> showDefault
<> value daemon_err
)
nrm_log <- strOption
( long "nrm_log"
<> metavar "FILENAME"
<> help "Output file (relative to --output_dir), daemon log"
<> showDefault
<> value nrm_log
)
messageDaemonOut <- optional $ strOption
( long "message_daemon_stdout"
<> metavar "STRING"
<> help
"The appearance of this character string in the daemon stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault
<> maybe mempty value messageDaemonOut
)
messageDaemonErr <- optional $ strOption
( long "message_daemon_stderr"
<> metavar "STRING"
<> help
"The appearance of this character string in the daemon stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageDaemonErr <> value daemon
) )
messageCmdRunOut <- optional $ strOption cmdrun <- behaviorOption
( long "message_cmd_run_stdout" ( long "cmd_run"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd run` behavior"
"The appearance of this character string in the cmd run stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdRunOut <> value cmdrun
) )
messageCmdRunErr <- optional $ strOption cmdlisten <- behaviorOption
( long "message_cmd_run_stderr" ( long "cmd_listen"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd listen` behavior"
"The appearance of this character string in the cmd run stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdRunErr <> value cmdlisten
) )
messageCmdListenOut <- optional $ strOption cmdlistenprogress <- behaviorOption
( long "message_cmd_listen_stdout" ( long "cmd_listen_progress"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd listen --filter progress` behavior"
"The appearance of this character string in the cmd listen stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdListenOut <> value cmdlistenprogress
) )
messageCmdListenErr <- optional $ strOption cmdlistenpower <- behaviorOption
( long "message_cmd_listen_stderr" ( long "cmd_listen_power"
<> metavar "STRING" <> metavar "BEHAVIOR"
<> help <> help "`cmd listen --filter power` behavior"
"The appearance of this character string in the cmd listen stdout \
\ will be monitored during execution. When observed, the \
\ stack will be killed and a return code of 0 will be returned."
<> showDefault <> showDefault
<> maybe mempty value messageCmdListenErr <> value cmdlistenpower
) )
pure StackArgs {..} pure StackArgs {..}
This diff is collapsed.
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
module Argo.Utils where module Argo.Utils where
import Argo.Args
import Turtle import Turtle
import Prelude hiding ( FilePath ) import Prelude hiding ( FilePath )
import System.Console.ANSI import System.Console.ANSI
...@@ -37,7 +38,7 @@ printCommand = printf ("Running: " % s % "\n") ...@@ -37,7 +38,7 @@ printCommand = printf ("Running: " % s % "\n")
printWarning = colorShell Yellow . printf ("Warning: " % s) printWarning = colorShell Yellow . printf ("Warning: " % s)
printError = colorShell Red . printf ("Error: " % s) printError = colorShell Red . printf ("Error: " % s)
printSuccess = colorShell Green . printf ("Success: " % s) printSuccess = colorShell Green . printf ("Success: " % s)
printTest = colorShell Green . printf ("RUNNING TEST: " % s%"\n") printTest = colorShell Green . printf ("RUNNING TEST: " % s % "\n")
dieRed str = dieRed str =
colorShell Red (printf ("Failure: " % s) str) >> exit (ExitFailure 1) colorShell Red (printf ("Failure: " % s) str) >> exit (ExitFailure 1)
...@@ -60,7 +61,7 @@ sudoRemoveFile printer desc filePath = do ...@@ -60,7 +61,7 @@ sudoRemoveFile printer desc filePath = do
go useSudo = do go useSudo = do
printer $ format ("found stale " % s % " at " % fp % ".. ") desc filePath printer $ format ("found stale " % s % " at " % fp % ".. ") desc filePath
shell shell
(format ((if useSudo then "sudo " else "") % "rm -f " % fp) filePath) (format ((if useSudo then "sudo " else "") % "rm -rf " % fp) filePath)
Turtle.empty Turtle.empty
>>= \case >>= \case
ExitSuccess -> colorShell Green $ printf " Successfully removed.\n" ExitSuccess -> colorShell Green $ printf " Successfully removed.\n"
...@@ -82,36 +83,36 @@ verboseShell' command input = ...@@ -82,36 +83,36 @@ verboseShell' command input =
printCommand command >> shellStrictWithErr command input printCommand command >> shellStrictWithErr command input
cleanSocket = sudoRemoveFile printError "socket" cleanSocket = sudoRemoveFile printError "socket"
cleanLog = sudoRemoveFile printWarning "log file" cleanLog = sudoRemoveFile printWarning "log folder"
kbInstallHandler :: IO () -> IO Handler kbInstallHandler :: IO () -> IO Handler
kbInstallHandler h = installHandler keyboardSignal (Catch h) Nothing kbInstallHandler h = installHandler keyboardSignal (Catch h) Nothing
data PatternMatched = PatternMatched deriving (Show, Typeable) data PatternMatched = PatternMatched deriving (Show, Typeable)
instance Exception PatternMatched instance Exception PatternMatched
data Instrumentation = Instrumentation data Instrumentation = Instrumentation
{ process :: CreateProcess CreateProcess
, stdOutFile :: FilePath StdOutLog
, stdErrFile :: FilePath StdErrLog
, messageOut :: Maybe Text (Maybe TestText)
, messageErr :: Maybe Text } deriving (Show) deriving (Show)
runI :: Instrumentation -> IO (Either PatternMatched (ExitCode, (), ())) runI :: Instrumentation -> IO (Either PatternMatched (ExitCode, (), ()))
runI Instrumentation {..} = try (reroutedDaemon process) runI (Instrumentation cp outlog@(StdOutLog out) errlog@(StdErrLog err) t) = try
(reroutedDaemon cp)
where where
reroutedDaemon process = reroutedDaemon process =
withSinkFile (encodeString stdOutFile) $ \outSink -> withSinkFile (T.unpack out)
withSinkFile (encodeString stdErrFile) $ \outSink ->
$ \errSink -> sourceProcessWithStreams withSinkFile (T.unpack err) $ \errSink -> sourceProcessWithStreams
process process
mempty mempty
(makeMatcher messageOut .| outSink) (makeMatcher t .| outSink)
(makeMatcher messageErr .| errSink) (makeMatcher t .| errSink)
makeMatcher maybeMessage = case maybeMessage of makeMatcher maybeMessage = case maybeMessage of
Just msg -> untilMatch msg Just (TestText msg) -> untilMatch msg
Nothing -> awaitForever yield Nothing -> awaitForever yield
untilMatch :: Text -> ConduitT ByteString ByteString IO () untilMatch :: Text -> ConduitT ByteString ByteString IO ()
untilMatch message = do untilMatch message = do
inb <- await inb <- await
...@@ -122,3 +123,9 @@ runI Instrumentation {..} = try (reroutedDaemon process) ...@@ -122,3 +123,9 @@ runI Instrumentation {..} = try (reroutedDaemon process)
yield b yield b
untilMatch message untilMatch message
_ -> return () _ -> return ()
processBehaviorToI :: CreateProcess -> ProcessBehavior -> Maybe Instrumentation
processBehaviorToI cp = \case
DontRun -> Nothing
JustRun out err -> Just $ Instrumentation cp out err Nothing
SucceedTestOnMessage t out err -> Just $ Instrumentation cp out err (Just t)
...@@ -16,7 +16,7 @@ executable argotk ...@@ -16,7 +16,7 @@ executable argotk
main-is: argotk.hs main-is: argotk.hs
-- other-modules: -- other-modules:
-- other-extensions: -- other-extensions:
build-depends: base, shake build-depends: base, shake, argo, turtle, data-default, async, unix, text, optparse-applicative, foldl, ansi-terminal
--hs-source-dirs: src --hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010
GHC-Options: -Wall GHC-Options: -Wall
This diff is collapsed.
...@@ -18,6 +18,7 @@ let ...@@ -18,6 +18,7 @@ let
hpkgs = pkgs.haskellPackages.override { hpkgs = pkgs.haskellPackages.override {
overrides = self: super: rec { overrides = self: super: rec {
argo = self.callCabal2nix "argo" (filterHdevTools ./argo) {}; argo = self.callCabal2nix "argo" (filterHdevTools ./argo) {};
argotk = self.callCabal2nix "argotk" (filterHdevTools ./argotk) {};
}; };
}; };
...@@ -49,17 +50,23 @@ in rec ...@@ -49,17 +50,23 @@ in rec
amg = pkgs.applications.nrm.amg; amg = pkgs.applications.nrm.amg;
inherit(hpkgs) argo; inherit(hpkgs) argo argotk;
dev-lib = hpkgs.shellFor { hack-argo = hpkgs.shellFor {
packages = p: with p; [ argo ]; packages = p: with p; [ argo ];
withHoogle = true; withHoogle = true;
buildInputs = devInputs ++ devHPackages; buildInputs = devInputs ++ devHPackages;
}; };
hack-argotk = hpkgs.shellFor {
packages = p: with p; [ argotk ];
withHoogle = true;
buildInputs = devInputs ++ devHPackages;
};
manifests = ./manifests; manifests = ./manifests;
argotk = pkgs.stdenv.mkDerivation rec { argotkp = pkgs.stdenv.mkDerivation rec {
name = "env"; name = "env";
env = pkgs.buildEnv { name = name; paths = buildInputs ++ propagatedBuildInputs; }; env = pkgs.buildEnv { name = name; paths = buildInputs ++ propagatedBuildInputs; };
src = filterHdevTools ./argotk; src = filterHdevTools ./argotk;
...@@ -84,7 +91,7 @@ in rec ...@@ -84,7 +91,7 @@ in rec
name = "env"; name = "env";
env = pkgs.buildEnv { name = name; paths = buildInputs; }; env = pkgs.buildEnv { name = name; paths = buildInputs; };
buildInputs = [ buildInputs = [
argotk argotkp
pkgs.coreutils pkgs.coreutils
pkgs.utillinux pkgs.utillinux
containers containers
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment