Revision 9ba5c28f Ganeti/HTools/IAlloc.hs

b/Ganeti/HTools/IAlloc.hs
16 16
import Ganeti.HTools.Utils ()
17 17

  
18 18

  
19
-- Some constants
20

  
21
{-- Our cheap monad-like stuff.
22

  
23
Thi is needed since Either e a is already a monad instance somewhere
24
in the standard libraries (Control.Monad.Error) and we don't need that
25
entire thing.
26

  
27
-}
28
combine :: (Either String a) -> (a -> Either String b)  -> (Either String b)
29
combine (Left s) _ = Left s
30
combine (Right s) f = f s
31

  
32
ensureList :: [Either String a] -> Either String [a]
33
ensureList lst =
34
    foldr (\elem accu ->
35
               case (elem, accu) of
36
                 (Left x, _) -> Left x
37
                 (_, Left x) -> Left x -- should never happen
38
                 (Right e, Right a) -> Right (e:a)
39
          )
40
    (Right []) lst
41

  
42
listHead :: Either String [a] -> Either String a
43
listHead lst =
44
    case lst of
45
      Left x -> Left x
46
      Right (x:_) -> Right x
47
      Right [] -> Left "List empty"
48

  
49
loadJSArray :: String -> Either String [JSObject JSValue]
50
loadJSArray s = resultToEither $ decodeStrict s
51

  
52
fromObj :: JSON a => String -> JSObject JSValue -> Either String a
53
fromObj k o =
54
    case lookup k (fromJSObject o) of
55
      Nothing -> Left $ printf "key '%s' not found" k
56
      Just val -> resultToEither $ readJSON val
57

  
58
getStringElement :: String -> JSObject JSValue -> Either String String
59
getStringElement = fromObj
60

  
61
getIntElement :: String -> JSObject JSValue -> Either String Int
62
getIntElement = fromObj
63

  
64
getListElement :: String -> JSObject JSValue
65
               -> Either String [JSValue]
66
getListElement = fromObj
67

  
68
readString :: JSValue -> Either String String
69
readString v =
70
    case v of
71
      JSString s -> Right $ fromJSString s
72
      _ -> Left "Wrong JSON type"
73

  
74
concatElems :: Either String String
75
            -> Either String String
76
            -> Either String String
77
concatElems = apply2 (\x y -> x ++ "|" ++ y)
78

  
79
apply1 :: (a -> b) -> Either String a -> Either String b
80
apply1 fn a =
81
    case a of
82
      Left x -> Left x
83
      Right y -> Right $ fn y
84

  
85
apply2 :: (a -> b -> c)
86
       -> Either String a
87
       -> Either String b
88
       -> Either String c
89
apply2 fn a b =
90
    case (a, b) of
91
      (Right x, Right y) -> Right $ fn x y
92
      (Left x, _) -> Left x
93
      (_, Left y) -> Left y
94

  
95
parseList :: (JSObject JSValue -> Either String String)
96
          -> [JSObject JSValue]
97
          ->Either String String
98
parseList fn idata =
99
    let ml = ensureList $ map fn idata
100
    in ml `combine` (Right . unlines)
101

  
102 19
parseInstance :: JSObject JSValue -> Either String String
103 20
parseInstance a =
104 21
    let name = getStringElement "name" a

Also available in: Unified diff