Provide a special filter for host names
authorKlaus Aehlig <aehlig@google.com>
Fri, 21 Jun 2013 13:51:00 +0000 (15:51 +0200)
committerKlaus Aehlig <aehlig@google.com>
Mon, 24 Jun 2013 14:11:17 +0000 (16:11 +0200)
For host names, usually short forms are used, e.g., node1 or node1.sub
instead of the full qualified node1.sub.example.com. Therefore comparing
node names only by equality is too restrictive. This patch provides an
alternative makeHostnameFilter to makeSimpleFilter suitable for comparing
host names.

Signed-off-by: Klaus Aehlig <aehlig@google.com>
Reviewed-by: Guido Trotter <ultrotter@google.com>

src/Ganeti/Query/Filter.hs

index b4da138..acb1135 100644 (file)
@@ -48,12 +48,15 @@ module Ganeti.Query.Filter
   ( compileFilter
   , evaluateFilter
   , requestedNames
+  , FilterConstructor
   , makeSimpleFilter
+  , makeHostnameFilter
   ) where
 
 import Control.Applicative
 import Control.Monad (liftM)
 import qualified Data.Map as Map
+import Data.Maybe (fromJust)
 import Data.Traversable (traverse)
 import Text.JSON (JSValue(..), fromJSString)
 import Text.JSON.Pretty (pp_value)
@@ -215,8 +218,30 @@ requestedNames namefield (EQFilter fld val) =
     else Nothing
 requestedNames _ _ = Nothing
 
+
+type FilterConstructor = String -> [Either String Integer] -> Filter FilterField
+  
 -- | Builds a simple filter from a list of names.
 makeSimpleFilter :: String -> [Either String Integer] -> Filter FilterField
 makeSimpleFilter _ [] = EmptyFilter
 makeSimpleFilter namefield vals =
   OrFilter $ map (EQFilter namefield . either QuotedString NumericValue) vals
+
+-- | List of symbols with a special meaning for regular expressions.
+reSpecialSymbols :: String
+reSpecialSymbols = "\\.|()[]"
+
+-- | Quote symbols that have special meaning in regular expressions.
+quoteForRegex :: String -> String
+quoteForRegex s = s >>= \x ->
+  if x `elem` reSpecialSymbols then ['\\', x] else [x]
+
+-- | Builds a filter for hostnames from a list of names.
+makeHostnameFilter :: String -> [Either String Integer] -> Filter FilterField
+makeHostnameFilter _ [] = EmptyFilter
+makeHostnameFilter namefield vals = 
+  OrFilter . flip map vals
+  $ either  (RegexpFilter namefield . fromJust . mkRegex
+             . (\ s -> "^(" ++ s ++ "|" ++ s ++ "\\..*)$")
+             . quoteForRegex)
+            (EQFilter namefield  . NumericValue)