I want to replace configuration file contents using Propellor, but some configuration files are long so I want to keep them outside config.hs and without having to use quotation. I came up with this:
``` {-# LANGUAGE TemplateHaskell #-} module Utility.Embed where
import Language.Haskell.TH import qualified Data.FileEmbed as FE
sourceFile :: FilePath -> Q Exp sourceFile path = return . AppE (VarE 'lines) =<< FE.embedStringFile path ```
Which can be used like this:
standardSystem :: HostName -> Host
standardSystem hn = host hn
& Apt.installed ["heimdal-clients"]
& "/etc/krb5.conf" `File.hasContent`
$(sourceFile "files/etc/krb5.conf")
What do you think, is this the right approach or should I just read source files with the IO monad?
I think this is fine if you want to do it that way, and it's nice how short and simple the code is!
If you wanted to add this as a patch in mainline propellor, I'd need to think about whether it makes sense to require working TH support to build propellor. I guess all the systems I personally run propellor on now, including the arm ones, have working TH, but there are certianly linux architectures that don't support TH yet.
A build flag might be an option. Or, keep it in your local configuration, since it is quite short-n-sweet.
In that case, I will probably create a regular property for copying file contents. It seemed like a neat solution, but if it's not available everywhere I don't think it's worth it. I've also heard that there are problems with TH so it might be best to avoid it unless there is a compelling reason to use it.
I'm also thinking about using Data.Text.Template to template configuration files. With TH, the templates could be compiled and error-checked during build-time, kind of like what Yesod does. But again, I don't think it's worth the trouble.