module Puppet.Plugins (initLua, puppetFunc, closeLua, getFiles) where
import Prelude hiding (catch)
import qualified Scripting.Lua as Lua
import Scripting.LuaUtils()
import Control.Exception
import qualified Data.Map as Map
import Control.Monad.IO.Class
import System.IO
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Puppet.Interpreter.Types
import Puppet.Printers
import Puppet.Utils
instance Lua.StackValue ResolvedValue
where
push l (ResolvedString s) = Lua.push l s
push l (ResolvedRegexp s) = Lua.push l s
push l (ResolvedInt i) = Lua.push l (fromIntegral i :: Int)
push l (ResolvedDouble d) = Lua.push l d
push l (ResolvedBool b) = Lua.push l b
push l (ResolvedRReference rr _) = Lua.push l rr
push l (ResolvedArray arr) = Lua.push l arr
push l (ResolvedHash h) = Lua.push l (Map.fromList h)
push l (ResolvedUndefined) = Lua.push l ("undefined" :: T.Text)
peek l n = do
t <- Lua.ltype l n
case t of
Lua.TBOOLEAN -> fmap (fmap ResolvedBool) (Lua.peek l n)
Lua.TSTRING -> fmap (fmap ResolvedString) (Lua.peek l n)
Lua.TNUMBER -> fmap (fmap ResolvedDouble) (Lua.peek l n)
Lua.TNIL -> return (Just ResolvedUndefined)
Lua.TNONE -> return (Just ResolvedUndefined)
Lua.TTABLE -> do
p <- Lua.peek l n :: IO (Maybe (Map.Map ResolvedValue ResolvedValue))
case p of
Just kp -> let ks = Map.keys kp
cp = map (\(a,b) -> (showValue a, b)) $ Map.toList kp
in if (all (\(a,b) -> a == ResolvedDouble b) (zip ks [1.0..]))
then return $ Just (ResolvedArray (map snd cp))
else return $ Just (ResolvedHash cp)
_ -> return Nothing
_ -> return Nothing
valuetype _ = Lua.TUSERDATA
getDirContents :: T.Text -> IO [T.Text]
getDirContents x = fmap (filter (not . T.all (=='.'))) (getDirectoryContents x)
checkForSubFiles :: T.Text -> T.Text -> IO [T.Text]
checkForSubFiles extension dir = do
content <- catch (fmap Right (getDirContents dir)) (\e -> return $ Left (e :: IOException))
case content of
Right o -> do
return ((map (\x -> dir <> "/" <> x) . filter (T.isSuffixOf extension)) o )
Left _ -> return []
getFiles :: T.Text -> T.Text -> T.Text -> IO [T.Text]
getFiles moduledir subdir extension =
getDirContents moduledir
>>= mapM ( (checkForSubFiles extension) . (\x -> moduledir <> "/" <> x <> "/" <> subdir))
>>= return . concat
getLuaFiles :: T.Text -> IO [T.Text]
getLuaFiles moduledir = getFiles moduledir "lib/puppet/parser/luafunctions" ".lua"
loadLuaFile :: Lua.LuaState -> T.Text -> IO [T.Text]
loadLuaFile l file = do
r <- Lua.loadfile l (T.unpack file)
case r of
0 -> Lua.call l 0 0 >> return [takeBaseName file]
_ -> do
T.hPutStrLn stderr ("Could not load file " <> file)
return []
puppetFunc :: Lua.LuaState -> T.Text -> [ResolvedValue] -> CatalogMonad ResolvedValue
puppetFunc l fn args = do
content <- liftIO $ catch (fmap Right (Lua.callfunc l (T.unpack fn) args)) (\e -> return $ Left $ tshow (e :: SomeException))
case content of
Right x -> return x
Left y -> throwPosError y
initLua :: T.Text -> IO (Lua.LuaState, [T.Text])
initLua moduledir = do
funcfiles <- getLuaFiles moduledir
l <- Lua.newstate
Lua.openlibs l
luafuncs <- fmap concat $ mapM (loadLuaFile l) funcfiles
return (l , luafuncs)
closeLua :: Lua.LuaState -> IO ()
closeLua = Lua.close