1 module Network.AMQP.Utils.Options where
3 import qualified Data.ByteString.Char8 as BS
4 import Data.Default.Class
5 import Data.Int (Int64)
6 import qualified Data.Map as M
8 import Data.Text (Text, pack)
9 import Data.Version (showVersion)
10 import Data.Word (Word16)
12 import Network.AMQP.Types
13 import Network.Socket (PortNumber)
14 import Paths_amqp_utils (version)
15 import System.Console.GetOpt
17 portnumber :: Args -> PortNumber
19 | (port a) == Nothing && (tls a) = 5671
20 | (port a) == Nothing = 5672
21 | otherwise = fromJust (port a)
23 -- | A data type for our options
27 , port :: Maybe PortNumber
30 , currentExchange :: String
31 , bindings :: [(String, String)]
33 , anRiss :: Maybe Int64
34 , fileProcess :: Maybe String
35 , qName :: Maybe String
36 , cert :: Maybe String
41 , heartBeat :: Maybe Word16
42 , tempDir :: Maybe String
43 , additionalArgs :: [String]
44 , connectionName :: Maybe String
46 , inputFiles :: [(String,String,String)]
47 , outputFile :: String
51 , msgtype :: Maybe Text
52 , userid :: Maybe Text
54 , clusterid :: Maybe Text
55 , contenttype :: Maybe Text
56 , contentencoding :: Maybe Text
57 , replyto :: Maybe Text
59 , corrid :: Maybe Text
60 , msgexp :: Maybe Text
61 , msgheader :: Maybe FieldTable
62 , fnheader :: [String]
65 , persistent :: Maybe DeliveryMode
68 , rpc_timeout :: Double
69 , connect_timeout :: Int
71 , cleanupTmpFile :: Bool
72 , removeSentFile :: Bool
73 , moveSentFileTo :: Maybe FilePath
77 instance Default Args where
131 allOptions :: [(String, OptDescr (Args -> Args))]
138 (\s o -> o {bindings = (currentExchange o, s) : (bindings o)})
140 ("AMQP binding key"))
148 { fileProcess = Just (fromMaybe callback s)
149 , tempDir = Just (fromMaybe "/tmp" (tempDir o))
152 ("Callback Script File (implies -t) (-X without arg: " ++
158 (ReqArg (\s o -> o {additionalArgs = s : (additionalArgs o)}) "ARG")
159 "additional argument for -X callback")
163 ["tempdir", "target"]
164 (OptArg (\s o -> o {tempDir = Just (fromMaybe "/tmp" s)}) "DIR")
165 "tempdir (default: no file creation, -t without arg: /tmp)")
170 (ReqArg (\s o -> o {preFetch = read s}) "INT")
171 ("Prefetch count. (0=unlimited, 1=off, default: " ++
172 show (preFetch def) ++ ")"))
177 (NoArg (\o -> o {ack = not (ack o)}))
178 ("Toggle ack messages (default: " ++ show (ack def) ++ ")"))
183 (NoArg (\o -> o {requeuenack = not (requeuenack o)}))
184 ("Toggle requeue when rejected (default: " ++
185 show (requeuenack def) ++ ")"))
190 (ReqArg (\s o -> o {rKey = s}) "ROUTINGKEY")
195 ["routingkey", "qname"]
196 (ReqArg (\s o -> o {rKey = s}) "ROUTINGKEY")
202 (ReqArg (\s o -> o {inputFiles = (s,currentExchange o,rKey o):(inputFiles o)}) "INPUTFILE")
203 ("Message input file (default: <stdin>)"))
208 (ReqArg (\s o -> o {outputFile = s}) "OUTPUTFILE")
209 ("Message output file (default: " ++ (outputFile def) ++ ")"))
214 (NoArg (\o -> o {lineMode = not (lineMode o)}))
215 ("Toggle line-by-line mode (default: " ++ show (lineMode def) ++ ")"))
220 (NoArg (\o -> o {confirm = not (confirm o)}))
221 ("Toggle confirms (default: " ++ show (confirm def) ++ ")"))
226 (ReqArg (\s o -> o {msgid = Just $ pack s}) "ID")
232 (ReqArg (\s o -> o {msgtype = Just $ pack s}) "TYPE")
238 (ReqArg (\s o -> o {userid = Just $ pack s}) "USERID")
244 (ReqArg (\s o -> o {appid = Just $ pack s}) "APPID")
250 (ReqArg (\s o -> o {clusterid = Just $ pack s}) "CLUSTERID")
251 "Message Cluster-ID")
256 (ReqArg (\s o -> o {contenttype = Just $ pack s}) "CONTENTTYPE")
257 "Message Content-Type")
262 (ReqArg (\s o -> o {contentencoding = Just $ pack s}) "CONTENTENCODING")
263 "Message Content-Encoding")
268 (ReqArg (\s o -> o {replyto = Just $ pack s}) "REPLYTO")
274 (ReqArg (\s o -> o {rpc_timeout = read s}) "SECONDS")
275 ("How long to wait for reply (default: " ++
276 show (rpc_timeout def) ++ ")"))
281 (ReqArg (\s o -> o {prio = Just $ read s}) "PRIO")
287 (ReqArg (\s o -> o {corrid = Just $ pack s}) "CORRID")
288 "Message CorrelationID")
293 (ReqArg (\s o -> o {msgexp = Just $ pack s}) "EXP")
294 "Message Expiration")
300 (\s o -> o {msgheader = addheader (msgheader o) s})
307 (ReqArg (\s o -> o {fnheader = s : (fnheader o)}) "HEADERNAME")
308 "Put filename into this header")
313 (ReqArg (\s o -> o {suffix = s : (suffix o)}) "SUFFIX")
314 "Allowed file suffixes in hotfolder mode")
319 (OptArg (\s o -> o {removeSentFile = True, moveSentFileTo = s}) "DIR")
320 ("Remove (or move to DIR) sent file in hotfolder mode"))
325 (NoArg (\o -> o {initialScan = not (initialScan o)}))
326 ("Toggle initial directory scan in hotfolder mode (default: " ++
327 show (initialScan def) ++ ")"))
332 (NoArg (\o -> o {magic = not (magic o)}))
333 ("Toggle setting content-type and -encoding from file contents (default: " ++
334 show (magic def) ++ ")"))
339 (NoArg (\o -> o {persistent = Just Persistent}))
340 "Set persistent delivery")
345 (NoArg (\o -> o {persistent = Just NonPersistent}))
346 "Set nonpersistent delivery")
351 (ReqArg (\s o -> o {anRiss = Just (read s)}) "INT")
352 "limit number of shown body chars (default: unlimited)")
357 (ReqArg (\s o -> o {qName = Just s}) "QUEUENAME")
358 "Ignore Exchange and bind to existing Queue")
364 (\o -> o {simple = True, cleanupTmpFile = not (cleanupTmpFile o)}))
365 "call callback with one arg (filename) only")
370 (NoArg (\o -> o {cleanupTmpFile = not (cleanupTmpFile o)}))
371 "Toggle remove tempfile after script call. Default False, but default True if --simple (-i)")
376 (ReqArg (\s o -> o {tmpQName = s}) "TEMPQNAME")
377 "Name for temporary exclusive Queue")
382 (ReqArg (\s o -> o {currentExchange = s}) "EXCHANGE")
383 ("AMQP Exchange (default: \"\")"))
388 (ReqArg (\s o -> o {server = s}) "SERVER")
389 ("AMQP Server (default: " ++ server def ++ ")"))
394 (ReqArg (\s o -> o {vHost = s}) "VHOST")
395 ("AMQP Virtual Host (default: " ++ vHost def ++ ")"))
400 (ReqArg (\s o -> o {port = Just (read s)}) "PORT")
401 ("Server Port Number (default: " ++ show (portnumber def) ++ ")"))
406 (NoArg (\o -> o {tls = not (tls o)}))
407 ("Toggle TLS (default: " ++ show (tls def) ++ ")"))
412 (ReqArg (\s o -> o {cert = Just s}) "CERTFILE")
413 ("TLS Client Certificate File"))
418 (ReqArg (\s o -> o {key = Just s}) "KEYFILE")
419 ("TLS Client Private Key File"))
424 (ReqArg (\s o -> o {user = s}) "USERNAME")
425 ("Username for Auth"))
430 (ReqArg (\s o -> o {pass = s}) "PASSWORD")
431 ("Password for Auth"))
436 (ReqArg (\s o -> o {heartBeat = (Just (read s))}) "INT")
437 "heartbeat interval (0=disable, default: set by server)")
442 (ReqArg (\s o -> o {connectionName = Just s}) "NAME")
443 "connection name, will be shown in RabbitMQ web interface")
448 (ReqArg (\s o -> o {connect_timeout = read s}) "SECONDS")
449 ("timeout for establishing initial connection (default: " ++
450 show (connect_timeout def) ++ ")"))
453 -- | Options for the executables
454 options :: Char -> [OptDescr (Args -> Args)]
455 options exename = map snd $ filter ((elem exename) . fst) allOptions
457 -- | Add a header with a String value
458 addheader :: Maybe FieldTable -> String -> Maybe FieldTable
459 addheader Nothing string =
460 Just $ FieldTable $ M.singleton (getkey string) (getval string)
461 addheader (Just (FieldTable oldheader)) string =
462 Just $ FieldTable $ M.insert (getkey string) (getval string) oldheader
464 getkey :: String -> Text
465 getkey s = pack $ takeWhile (/= '=') s
467 getval :: String -> FieldValue
468 getval s = FVString $ BS.pack $ tail $ dropWhile (/= '=') s
470 -- | 'parseargs' exename argstring
471 -- applies options onto argstring
472 parseargs :: Char -> [String] -> IO Args
473 parseargs exename argstring =
474 case getOpt Permute opt argstring of
475 (o, [], []) -> return $ foldl (flip id) def o
477 ioError $ userError $ concat errs ++ usageInfo (usage exename) opt
479 opt = options exename
481 -- | the default callback for the -X option
483 callback = "/usr/lib/haskell-amqp-utils/callback"
485 usage :: Char -> String
489 (showVersion version) ++
492 (longname exename) ++
496 longname :: Char -> String
497 longname 'a' = "agitprop"
498 longname 'k' = "konsum"
499 longname 'r' = "arbeite"
500 longname 'p' = "plane"
501 longname _ = "command"