{-#LANGUAGE OverloadedStrings#-}
{-#LANGUAGE TemplateHaskell#-}
{-#LANGUAGE QuasiQuotes#-}
{-#LANGUAGE ExtendedDefaultRules #-}
{-#LANGUAGE RecordWildCards #-}
{-#LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
import Prelude hiding (FilePath)
import Shelly hiding (command)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Data.Monoid
import Options.Applicative
import qualified Data.Yaml as Y
import Network.Builder
default (T.Text)
data Command
= Create String
| Destroy String
| Show String
| CreateTunnel String
| DestroyTunnel String
| ShowTunnel String
create :: Parser Command
create = Create
<$> option str (long "conf" <> value "network-builder.yml" <> metavar "CONFILE")
destroy :: Parser Command
destroy = Destroy
<$> option str (long "conf" <> value "network-builder.yml" <> metavar "CONFILE")
createTun :: Parser Command
createTun = CreateTunnel
<$> argument str (metavar "TUNNELFILE")
destroyTun :: Parser Command
destroyTun = DestroyTunnel
<$> argument str (metavar "TUNNELFILE")
showTun :: Parser Command
showTun = ShowTunnel
<$> argument str (metavar "TUNNELFILE")
showYaml :: Parser Command
showYaml = Show
<$> option auto (long "conf" <> value "network-builder.yml" <> metavar "CONFILE")
parse :: Parser Command
parse = subparser $
command "create" (info create (progDesc "create linux-network-namespaces")) <>
command "destroy" (info destroy (progDesc "destroy linux-network-namespaces")) <>
command "show" (info showYaml (progDesc "show decoded yaml-conf")) <>
command "create-tunnel" (info createTun (progDesc "create tunnel")) <>
command "destroy-tunnel" (info destroyTun (progDesc "destroy tunnel")) <>
command "show-tunnel" (info showTun (progDesc "show tunnel"))
runCmd' :: String -> (HostServer -> Sh a) -> IO a
runCmd' file action' = shelly $ do
echo $ T.pack file
eyaml <- liftIO $ Y.decodeFileEither file
case eyaml of
Right conf -> action' conf
Left err -> do
echo $ T.pack $ show err
exit 1
runCmd'' :: String
-> (NetworkNameSpace -> Tunnel -> Sh a)
-> (HostServer -> Tunnel -> Sh a)
-> IO a
runCmd'' file act0 act1 = shelly $ do
eyaml <- liftIO $ Y.decodeFileEither file :: Sh (Either Y.ParseException (NetworkNameSpace,Tunnel))
case eyaml of
Right (netconf,tunnelconf) -> act0 netconf tunnelconf
Left _err -> do
eyaml' <- liftIO $ Y.decodeFileEither file :: Sh (Either Y.ParseException (HostServer,Tunnel))
case eyaml' of
Right (netconf,tunnelconf) -> act1 netconf tunnelconf
Left err -> do
echo $ T.pack $ show err
exit 1
runCmd :: Command -> IO ()
runCmd (Create file) = runCmd' file createNetworkNameSpaces
runCmd (Destroy file) = runCmd' file deleteNetworkNameSpaces
runCmd (Show file) = runCmd' file $ echo . T.pack . show
runCmd (CreateTunnel file) = runCmd'' file createTunnel createTunnel
runCmd (DestroyTunnel file) = runCmd'' file deleteTunnel deleteTunnel
runCmd (ShowTunnel file) = runCmd'' file
(\n t -> echo $ T.decodeUtf8 $ Y.encode (n,t))
(\n t -> echo $ T.decodeUtf8 $ Y.encode (n,t))
opts :: ParserInfo Command
opts = info (parse <**> helper) idm
main :: IO ()
main = execParser opts >>= runCmd