propellor 5.3.4 → 5.3.5
raw patch · 14 files changed
+219/−184 lines, 14 filesdep +propellordep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: propellor
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Propellor.DotDir: checkRepoUpToDate :: IO ()
+ Propellor.DotDir: distrepo :: FilePath
+ Propellor.DotDir: dotPropellor :: IO FilePath
+ Propellor.DotDir: interactiveInit :: IO ()
+ Propellor.Wrapper: runWrapper :: IO ()
- Propellor.Property.Scheduled: period :: (IsProp (Property i)) => Property i -> Recurrance -> Property i
+ Propellor.Property.Scheduled: period :: Property i -> Recurrance -> Property i
- Propellor.Property.Scheduled: periodParse :: (IsProp (Property i)) => Property i -> String -> Property i
+ Propellor.Property.Scheduled: periodParse :: Property i -> String -> Property i
Files
- CHANGELOG +10/−0
- debian/changelog +10/−0
- executables/propellor-config.hs +29/−0
- executables/wrapper.hs +6/−0
- joeyconfig.hs +17/−29
- propellor.cabal +22/−33
- src/Propellor/Property/Apt.hs +6/−0
- src/Propellor/Property/Machine.hs +1/−1
- src/Propellor/Property/Scheduled.hs +2/−2
- src/Propellor/Property/SiteSpecific/JoeySites.hs +29/−4
- src/Propellor/Property/Systemd.hs +2/−2
- src/Propellor/Wrapper.hs +85/−0
- src/propellor-config.hs +0/−29
- src/wrapper.hs +0/−84
CHANGELOG view
@@ -1,3 +1,13 @@+propellor (5.3.5) unstable; urgency=medium++ * Apt.stdSourcesList now adds stable-updates suite+ Thanks, Sean Whitton+ * Significantly increased propellor build speed when your config.hs+ is in a fork of the propellor repository, by avoiding redundant builds+ of propellor library.++ -- Joey Hess <id@joeyh.name> Sun, 22 Apr 2018 12:27:45 -0400+ propellor (5.3.4) unstable; urgency=medium * Apt.trustsKey: Use apt-key to add key rather than manually driving gpg,
debian/changelog view
@@ -1,3 +1,13 @@+propellor (5.3.5) unstable; urgency=medium++ * Apt.stdSourcesList now adds stable-updates suite+ Thanks, Sean Whitton+ * Significantly increased propellor build speed when your config.hs+ is in a fork of the propellor repository, by avoiding redundant builds+ of propellor library.++ -- Joey Hess <id@joeyh.name> Sun, 22 Apr 2018 12:27:45 -0400+ propellor (5.3.4) unstable; urgency=medium * Apt.trustsKey: Use apt-key to add key rather than manually driving gpg,
+ executables/propellor-config.hs view
@@ -0,0 +1,29 @@+-- This is the main configuration file for Propellor, and is used to build+-- the propellor program.++import Propellor+import qualified Propellor.Property.File as File+import qualified Propellor.Property.Apt as Apt+import qualified Propellor.Property.Cron as Cron+import qualified Propellor.Property.User as User++main :: IO ()+main = defaultMain hosts++-- The hosts propellor knows about.+hosts :: [Host]+hosts =+ [ mybox+ ]++-- An example host.+mybox :: Host+mybox = host "mybox.example.com" $ props+ & osDebian Unstable X86_64+ & Apt.stdSourcesList+ & Apt.unattendedUpgrades+ & Apt.installed ["etckeeper"]+ & Apt.installed ["ssh"]+ & User.hasSomePassword (User "root")+ & File.dirExists "/var/www"+ & Cron.runPropellor (Cron.Times "30 * * * *")
+ executables/wrapper.hs view
@@ -0,0 +1,6 @@+module Main where++import Propellor.Wrapper++main :: IO ()+main = runWrapper
joeyconfig.hs view
@@ -33,7 +33,6 @@ import qualified Propellor.Property.Journald as Journald import qualified Propellor.Property.Fail2Ban as Fail2Ban import qualified Propellor.Property.Laptop as Laptop-import qualified Propellor.Property.OS as OS import qualified Propellor.Property.HostingProvider.CloudAtCost as CloudAtCost import qualified Propellor.Property.HostingProvider.Linode as Linode import qualified Propellor.Property.HostingProvider.DigitalOcean as DigitalOcean@@ -49,7 +48,6 @@ hosts :: [Host] -- * \ | | '--------' hosts = -- (o) ` [ darkstar- , gnu , dragon , clam , orca@@ -64,25 +62,6 @@ , keysafe ] ++ monsters -testvm :: Host-testvm = host "testvm.kitenet.net" $ props- & osDebian Unstable X86_64- & OS.cleanInstallOnce (OS.Confirmed "testvm.kitenet.net")- `onChange` postinstall- & Hostname.sane- & Hostname.searchDomain- & Apt.installed ["linux-image-amd64"]- & Apt.installed ["ssh"]- & User.hasPassword (User "root")- where- postinstall :: Property (HasInfo + DebianLike)- postinstall = propertyList "fixing up after clean install" $ props- & OS.preserveRootSshAuthorized- & OS.preserveResolvConf- & Apt.update- & Grub.boots "/dev/sda"- `requires` Grub.installed Grub.PC- darkstar :: Host darkstar = host "darkstar.kitenet.net" $ props & osDebian Unstable X86_64@@ -106,10 +85,9 @@ -- & imageBuiltFor honeybee -- (RawDiskImage "/srv/honeybee.img") -- (Debootstrapped mempty)--gnu :: Host-gnu = host "gnu.kitenet.net" $ props- & Postfix.satellite+ & imageBuiltFor banana+ (RawDiskImage "/srv/banana.img")+ (Debootstrapped mempty) dragon :: Host dragon = host "dragon.kitenet.net" $ props@@ -182,6 +160,17 @@ & Systemd.nspawned (GitAnnexBuilder.androidAutoBuilderContainer (Cron.Times "1 1 * * *") "3h") +banana :: Host+banana = host "banana.kitenet.net" $ props+ & lemaker_Banana_Pi+ & hasPartition+ ( partition EXT4+ `mountedAt` "/"+ `setSize` MegaBytes 950+ )+ & osDebian Testing ARMHF+ & User.hasInsecurePassword (User "root") "root"+ honeybee :: Host honeybee = host "honeybee.kitenet.net" $ props & standardSystem Testing ARMHF@@ -232,7 +221,6 @@ & ipv4 "66.228.36.95" & ipv6 "2600:3c03::f03c:91ff:fe73:b0d2" & alias "kitenet.net"- & alias "wren.kitenet.net" -- temporary & Ssh.hostKeys (Context "kitenet.net") [ (SshDsa, "ssh-dss AAAAB3NzaC1kc3MAAACBAO9tnPUT4p+9z7K6/OYuiBNHaij4Nzv5YVBih1vMl+ALz0gYAj8RWJzXmqp5buFAyfgOoLw+H9s1bBS01Sy3i07Dm6cx1fWG4RXL/E/3w1tavX99GD2bBxDBu890ebA5Tp+eFRJkS9+JwSvFiF6CP7NbVjifCagoUO56Ig048RwDAAAAFQDPY2xM3q6KwsVQliel23nrd0rV2QAAAIEAga3hj1hL00rYPNnAUzT8GAaSP62S4W68lusErH+KPbsMwFBFY/Ib1FVf8k6Zn6dZLh/HH/RtJi0JwdzPI1IFW+lwVbKfwBvhQ1lw9cH2rs1UIVgi7Wxdgfy8gEWxf+QIqn62wG+Ulf/HkWGvTrRpoJqlYRNS/gnOWj9Z/4s99koAAACBAM/uJIo2I0nK15wXiTYs/NYUZA7wcErugFn70TRbSgduIFH6U/CQa3rgHJw9DCPCQJLq7pwCnFH7too/qaK+czDk04PsgqV0+Jc7957gU5miPg50d60eJMctHV4eQ1FpwmGGfXxRBR9k2ZvikWYatYir3L6/x1ir7M0bA9IzNU45") , (SshRsa, "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEA2QAJEuvbTmaN9ex9i9bjPhMGj+PHUYq2keIiaIImJ+8mo+yKSaGUxebG4tpuDPx6KZjdycyJt74IXfn1voGUrfzwaEY9NkqOP3v6OWTC3QeUGqDCeJ2ipslbEd9Ep9XBp+/ldDQm60D0XsIZdmDeN6MrHSbKF4fXv1bqpUoUILk=")@@ -242,6 +230,7 @@ & Network.preserveStatic "eth0" `requires` Network.cleanInterfacesFile & Apt.installed ["linux-image-amd64"]+ & Apt.serviceInstalledRunning "swapspace" & Linode.serialGrub & Linode.mlocateEnabled & Apt.unattendedUpgrades@@ -341,7 +330,7 @@ , "search kitenet.net" ] & alias "debug-me.joeyh.name"- -- debug-me installed manually until package is available+ & Apt.installed ["debug-me"] & Systemd.enabled "debug-me" -- testing@@ -637,8 +626,7 @@ , host "ns6.gandi.net" $ props & ipv4 "217.70.177.40" , host "animx" $ props- & ipv4 "76.7.162.186"- & ipv4 "76.7.162.187"+ & ipv4 "76.7.174.49" ]
propellor.cabal view
@@ -1,5 +1,5 @@ Name: propellor-Version: 5.3.4+Version: 5.3.5 Cabal-Version: >= 1.20 License: BSD2 Maintainer: Joey Hess <id@joeyh.name>@@ -35,38 +35,6 @@ . It is configured using haskell. -Executable propellor- Default-Language: Haskell98- Main-Is: wrapper.hs- GHC-Options: -threaded -Wall -fno-warn-tabs -O0- if impl(ghc >= 8.0)- GHC-Options: -fno-warn-redundant-constraints- Default-Extensions: TypeOperators- Hs-Source-Dirs: src- Build-Depends:- -- propellor needs to support the ghc shipped in Debian stable,- -- and also only depends on packages in Debian stable.- base >= 4.5, base < 5,- directory, filepath, IfElse, process, bytestring, hslogger, split,- unix, unix-compat, ansi-terminal, containers (>= 0.5), network, async,- time, mtl, transformers, exceptions (>= 0.6), stm, text, hashable- Other-Modules:- Propellor.DotDir--Executable propellor-config- Default-Language: Haskell98- Main-Is: propellor-config.hs- GHC-Options: -threaded -Wall -fno-warn-tabs -O0- if impl(ghc >= 8.0)- GHC-Options: -fno-warn-redundant-constraints- Default-Extensions: TypeOperators- Hs-Source-Dirs: src- Build-Depends:- base >= 4.5, base < 5,- directory, filepath, IfElse, process, bytestring, hslogger, split,- unix, unix-compat, ansi-terminal, containers (>= 0.5), network, async,- time, mtl, transformers, exceptions (>= 0.6), stm, text, hashable- Library Default-Language: Haskell98 GHC-Options: -Wall -fno-warn-tabs -O0@@ -75,6 +43,8 @@ Default-Extensions: TypeOperators Hs-Source-Dirs: src Build-Depends:+ -- propellor needs to support the ghc shipped in Debian stable,+ -- and also only depends on packages in Debian stable. base >= 4.5, base < 5, directory, filepath, IfElse, process, bytestring, hslogger, split, unix, unix-compat, ansi-terminal, containers (>= 0.5), network, async,@@ -83,6 +53,7 @@ Exposed-Modules: Propellor Propellor.Base+ Propellor.DotDir Propellor.Location Propellor.Property Propellor.Property.Aiccu@@ -211,6 +182,7 @@ Propellor.Types.ResultCheck Propellor.Types.Singletons Propellor.Types.ZFS+ Propellor.Wrapper Other-Modules: Propellor.Bootstrap Propellor.Git@@ -254,6 +226,23 @@ System.Console.Concurrent System.Console.Concurrent.Internal System.Process.Concurrent+ Paths_propellor++Executable propellor-config+ Default-Language: Haskell98+ Hs-Source-Dirs: executables+ Main-Is: propellor-config.hs+ GHC-Options: -threaded -Wall -fno-warn-tabs -O0+ if impl(ghc >= 8.0)+ GHC-Options: -fno-warn-redundant-constraints+ Default-Extensions: TypeOperators+ Build-Depends: propellor, base++Executable propellor+ Default-Language: Haskell98+ Hs-Source-Dirs: executables+ Main-Is: wrapper.hs+ Build-Depends: propellor, base source-repository head type: git
src/Propellor/Property/Apt.hs view
@@ -88,6 +88,8 @@ binandsrc url suite = catMaybes [ Just l , Just $ srcLine l+ , sul+ , srcLine <$> sul , bl , srcLine <$> bl ]@@ -96,6 +98,10 @@ bl = do bs <- backportSuite suite return $ debLine bs url stdSections+ -- formerly known as 'volatile'+ sul = do+ sus <- stableUpdatesSuite suite+ return $ debLine sus url stdSections stdArchiveLines :: Propellor SourcesGenerator stdArchiveLines = return . binandsrc =<< getMirror
src/Propellor/Property/Machine.hs view
@@ -48,10 +48,10 @@ marvell_SheevaPlug, cubietech_Cubietruck, olimex_A10_OLinuXino_LIME,+ lemaker_Banana_Pi, -- * ARM boards (untested) cubietech_Cubieboard, cubietech_Cubieboard2,- lemaker_Banana_Pi, lemaker_Banana_Pro, olimex_A10s_OLinuXino_Micro, olimex_A20_OLinuXino_LIME,
src/Propellor/Property/Scheduled.hs view
@@ -21,7 +21,7 @@ -- -- This uses the description of the Property to keep track of when it was -- last run.-period :: (IsProp (Property i)) => Property i -> Recurrance -> Property i+period :: Property i -> Recurrance -> Property i period prop recurrance = flip describe desc $ adjustPropertySatisfy prop $ \satisfy -> do lasttime <- liftIO $ getLastChecked (getDesc prop) nexttime <- liftIO $ fmap startTime <$> nextTime schedule lasttime@@ -37,7 +37,7 @@ desc = getDesc prop ++ " (period " ++ fromRecurrance recurrance ++ ")" -- | Like period, but parse a human-friendly string.-periodParse :: (IsProp (Property i)) => Property i -> String -> Property i+periodParse :: Property i -> String -> Property i periodParse prop s = case toRecurrance s of Just recurrance -> period prop recurrance Nothing -> adjustPropertySatisfy prop $ \_ -> do
src/Propellor/Property/SiteSpecific/JoeySites.hs view
@@ -15,6 +15,7 @@ import qualified Propellor.Property.Cron as Cron import qualified Propellor.Property.Service as Service import qualified Propellor.Property.User as User+import qualified Propellor.Property.Group as Group import qualified Propellor.Property.Borg as Borg import qualified Propellor.Property.Apache as Apache import qualified Propellor.Property.Postfix as Postfix@@ -916,10 +917,15 @@ & File.ownerGroup "/var/www/html" user (userGroup user) & Git.cloned user "git://git.kitenet.net/joey/homepower" d Nothing & buildpoller+ & Systemd.enabled setupservicename+ `requires` setupserviceinstalled+ `onChange` Systemd.started setupservicename & Systemd.enabled servicename `requires` serviceinstalled `onChange` Systemd.started servicename & User.hasGroup user (Group "dialout")+ & Group.exists (Group "gpio") Nothing+ & User.hasGroup user (Group "gpio") & Cron.niceJob "homepower upload" (Cron.Times "1 * * * *") user d rsynccommand `requires` Ssh.userKeyAt (Just sshkeyfile) user ctx sshkey@@ -951,6 +957,23 @@ , "[Install]" , "WantedBy=multi-user.target" ]+ setupservicename = "homepower-setup"+ setupservicefile = "/etc/systemd/system/" ++ setupservicename ++ ".service"+ setupserviceinstalled = setupservicefile `File.hasContent`+ [ "[Unit]"+ , "Description=home power monitor setup"+ , ""+ , "[Service]"+ , "ExecStart=" ++ d ++ "/setup"+ , "WorkingDirectory=" ++ d+ , "User=root"+ , "Group=root"+ , "Type=oneshot"+ , ""+ , "[Install]"+ , "WantedBy=multi-user.target"+ , "WantedBy=homepower.target"+ ] -- Any changes to the rsync command will need my .authorized_keys -- rsync server command to be updated too. rsynccommand = "rsync -e 'ssh -i" ++ sshkeyfile ++ "' -avz rrds/recent/ joey@kitenet.net:/srv/web/homepower.joeyh.name/rrds/recent/"@@ -987,6 +1010,7 @@ , "dhcp-range=10.1.1.100,10.1.1.150,24h" , "no-hosts" , "address=/honeybee.kitenet.net/10.1.1.1"+ , "address=/house.kitenet.net/10.1.1.1" ] `onChange` Service.restarted "dnsmasq" & ipmasq "wlan0"@@ -1040,7 +1064,7 @@ laptopSoftware :: Property DebianLike laptopSoftware = Apt.installed- [ "intel-microcode"+ [ "intel-microcode", "acpi" , "procmeter3", "xfce4", "procmeter3", "unclutter" , "mplayer", "fbreader", "firefox", "chromium" , "libdatetime-event-sunrise-perl", "libtime-duration-perl"@@ -1055,6 +1079,7 @@ , "pmount", "tree", "pv" , "arbtt", "hledger", "bc" , "apache2", "ikiwiki", "libhighlight-perl"+ , "avahi-daemon", "avahi-discover" , "pal" , "yeahconsole", "xkbset", "xinput" , "assword", "pumpa"@@ -1096,13 +1121,13 @@ ["--debian", "sun7i-a20-cubietruck"] `assume` MadeChange mydts =- [ "/* Device tree addition enabling onewire sensors on CubieTruck GPIO pin PG8 */"+ [ "/* Device tree addition enabling onewire sensors on CubieTruck GPIO pin PC21 */" , "#include <dt-bindings/gpio/gpio.h>" , "" , "/ {" , "\tonewire_device {" , "\t\tcompatible = \"w1-gpio\";"- , "\t\tgpios = <&pio 6 8 GPIO_ACTIVE_HIGH>; /* PG8 */"+ , "\t\tgpios = <&pio 2 21 GPIO_ACTIVE_HIGH>; /* PC21 */" , "\t\tpinctrl-names = \"default\";" , "\t\tpinctrl-0 = <&my_w1_pin>;" , "\t};"@@ -1110,7 +1135,7 @@ , "" , "&pio {" , "\tmy_w1_pin: my_w1_pin@0 {"- , "\t\tallwinner,pins = \"PG8\";"+ , "\t\tallwinner,pins = \"PC21\";" , "\t\tallwinner,function = \"gpio_in\";" , "\t};" , "};"
src/Propellor/Property/Systemd.hs view
@@ -217,7 +217,7 @@ -- to bootstrap. -- -- > container "webserver" $ \d -> Chroot.debootstrapped mempty d $ props--- > & osDebian Unstable X86_64+-- > & osDebian Unstable X86_64 -- > & Apt.installedRunning "apache2" -- > & ... container :: MachineName -> (FilePath -> Chroot.Chroot) -> Container@@ -238,7 +238,7 @@ -- to bootstrap. -- -- > debContainer "webserver" $ props--- > & osDebian Unstable X86_64+-- > & osDebian Unstable X86_64 -- > & Apt.installedRunning "apache2" -- > & ... debContainer :: MachineName -> Props metatypes -> Container
+ src/Propellor/Wrapper.hs view
@@ -0,0 +1,85 @@+-- | This module is used to implement a wrapper program for propellor+-- distribution.+--+-- Distributions should install this program into PATH.+-- (Cabal builds it as dist/build/propellor/propellor).+--+-- This is not the propellor main program (that's config.hs).+-- This bootstraps ~/.propellor/config.hs, builds it if+-- it's not already built, and runs it.+--+-- If ./config.hs exists and looks like a propellor config file, +-- it instead builds and runs in the current working directory.++module Propellor.Wrapper (runWrapper) where++import Propellor.DotDir+import Propellor.Message+import Propellor.Bootstrap+import Utility.Monad+import Utility.Directory+import Utility.FileMode+import Utility.Process+import Utility.Process.NonConcurrent+import Utility.FileSystemEncoding++import System.Environment (getArgs)+import System.Exit+import System.Posix+import Data.List+import Control.Monad.IfElse+import Control.Applicative+import Prelude++runWrapper :: IO ()+runWrapper = withConcurrentOutput $ do+ useFileSystemEncoding+ go =<< getArgs+ where+ go ["--init"] = interactiveInit+ go args = ifM configInCurrentWorkingDirectory+ ( buildRunConfig args+ , ifM (doesDirectoryExist =<< dotPropellor)+ ( do+ checkRepoUpToDate+ changeWorkingDirectory =<< dotPropellor+ buildRunConfig args+ , error "Seems that ~/.propellor/ does not exist. To set it up, run: propellor --init"+ )+ )++buildRunConfig :: [String] -> IO ()+buildRunConfig args = do+ unlessM (doesFileExist "propellor") $ do+ buildPropellor Nothing+ putStrLn ""+ putStrLn ""+ (_, _, _, pid) <- createProcessNonConcurrent (proc "./propellor" args) + exitWith =<< waitForProcessNonConcurrent pid++configInCurrentWorkingDirectory :: IO Bool+configInCurrentWorkingDirectory = ifM (doesFileExist "config.hs")+ ( do+ -- This is a security check to avoid using the current+ -- working directory as the propellor configuration+ -- if it's not owned by the user, or is world-writable,+ -- or group writable. (Some umasks may make directories+ -- group writable, but typical ones do not.)+ s <- getFileStatus "."+ uid <- getRealUserID+ if fileOwner s /= uid+ then unsafe "you don't own the current directory"+ else if checkMode groupWriteMode (fileMode s)+ then unsafe "the current directory is group writable"+ else if checkMode otherWriteMode (fileMode s)+ then unsafe "the current directory is world-writable"+ else ifM mentionspropellor+ ( return True+ , notusing "it does not seem to be a propellor config file"+ )+ , return False+ )+ where+ unsafe s = notusing (s ++ ". This seems unsafe.")+ notusing s = error $ "Not using ./config.hs because " ++ s+ mentionspropellor = ("Propellor" `isInfixOf`) <$> readFile "config.hs"
− src/propellor-config.hs
@@ -1,29 +0,0 @@--- This is the main configuration file for Propellor, and is used to build--- the propellor program.--import Propellor-import qualified Propellor.Property.File as File-import qualified Propellor.Property.Apt as Apt-import qualified Propellor.Property.Cron as Cron-import qualified Propellor.Property.User as User--main :: IO ()-main = defaultMain hosts---- The hosts propellor knows about.-hosts :: [Host]-hosts =- [ mybox- ]---- An example host.-mybox :: Host-mybox = host "mybox.example.com" $ props- & osDebian Unstable X86_64- & Apt.stdSourcesList- & Apt.unattendedUpgrades- & Apt.installed ["etckeeper"]- & Apt.installed ["ssh"]- & User.hasSomePassword (User "root")- & File.dirExists "/var/www"- & Cron.runPropellor (Cron.Times "30 * * * *")
− src/wrapper.hs
@@ -1,84 +0,0 @@--- | Wrapper program for propellor distribution.------ Distributions should install this program into PATH.--- (Cabal builds it as dist/build/propellor/propellor).------ This is not the propellor main program (that's config.hs).--- This bootstraps ~/.propellor/config.hs, builds it if--- it's not already built, and runs it.------ If ./config.hs exists and looks like a propellor config file, --- it instead builds and runs in the current working directory.--module Main where--import Propellor.DotDir-import Propellor.Message-import Propellor.Bootstrap-import Utility.Monad-import Utility.Directory-import Utility.FileMode-import Utility.Process-import Utility.Process.NonConcurrent-import Utility.FileSystemEncoding--import System.Environment (getArgs)-import System.Exit-import System.Posix-import Data.List-import Control.Monad.IfElse-import Control.Applicative-import Prelude--main :: IO ()-main = withConcurrentOutput $ do- useFileSystemEncoding- go =<< getArgs- where- go ["--init"] = interactiveInit- go args = ifM configInCurrentWorkingDirectory- ( buildRunConfig args- , ifM (doesDirectoryExist =<< dotPropellor)- ( do- checkRepoUpToDate- changeWorkingDirectory =<< dotPropellor- buildRunConfig args- , error "Seems that ~/.propellor/ does not exist. To set it up, run: propellor --init"- )- )--buildRunConfig :: [String] -> IO ()-buildRunConfig args = do- unlessM (doesFileExist "propellor") $ do- buildPropellor Nothing- putStrLn ""- putStrLn ""- (_, _, _, pid) <- createProcessNonConcurrent (proc "./propellor" args) - exitWith =<< waitForProcessNonConcurrent pid--configInCurrentWorkingDirectory :: IO Bool-configInCurrentWorkingDirectory = ifM (doesFileExist "config.hs")- ( do- -- This is a security check to avoid using the current- -- working directory as the propellor configuration- -- if it's not owned by the user, or is world-writable,- -- or group writable. (Some umasks may make directories- -- group writable, but typical ones do not.)- s <- getFileStatus "."- uid <- getRealUserID- if fileOwner s /= uid- then unsafe "you don't own the current directory"- else if checkMode groupWriteMode (fileMode s)- then unsafe "the current directory is group writable"- else if checkMode otherWriteMode (fileMode s)- then unsafe "the current directory is world-writable"- else ifM mentionspropellor- ( return True- , notusing "it does not seem to be a propellor config file"- )- , return False- )- where- unsafe s = notusing (s ++ ". This seems unsafe.")- notusing s = error $ "Not using ./config.hs because " ++ s- mentionspropellor = ("Propellor" `isInfixOf`) <$> readFile "config.hs"