Revision 22278fa7

b/htest/Test/Ganeti/Common.hs
64 64
    cmdarg:_ ->
65 65
      case parseOptsInner defaults
66 66
             ["--" ++ cmdarg ++ maybe "" ("=" ++) (repr val)]
67
             "prog" [opt] of
67
             "prog" [opt] [] of
68 68
        Left e -> failfn $ "Failed to parse option '" ++ cmdarg ++ ": " ++
69 69
                  show e
70 70
        Right (options, _) -> eqcheck ("Wrong value in option " ++
......
83 83
  let prefix = "--" ++ head longs ++ "="
84 84
      good_cmd = prefix ++ good
85 85
      bad_cmd = prefix ++ bad in
86
  case (parseOptsInner defaults [bad_cmd]  "prog" [opt],
87
        parseOptsInner defaults [good_cmd] "prog" [opt]) of
86
  case (parseOptsInner defaults [bad_cmd]  "prog" [opt] [],
87
        parseOptsInner defaults [good_cmd] "prog" [opt] []) of
88 88
    (Left _,  Right _) -> passfn
89 89
    (Right _, Right _) -> failfn $ "Command line '" ++ bad_cmd ++
90 90
                          "' succeeded when it shouldn't"
......
97 97

  
98 98
-- | Helper to test that a given option is accepted OK with quick exit.
99 99
checkEarlyExit :: (StandardOptions a) =>
100
                  a -> String -> [GenericOptType a] -> Assertion
101
checkEarlyExit defaults name options =
100
                  a -> String -> [GenericOptType a] -> [ArgCompletion]
101
               -> Assertion
102
checkEarlyExit defaults name options arguments =
102 103
  mapM_ (\param ->
103
           case parseOptsInner defaults [param] name options of
104
           case parseOptsInner defaults [param] name options arguments of
104 105
             Left (code, _) ->
105 106
               assertEqual ("Program " ++ name ++
106 107
                            " returns invalid code " ++ show code ++
b/htest/Test/Ganeti/Daemon.hs
76 76
-- | Test that the option list supports some common options.
77 77
case_stdopts :: Assertion
78 78
case_stdopts =
79
  checkEarlyExit defaultOptions "prog" [oShowHelp, oShowVer]
79
  checkEarlyExit defaultOptions "prog" [oShowHelp, oShowVer] []
80 80

  
81 81
testSuite "Daemon"
82 82
          [ 'prop_string_arg
b/htest/Test/Ganeti/HTools/CLI.hs
118 118
-- | Test that all binaries support some common options.
119 119
case_stdopts :: Assertion
120 120
case_stdopts =
121
  mapM_ (\(name, (_, o)) -> checkEarlyExit defaultOptions name
122
                            (o ++ genericOpts)) Program.personalities
121
  mapM_ (\(name, (_, o, a)) -> checkEarlyExit defaultOptions name
122
                               (o ++ genericOpts) a) Program.personalities
123 123

  
124 124
testSuite "HTools/CLI"
125 125
          [ 'prop_parseISpec
b/htools/Ganeti/Common.hs
183 183
          -> [String]               -- ^ The command line arguments
184 184
          -> String                 -- ^ The program name
185 185
          -> [GenericOptType a]     -- ^ The supported command line options
186
          -> [ArgCompletion]        -- ^ The supported command line arguments
186 187
          -> IO (a, [String])       -- ^ The resulting options and
187 188
                                    -- leftover arguments
188
parseOpts defaults argv progname options =
189
  case parseOptsInner defaults argv progname options of
189
parseOpts defaults argv progname options arguments =
190
  case parseOptsInner defaults argv progname options arguments of
190 191
    Left (code, msg) -> do
191 192
      hPutStr (if code == ExitSuccess then stdout else stderr) msg
192 193
      exitWith code
......
201 202
               -> [String]
202 203
               -> String
203 204
               -> [GenericOptType a]
205
               -> [ArgCompletion]
204 206
               -> Either (ExitCode, String) (a, [String])
205
parseOptsInner defaults argv progname options  =
207
parseOptsInner defaults argv progname options arguments  =
206 208
  case getOpt Permute (map fst options) argv of
207 209
    (opts, args, []) ->
208 210
      case foldM (flip id) defaults opts of
......
216 218
                 , (verRequested parsed,
217 219
                    Left (ExitSuccess, versionInfo progname))
218 220
                 , (compRequested parsed,
219
                    Left (ExitSuccess, completionInfo progname options []))
221
                    Left (ExitSuccess, completionInfo progname options
222
                                         arguments))
220 223
                 ]
221 224
    (_, _, errs) ->
222 225
      Left (ExitFailure 2, "Command line error: "  ++ concat errs ++ "\n" ++
b/htools/Ganeti/Daemon.hs
176 176
parseArgs :: String -> [OptType] -> IO (DaemonOptions, [String])
177 177
parseArgs cmd options = do
178 178
  cmd_args <- getArgs
179
  parseOpts defaultOptions cmd_args cmd $ options ++ genericOpts
179
  parseOpts defaultOptions cmd_args cmd (options ++ genericOpts) []
180 180

  
181 181
-- * Daemon-related functions
182 182
-- | PID file mode.
b/htools/Ganeti/HTools/CLI.hs
526 526
parseOpts :: [String]               -- ^ The command line arguments
527 527
          -> String                 -- ^ The program name
528 528
          -> [OptType]              -- ^ The supported command line options
529
          -> [ArgCompletion]        -- ^ The supported command line arguments
529 530
          -> IO (Options, [String]) -- ^ The resulting options and leftover
530 531
                                    -- arguments
531 532
parseOpts = Common.parseOpts defaultOptions
b/htools/Ganeti/HTools/Program.hs
27 27
  ( personalities
28 28
  ) where
29 29

  
30
import Ganeti.Common (ArgCompletion)
30 31
import Ganeti.HTools.CLI (OptType, Options)
31 32

  
32 33
import qualified Ganeti.HTools.Program.Hail as Hail
......
37 38
import qualified Ganeti.HTools.Program.Hinfo as Hinfo
38 39

  
39 40
-- | Supported binaries.
40
personalities :: [(String, (Options -> [String] -> IO (), [OptType]))]
41
personalities = [ ("hail",   (Hail.main,   Hail.options))
42
                , ("hbal",   (Hbal.main,   Hbal.options))
43
                , ("hcheck", (Hcheck.main, Hcheck.options))
44
                , ("hscan",  (Hscan.main,  Hscan.options))
45
                , ("hspace", (Hspace.main, Hspace.options))
46
                , ("hinfo",  (Hinfo.main,  Hinfo.options))
41
personalities :: [(String,
42
                   (Options -> [String] -> IO (), [OptType], [ArgCompletion]))]
43
personalities = [ ("hail",   (Hail.main,   Hail.options,   Hail.arguments))
44
                , ("hbal",   (Hbal.main,   Hbal.options,   Hbal.arguments))
45
                , ("hcheck", (Hcheck.main, Hcheck.options, Hcheck.arguments))
46
                , ("hscan",  (Hscan.main,  Hscan.options,  Hscan.arguments ))
47
                , ("hspace", (Hspace.main, Hspace.options, Hspace.arguments))
48
                , ("hinfo",  (Hinfo.main,  Hinfo.options,  Hinfo.arguments))
47 49
                ]
b/htools/Ganeti/HTools/Program/Hail.hs
23 23

  
24 24
-}
25 25

  
26
module Ganeti.HTools.Program.Hail (main, options) where
26
module Ganeti.HTools.Program.Hail
27
  ( main
28
  , options
29
  , arguments
30
  ) where
27 31

  
28 32
import Control.Monad
29 33
import Data.Maybe (fromMaybe, isJust)
......
32 36

  
33 37
import qualified Ganeti.HTools.Cluster as Cluster
34 38

  
39
import Ganeti.Common
35 40
import Ganeti.HTools.CLI
36 41
import Ganeti.HTools.IAlloc
37 42
import Ganeti.HTools.Loader (Request(..), ClusterData(..))
......
47 52
  , oVerbose
48 53
  ]
49 54

  
55
-- | The list of arguments supported by the program.
56
arguments :: [ArgCompletion]
57
arguments = [ArgCompletion OptComplFile 1 (Just 1)]
58

  
50 59
wrapReadRequest :: Options -> [String] -> IO Request
51 60
wrapReadRequest opts args = do
52 61
  when (null args) $ do
b/htools/Ganeti/HTools/Program/Hbal.hs
24 24
-}
25 25

  
26 26
module Ganeti.HTools.Program.Hbal
27
    ( main
28
    , options
29
    , iterateDepth
30
    ) where
27
  ( main
28
  , options
29
  , arguments
30
  , iterateDepth
31
  ) where
31 32

  
32 33
import Control.Concurrent (threadDelay)
33 34
import Control.Exception (bracket)
......
48 49
import qualified Ganeti.HTools.Node as Node
49 50
import qualified Ganeti.HTools.Instance as Instance
50 51

  
52
import Ganeti.Common
51 53
import Ganeti.HTools.CLI
52 54
import Ganeti.HTools.ExtLoader
53 55
import Ganeti.HTools.Types
......
88 90
  , oSaveCluster
89 91
  ]
90 92

  
93
-- | The list of arguments supported by the program.
94
arguments :: [ArgCompletion]
95
arguments = []
96

  
91 97
{- | Start computing the solution at the given depth and recurse until
92 98
we find a valid solution or we exceed the maximum depth.
93 99

  
b/htools/Ganeti/HTools/Program/Hcheck.hs
23 23

  
24 24
-}
25 25

  
26
module Ganeti.HTools.Program.Hcheck (main, options) where
26
module Ganeti.HTools.Program.Hcheck
27
  ( main
28
  , options
29
  , arguments
30
  ) where
27 31

  
28 32
import Control.Monad
29 33
import Data.List (transpose)
......
39 43

  
40 44
import qualified Ganeti.HTools.Program.Hbal as Hbal
41 45

  
46
import Ganeti.Common
42 47
import Ganeti.HTools.CLI
43 48
import Ganeti.HTools.ExtLoader
44 49
import Ganeti.HTools.Loader
......
71 76
  , oVerbose
72 77
  ]
73 78

  
79
-- | The list of arguments supported by the program.
80
arguments :: [ArgCompletion]
81
arguments = []
82

  
74 83
-- | Check phase - are we before (initial) or after rebalance.
75 84
data Phase = Initial
76 85
           | Rebalanced
b/htools/Ganeti/HTools/Program/Hinfo.hs
23 23

  
24 24
-}
25 25

  
26
module Ganeti.HTools.Program.Hinfo (main, options) where
26
module Ganeti.HTools.Program.Hinfo
27
  ( main
28
  , options
29
  , arguments
30
  ) where
27 31

  
28 32
import Control.Monad
29 33
import Data.List
......
38 42
import qualified Ganeti.HTools.Group as Group
39 43
import qualified Ganeti.HTools.Instance as Instance
40 44

  
45
import Ganeti.Common
41 46
import Ganeti.HTools.CLI
42 47
import Ganeti.HTools.ExtLoader
43 48
import Ganeti.HTools.Loader
......
57 62
  , oOfflineNode
58 63
  ]
59 64

  
65
-- | The list of arguments supported by the program.
66
arguments :: [ArgCompletion]
67
arguments = []
68

  
60 69
-- | Group information data-type.
61 70
data GroupInfo = GroupInfo { giName      :: String
62 71
                           , giNodeCount :: Int
b/htools/Ganeti/HTools/Program/Hscan.hs
23 23

  
24 24
-}
25 25

  
26
module Ganeti.HTools.Program.Hscan (main, options) where
26
module Ganeti.HTools.Program.Hscan
27
  ( main
28
  , options
29
  , arguments
30
  ) where
27 31

  
28 32
import Control.Monad
29 33
import Data.Maybe (isJust, fromJust, fromMaybe)
......
43 47
import Ganeti.HTools.Loader (checkData, mergeData, ClusterData(..))
44 48
import Ganeti.HTools.Text (serializeCluster)
45 49

  
50
import Ganeti.Common
46 51
import Ganeti.HTools.CLI
47 52
import Ganeti.HTools.Types
48 53

  
......
56 61
  , oNoHeaders
57 62
  ]
58 63

  
64
-- | The list of arguments supported by the program.
65
arguments :: [ArgCompletion]
66
arguments = [ArgCompletion OptComplHost 0 Nothing]
67

  
59 68
-- | Return a one-line summary of cluster state.
60 69
printCluster :: Node.List -> Instance.List
61 70
             -> String
b/htools/Ganeti/HTools/Program/Hspace.hs
23 23

  
24 24
-}
25 25

  
26
module Ganeti.HTools.Program.Hspace (main, options) where
26
module Ganeti.HTools.Program.Hspace
27
  (main
28
  , options
29
  , arguments
30
  ) where
27 31

  
28 32
import Control.Monad
29 33
import Data.Char (toUpper, toLower)
......
40 44
import qualified Ganeti.HTools.Node as Node
41 45
import qualified Ganeti.HTools.Instance as Instance
42 46

  
47
import Ganeti.Common
43 48
import Ganeti.HTools.Types
44 49
import Ganeti.HTools.CLI
45 50
import Ganeti.HTools.ExtLoader
......
69 74
  , oSaveCluster
70 75
  ]
71 76

  
77
-- | The list of arguments supported by the program.
78
arguments :: [ArgCompletion]
79
arguments = []
80

  
72 81
-- | The allocation phase we're in (initial, after tiered allocs, or
73 82
-- after regular allocation).
74 83
data Phase = PInitial
b/htools/htools.hs
57 57
      boolnames = map (\(x, y) -> (x == name, Just y)) personalities
58 58
  case select Nothing boolnames of
59 59
    Nothing -> usage name
60
    Just (fn, options) -> do
60
    Just (fn, options, arguments) -> do
61 61
         cmd_args <- getArgs
62
         (opts, args) <- parseOpts cmd_args name $ options ++ genericOpts
62
         (opts, args) <- parseOpts cmd_args name (options ++ genericOpts)
63
                           arguments
63 64
         fn opts args

Also available in: Unified diff