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
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
74 instance Default Args where
125 allOptions :: [(String, OptDescr (Args -> Args))]
132 (\s o -> o {bindings = (currentExchange o, s) : (bindings o)})
134 ("AMQP binding key (default: #)"))
142 { fileProcess = Just (fromMaybe callback s)
143 , tempDir = Just (fromMaybe "/tmp" (tempDir o))
146 ("Callback Script File (implies -t) (-X without arg: " ++
152 (ReqArg (\s o -> o {additionalArgs = s : (additionalArgs o)}) "ARG")
153 "additional argument for -X callback")
157 ["tempdir", "target"]
158 (OptArg (\s o -> o {tempDir = Just (fromMaybe "/tmp" s)}) "DIR")
159 "tempdir (default: no file creation, -t without arg: /tmp)")
164 (ReqArg (\s o -> o {preFetch = read s}) "INT")
165 ("Prefetch count. (0=unlimited, 1=off, default: " ++
166 show (preFetch def) ++ ")"))
171 (NoArg (\o -> o {ack = not (ack o)}))
172 ("Toggle ack messages (default: " ++ show (ack def) ++ ")"))
177 (NoArg (\o -> o {requeuenack = not (requeuenack o)}))
178 ("Toggle requeue when rejected (default: " ++
179 show (requeuenack def) ++ ")"))
184 (ReqArg (\s o -> o {rKey = s}) "ROUTINGKEY")
190 (ReqArg (\s o -> o {inputFile = s}) "INPUTFILE")
191 ("Message input file (default: " ++ (inputFile def) ++ ")"))
196 (ReqArg (\s o -> o {outputFile = s}) "OUTPUTFILE")
197 ("Message output file (default: " ++ (outputFile def) ++ ")"))
202 (NoArg (\o -> o {lineMode = not (lineMode o)}))
203 ("Toggle line-by-line mode (default: " ++ show (lineMode def) ++ ")"))
208 (NoArg (\o -> o {confirm = not (confirm o)}))
209 ("Toggle confirms (default: " ++ show (confirm def) ++ ")"))
214 (ReqArg (\s o -> o {msgid = Just $ pack s}) "ID")
220 (ReqArg (\s o -> o {msgtype = Just $ pack s}) "TYPE")
226 (ReqArg (\s o -> o {userid = Just $ pack s}) "USERID")
232 (ReqArg (\s o -> o {appid = Just $ pack s}) "APPID")
238 (ReqArg (\s o -> o {clusterid = Just $ pack s}) "CLUSTERID")
239 "Message Cluster-ID")
244 (ReqArg (\s o -> o {contenttype = Just $ pack s}) "CONTENTTYPE")
245 "Message Content-Type")
250 (ReqArg (\s o -> o {contentencoding = Just $ pack s}) "CONTENTENCODING")
251 "Message Content-Encoding")
256 (ReqArg (\s o -> o {replyto = Just $ pack s}) "REPLYTO")
262 (ReqArg (\s o -> o {rpc_timeout = read s}) "SECONDS")
263 ("How long to wait for reply (default: " ++
264 show (rpc_timeout def) ++ ")"))
269 (ReqArg (\s o -> o {prio = Just $ read s}) "PRIO")
275 (ReqArg (\s o -> o {corrid = Just $ pack s}) "CORRID")
276 "Message CorrelationID")
281 (ReqArg (\s o -> o {msgexp = Just $ pack s}) "EXP")
282 "Message Expiration")
288 (\s o -> o {msgheader = addheader (msgheader o) s})
295 (ReqArg (\s o -> o {fnheader = s : (fnheader o)}) "HEADERNAME")
296 "Put filename into this header")
301 (ReqArg (\s o -> o {suffix = s : (suffix o)}) "SUFFIX")
302 "Allowed file suffixes in hotfolder mode")
307 (NoArg (\o -> o {magic = not (magic o)}))
308 ("Toggle setting content-type and -encoding from file contents (default: " ++
309 show (magic def) ++ ")"))
314 (NoArg (\o -> o {persistent = Just Persistent}))
315 "Set persistent delivery")
320 (NoArg (\o -> o {persistent = Just NonPersistent}))
321 "Set nonpersistent delivery")
326 (ReqArg (\s o -> o {anRiss = Just (read s)}) "INT")
327 "limit number of shown body chars (default: unlimited)")
332 (ReqArg (\s o -> o {qName = Just s}) "QUEUENAME")
333 "Ignore Exchange and bind to existing Queue")
339 (\o -> o {simple = True, cleanupTmpFile = not (cleanupTmpFile o)}))
340 "call callback with one arg (filename) only")
345 (NoArg (\o -> o {cleanupTmpFile = not (cleanupTmpFile o)}))
346 "Toggle remove tempfile after script call. Default False, but default True if --simple (-i)")
351 (ReqArg (\s o -> o {tmpQName = s}) "TEMPQNAME")
352 "Name for temporary exclusive Queue")
357 (ReqArg (\s o -> o {currentExchange = s}) "EXCHANGE")
358 ("AMQP Exchange (default: \"\")"))
363 (ReqArg (\s o -> o {server = s}) "SERVER")
364 ("AMQP Server (default: " ++ server def ++ ")"))
369 (ReqArg (\s o -> o {vHost = s}) "VHOST")
370 ("AMQP Virtual Host (default: " ++ vHost def ++ ")"))
375 (ReqArg (\s o -> o {port = Just (read s)}) "PORT")
376 ("Server Port Number (default: " ++ show (portnumber def) ++ ")"))
381 (NoArg (\o -> o {tls = not (tls o)}))
382 ("Toggle TLS (default: " ++ show (tls def) ++ ")"))
387 (ReqArg (\s o -> o {cert = Just s}) "CERTFILE")
388 ("TLS Client Certificate File"))
393 (ReqArg (\s o -> o {key = Just s}) "KEYFILE")
394 ("TLS Client Private Key File"))
399 (ReqArg (\s o -> o {user = s}) "USERNAME")
400 ("Username for Auth"))
405 (ReqArg (\s o -> o {pass = s}) "PASSWORD")
406 ("Password for Auth"))
411 (ReqArg (\s o -> o {heartBeat = (Just (read s))}) "INT")
412 "heartbeat interval (0=disable, default: set by server)")
417 (ReqArg (\s o -> o {connectionName = Just s}) "NAME")
418 "connection name, will be shown in RabbitMQ web interface")
423 (ReqArg (\s o -> o {connect_timeout = read s}) "SECONDS")
424 ("timeout for establishing initial connection (default: " ++
425 show (connect_timeout def) ++ ")"))
428 -- | Options for the executables
429 options :: Char -> [OptDescr (Args -> Args)]
430 options exename = map snd $ filter ((elem exename) . fst) allOptions
432 -- | Add a header with a String value
433 addheader :: Maybe FieldTable -> String -> Maybe FieldTable
434 addheader Nothing string =
435 Just $ FieldTable $ M.singleton (getkey string) (getval string)
436 addheader (Just (FieldTable oldheader)) string =
437 Just $ FieldTable $ M.insert (getkey string) (getval string) oldheader
439 getkey :: String -> Text
440 getkey s = pack $ takeWhile (/= '=') s
442 getval :: String -> FieldValue
443 getval s = FVString $ BS.pack $ tail $ dropWhile (/= '=') s
445 -- | 'parseargs' exename argstring
446 -- applies options onto argstring
447 parseargs :: Char -> [String] -> IO Args
448 parseargs exename argstring =
449 case getOpt Permute opt argstring of
450 (o, [], []) -> return $ foldl (flip id) def o
452 ioError $ userError $ concat errs ++ usageInfo (usage exename) opt
454 opt = options exename
456 -- | the default callback for the -X option
458 callback = "/usr/lib/haskell-amqp-utils/callback"
460 usage :: Char -> String
464 (showVersion version) ++
467 (longname exename) ++
471 longname :: Char -> String
472 longname 'a' = "agitprop"
473 longname 'k' = "konsum"
474 longname 'r' = "arbeite"
475 longname 'p' = "plane"
476 longname _ = "command"