packages feed

propellor 5.7.0 → 5.8.0

raw patch · 22 files changed

+177/−80 lines, 22 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Propellor.Property.Chroot: inChroot :: Propellor Bool
- Propellor.Property.Chroot: instance GHC.Show.Show Propellor.Property.Chroot.InChroot
- Propellor.Property.SiteSpecific.JoeySites: homePower :: IsContext c => User -> [Host] -> c -> (SshKeyType, PubKeyText) -> Property (HasInfo + DebianLike)
+ Propellor.Info: hasContainerCapability :: ContainerCapability -> Propellor Bool
+ Propellor.Property.SiteSpecific.JoeySites: house :: IsContext c => User -> [Host] -> c -> (SshKeyType, PubKeyText) -> Property (HasInfo + DebianLike)
+ Propellor.Property.User: ownsWithPrimaryGroup :: User -> FilePath -> Property UnixLike
+ Propellor.Property.User: primaryGroup :: User -> IO Group
+ Propellor.Types.Container: FilesystemContained :: ContainerCapability
+ Propellor.Types.Container: HostnameContained :: ContainerCapability
+ Propellor.Types.Container: data ContainerCapability
+ Propellor.Types.Container: instance GHC.Classes.Eq Propellor.Types.Container.ContainerCapability
+ Propellor.Types.Container: instance GHC.Read.Read Propellor.Types.Container.ContainerCapability
+ Propellor.Types.Container: instance GHC.Show.Show Propellor.Types.Container.ContainerCapability
+ Propellor.Types.Container: instance Propellor.Types.Info.IsInfo [Propellor.Types.Container.ContainerCapability]
- Propellor.Property.Chroot: propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> Property UnixLike
+ Propellor.Property.Chroot: propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> [ContainerCapability] -> Property UnixLike
- Propellor.Property.Chroot: provisioned' :: Chroot -> Bool -> RevertableProperty (HasInfo + Linux) Linux
+ Propellor.Property.Chroot: provisioned' :: Chroot -> Bool -> [ContainerCapability] -> RevertableProperty (HasInfo + Linux) Linux
- Propellor.Types.CmdLine: ChrootChain :: HostName -> FilePath -> Bool -> Bool -> CmdLine
+ Propellor.Types.CmdLine: ChrootChain :: HostName -> FilePath -> Bool -> Bool -> [ContainerCapability] -> CmdLine

Files

CHANGELOG view
@@ -1,3 +1,24 @@+propellor (5.8.0) unstable; urgency=medium++  * Fix bug in File.containsShellSetting that replaced whole shell conffile+    content with the setting if the file did not previously contain a line+    setting the key to some value.+  * Removed inChroot, instead use hasContainerCapability FilesystemContained.+    (API change)+  * Hostname: Properties that used to not do anything in a systemd or+    docker container will now change the container's hostname,+    since it's namespaced.+  * Add User.ownsWithPrimaryGroup+    Thanks, Sean Whitton+  * Ssh.userKeys, Ssh.userKeyAt: Create .ssh directory when it does not yet+    exist.+  * Ssh.userKeyAt: When a relative filepath is provided, it's put inside+    the user's .ssh directory.+  * Fix Git.pulled always reporting a change.+    Thanks, Sean Whitton++ -- Joey Hess <id@joeyh.name>  Fri, 26 Apr 2019 08:23:29 -0400+ propellor (5.7.0) unstable; urgency=medium    * Sbuild.built no longer includes Apt.stdSourcesList by default,
debian/changelog view
@@ -1,3 +1,24 @@+propellor (5.8.0) unstable; urgency=medium++  * Fix bug in File.containsShellSetting that replaced whole shell conffile+    content with the setting if the file did not previously contain a line+    setting the key to some value.+  * Removed inChroot, instead use hasContainerCapability FilesystemContained.+    (API change)+  * Hostname: Properties that used to not do anything in a systemd or+    docker container will now change the container's hostname,+    since it's namespaced.+  * Add User.ownsWithPrimaryGroup+    Thanks, Sean Whitton+  * Ssh.userKeys, Ssh.userKeyAt: Create .ssh directory when it does not yet+    exist.+  * Ssh.userKeyAt: When a relative filepath is provided, it's put inside+    the user's .ssh directory.+  * Fix Git.pulled always reporting a change.+    Thanks, Sean Whitton++ -- Joey Hess <id@joeyh.name>  Fri, 26 Apr 2019 08:23:29 -0400+ propellor (5.7.0) unstable; urgency=medium    * Sbuild.built no longer includes Apt.stdSourcesList by default,
joeyconfig.hs view
@@ -193,17 +193,18 @@ 		[ (SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIS/hDYq1MAxfOBf49htym3BOYlx4Gk9SDpiHjv7u6IC") 		] -	& JoeySites.homePower+	& JoeySites.house 		(User "joey") 		hosts-		(Context "homepower.joeyh.name")+		(Context "house.joeyh.name") 		(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAmVYddg/RgCbIj+cLcEiddeFXaYFnbEJ3uGj9G/EyV joey@honeybee") 	& JoeySites.homeRouter 	& JoeySites.homeNAS 	& Apt.installed ["mtr-tiny", "iftop", "screen"] 	& Postfix.satellite -	& check (not <$> inChroot) (setupRevertableProperty autobuilder)+	& check (not <$> hasContainerCapability Systemd.FilesystemContained) +		(setupRevertableProperty autobuilder) 	-- In case compiler needs more than available ram 	& Apt.serviceInstalledRunning "swapspace"   where
propellor.cabal view
@@ -1,5 +1,5 @@ Name: propellor-Version: 5.7.0+Version: 5.8.0 Cabal-Version: 1.20 License: BSD2 Maintainer: Joey Hess <id@joeyh.name>
src/Propellor/CmdLine.hs view
@@ -129,7 +129,7 @@ 	go _ ListFields = listPrivDataFields hostlist 	go _ (AddKey keyid) = addKey keyid 	go _ (RmKey keyid) = rmKey keyid-	go _ c@(ChrootChain _ _ _ _) = Chroot.chain hostlist c+	go _ c@(ChrootChain _ _ _ _ _) = Chroot.chain hostlist c 	go _ (DockerChain hn cid) = Docker.chain hostlist hn cid 	go _ (DockerInit hn) = Docker.init hn 	go _ (GitPush fin fout) = gitPushHelper fin fout
src/Propellor/Info.hs view
@@ -11,6 +11,7 @@ 	pureInfoProperty', 	askInfo, 	getOS,+	hasContainerCapability, 	ipv4, 	ipv6, 	alias,@@ -26,6 +27,7 @@ import Propellor.Types import Propellor.Types.Info import Propellor.Types.MetaTypes+import Propellor.Types.Container  import "mtl" Control.Monad.Reader import qualified Data.Set as S@@ -74,6 +76,11 @@ -- | Gets a value from the host's Info. askInfo :: (IsInfo v) => Propellor v askInfo = asks (fromInfo . hostInfo)++-- | Checks if a ContainerCapability is set in the current Info.+hasContainerCapability :: ContainerCapability -> Propellor Bool+hasContainerCapability c = elem c+	<$> (askInfo ::  Propellor [ContainerCapability])  -- | Specifies that a host's operating system is Debian, -- and further indicates the suite and architecture.
src/Propellor/Property/Bootstrap.hs view
@@ -13,6 +13,7 @@ import Propellor.Base import Propellor.Bootstrap import Propellor.Types.Info+import Propellor.Types.Container import Propellor.Property.Chroot import Propellor.PrivData.Paths @@ -58,7 +59,7 @@ -- All build dependencies are installed, using distribution packages -- or falling back to using cabal or stack. bootstrappedFrom :: RepoSource -> Property Linux-bootstrappedFrom reposource = check inChroot $+bootstrappedFrom reposource = check (hasContainerCapability FilesystemContained) $ 	go `requires` clonedFrom reposource   where 	go :: Property Linux@@ -133,7 +134,7 @@ 			liftIO $ B.writeFile gitconfig cfg 		return MadeChange -	needclone = (inChroot <&&> truelocaldirisempty)+	needclone = (hasContainerCapability FilesystemContained <&&> truelocaldirisempty) 		<||> (liftIO (not <$> doesDirectoryExist localdir)) 	 	truelocaldirisempty = exposeTrueLocaldir $ const $
src/Propellor/Property/Chroot.hs view
@@ -9,7 +9,6 @@ 	ChrootBootstrapper(..), 	Debootstrapped(..), 	ChrootTarball(..),-	inChroot, 	exposeTrueLocaldir, 	-- * Internal use 	provisioned',@@ -23,6 +22,7 @@ import Propellor.Container import Propellor.Types.CmdLine import Propellor.Types.Chroot+import Propellor.Types.Container import Propellor.Types.Info import Propellor.Types.Core import Propellor.Property.Chroot.Util@@ -127,19 +127,20 @@ -- is first unmounted. Note that it does not ensure that any processes -- that might be running inside the chroot are stopped. provisioned :: Chroot -> RevertableProperty (HasInfo + Linux) Linux-provisioned c = provisioned' c False+provisioned c = provisioned' c False [FilesystemContained]  provisioned' 	:: Chroot 	-> Bool+	-> [ContainerCapability] 	-> RevertableProperty (HasInfo + Linux) Linux-provisioned' c@(Chroot loc bootstrapper infopropigator _) systemdonly =+provisioned' c@(Chroot loc bootstrapper infopropigator _) systemdonly caps = 	(infopropigator c normalContainerInfo $ setup `describe` chrootDesc c "exists") 		<!> 	(teardown `describe` chrootDesc c "removed")   where 	setup :: Property Linux-	setup = propellChroot c (inChrootProcess (not systemdonly) c) systemdonly+	setup = propellChroot c (inChrootProcess (not systemdonly) c) systemdonly caps 		`requires` built  	built = case buildchroot bootstrapper (chrootSystem c) loc of@@ -165,8 +166,8 @@ 	mempty { _chroots = M.singleton loc h }  -- | Propellor is run inside the chroot to provision it.-propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> Property UnixLike-propellChroot c@(Chroot loc _ _ _) mkproc systemdonly = property (chrootDesc c "provisioned") $ do+propellChroot :: Chroot -> ([String] -> IO (CreateProcess, IO ())) -> Bool -> [ContainerCapability] -> Property UnixLike+propellChroot c@(Chroot loc _ _ _) mkproc systemdonly caps = property (chrootDesc c "provisioned") $ do 	let d = localdir </> shimdir c 	let me = localdir </> "propellor" 	shim <- liftIO $ Shim.setup me Nothing d@@ -188,7 +189,7 @@  	chainprovision shim = do 		parenthost <- asks hostName-		cmd <- liftIO $ toChain parenthost c systemdonly+		cmd <- liftIO $ toChain parenthost c systemdonly caps 		pe <- liftIO standardPathEnv 		(p, cleanup) <- liftIO $ mkproc 			[ shim@@ -199,13 +200,13 @@ 		liftIO cleanup 		return r -toChain :: HostName -> Chroot -> Bool -> IO CmdLine-toChain parenthost (Chroot loc _ _ _) systemdonly = do+toChain :: HostName -> Chroot -> Bool -> [ContainerCapability] -> IO CmdLine+toChain parenthost (Chroot loc _ _ _) systemdonly caps = do 	onconsole <- isConsole <$> getMessageHandle-	return $ ChrootChain parenthost loc systemdonly onconsole+	return $ ChrootChain parenthost loc systemdonly onconsole caps  chain :: [Host] -> CmdLine -> IO ()-chain hostlist (ChrootChain hn loc systemdonly onconsole) =+chain hostlist (ChrootChain hn loc systemdonly onconsole caps) = 	case findHostNoAlias hostlist hn of 		Nothing -> errorMessage ("cannot find host " ++ hn) 		Just parenthost -> case M.lookup loc (_chroots $ fromInfo $ hostInfo parenthost) of@@ -216,11 +217,12 @@ 		changeWorkingDirectory localdir 		when onconsole forceConsole 		onlyProcess (provisioningLock loc) $-			runChainPropellor (setInChroot h) $+			runChainPropellor (setcaps h) $ 				ensureChildProperties $ 					if systemdonly 						then [toChildProperty Systemd.installed] 						else hostProperties h+	setcaps h = h { hostInfo = hostInfo h `addInfo` caps } chain _ _ = errorMessage "bad chain command"  inChrootProcess :: Bool -> Chroot -> [String] -> IO (CreateProcess, IO ())@@ -252,21 +254,6 @@ chrootDesc :: Chroot -> String -> String chrootDesc (Chroot loc _ _ _) desc = "chroot " ++ loc ++ " " ++ desc --- | Check if propellor is currently running within a chroot.------ This allows properties to check and avoid performing actions that--- should not be done in a chroot.-inChroot :: Propellor Bool-inChroot = extract . fromMaybe (InChroot False) . fromInfoVal <$> askInfo-  where-	extract (InChroot b) = b--setInChroot :: Host -> Host-setInChroot h = h { hostInfo = hostInfo h `addInfo` InfoVal (InChroot True) }--newtype InChroot = InChroot Bool-	deriving (Typeable, Show)- -- | Runs an action with the true localdir exposed, -- not the one bind-mounted into a chroot. The action is passed the -- path containing the contents of the localdir outside the chroot.@@ -276,7 +263,7 @@ -- we unmount the localdir to expose the true localdir. Finally, to cleanup, -- the temp directory is bind mounted back to the localdir. exposeTrueLocaldir :: (FilePath -> Propellor a) -> Propellor a-exposeTrueLocaldir a = ifM inChroot+exposeTrueLocaldir a = ifM (hasContainerCapability FilesystemContained) 	( withTmpDirIn (takeDirectory localdir) "propellor.tmp" $ \tmpdir -> 		bracket_ 			(movebindmount localdir tmpdir)
src/Propellor/Property/ConfFile.hs view
@@ -161,7 +161,7 @@ 		isline 		(not . isline) 		(const [line])-		(const [line])+		(++ [line]) 		f 	dedup = fileProperty "" dedup' f 	dedup' ls = let (pre, wanted, post) = foldl' find ([], [], []) ls
src/Propellor/Property/Docker.hs view
@@ -598,8 +598,9 @@ 	go cid h = do 		changeWorkingDirectory localdir 		onlyProcess (provisioningLock cid) $-			runChainPropellor h $ +			runChainPropellor (setcaps h) $  				ensureChildProperties $ hostProperties h+	setcaps h = h { hostInfo = hostInfo h `addInfo` [HostnameContained, FilesystemContained] }  stopContainer :: ContainerId -> IO Bool stopContainer cid = boolSystem dockercmd [Param "stop", Param $ fromContainerId cid ]
src/Propellor/Property/Git.hs view
@@ -110,7 +110,7 @@ 		[ "cd " ++ shellEscape dir 		, "git pull" 		]-		`changesFile` (dir </> ".git" </> "FETCH_HEAD")+		`changesFileContent` (dir </> ".git" </> "FETCH_HEAD")  isGitDir :: FilePath -> IO Bool isGitDir dir = isNothing <$> catchMaybeIO (readProcess "git" ["rev-parse", "--resolve-git-dir", dir])
src/Propellor/Property/Grub.hs view
@@ -18,9 +18,9 @@ import qualified Propellor.Property.ConfFile as ConfFile import qualified Propellor.Property.Apt as Apt import Propellor.Property.Mount-import Propellor.Property.Chroot (inChroot) import Propellor.Types.Info import Propellor.Types.Bootloader+import Propellor.Types.Container import Utility.SafeCommand  import Data.List@@ -34,10 +34,11 @@ -- | Installs the grub package. This does not make grub be used as the -- bootloader. ----- This includes running update-grub, unless it's run in a chroot.+-- This includes running update-grub, unless it's run in a chroot+-- or container. installed :: GrubTarget -> Property (HasInfo + DebianLike) installed grubtarget = installed' grubtarget -	`onChange` (check (not <$> inChroot) mkConfig)+	`onChange` (check (not <$> hasContainerCapability FilesystemContained) mkConfig)  -- | Run update-grub, to generate the grub boot menu. It will be -- automatically updated when kernel packages are installed.
src/Propellor/Property/Hostname.hs view
@@ -1,8 +1,10 @@+{-# LANGUAGE LambdaCase #-}+ module Propellor.Property.Hostname where  import Propellor.Base import qualified Propellor.Property.File as File-import Propellor.Property.Chroot (inChroot)+import Propellor.Types.Container import Utility.Split  import Data.List@@ -41,7 +43,7 @@ 			else Just ("127.0.1.1", [hn, basehost]) 		, Just ("127.0.0.1", ["localhost"]) 		]-	, check (not <$> inChroot) $+	, check safetochange $ 		cmdProperty "hostname" [basehost] 			`assume` NoChange 	]@@ -50,6 +52,10 @@ 	basehost = takeWhile (/= '.') hn 	domain = extractdomain hn 	+	safetochange = askInfo >>= return . \case+		[] -> True+		caps -> HostnameContained `elem` caps+ 	hostslines ipsnames =  		File.fileProperty desc (addhostslines ipsnames) "/etc/hosts" 	addhostslines :: [(String, [String])] -> [String] -> [String]
src/Propellor/Property/Localdir.hs view
@@ -7,7 +7,7 @@ import Propellor.Base import Propellor.Git.Config import Propellor.Types.Info-import Propellor.Property.Chroot (inChroot)+import Propellor.Types.Container import Propellor.Property.Mount (partialBindMountsOf, umountLazy)  -- | Sets the url to use as the origin of propellor's git repository.@@ -46,7 +46,7 @@ 		return NoChange   where 	atend _ = do-		ifM inChroot+		ifM (hasContainerCapability FilesystemContained) 			-- In a chroot, all we have to do is unmount localdir, 			-- and then delete it 			( liftIO $ umountLazy localdir
src/Propellor/Property/Sbuild.hs view
@@ -270,7 +270,7 @@  -- | Ensure that an sbuild schroot uses the host's Apt proxy. ----- This property is standardly used when the host has 'Apt.useLocalCacher'.+-- This property is typically used when the host has 'Apt.useLocalCacher'. useHostProxy :: Host -> Property DebianLike useHostProxy h = property' "use host's apt proxy" $ \w -> 	-- Note that we can't look at getProxyInfo outside the property,
src/Propellor/Property/SiteSpecific/JoeySites.hs view
@@ -754,10 +754,10 @@ 		, "# Redirect all to joeyh.name." 		, "rewriterule (.*) http://joeyh.name$1 [r]" 		]-	& alias "homepower.joeyh.name"-	& apacheSite "homepower.joeyh.name"-		[ "DocumentRoot /srv/web/homepower.joeyh.name"-		, "<Directory /srv/web/homepower.joeyh.name>"+	& alias "house.joeyh.name"+	& apacheSite "house.joeyh.name"+		[ "DocumentRoot /srv/web/house.joeyh.name"+		, "<Directory /srv/web/house.joeyh.name>" 		, "  Options Indexes ExecCGI" 		, "  AllowOverride None" 		, Apache.allowAll@@ -899,13 +899,13 @@ 	& "/etc/systemd/logind.conf" `ConfFile.containsIniSetting` 		("Login", "LidSwitchIgnoreInhibited", "no") -homePower :: IsContext c => User -> [Host] -> c -> (SshKeyType, Ssh.PubKeyText) -> Property (HasInfo + DebianLike)-homePower user hosts ctx sshkey = propertyList "home power" $ props+house :: IsContext c => User -> [Host] -> c -> (SshKeyType, Ssh.PubKeyText) -> Property (HasInfo + DebianLike)+house user hosts ctx sshkey = propertyList "home automation" $ props 	& Apache.installed 	& Apt.installed ["python", "python-pymodbus", "rrdtool", "rsync"]-	& File.ownerGroup "/var/www/html" user (userGroup user)-	& Git.cloned user "https://git.joeyh.name/git/joey/homepower.git" d Nothing+	& Git.cloned user "https://git.joeyh.name/git/joey/house.git" d Nothing 	& Git.cloned user "https://git.joeyh.name/git/reactive-banana-automation.git" (d </> "reactive-banana-automation") Nothing+	& websitesymlink 	& build 	& Systemd.enabled setupservicename 		`requires` setupserviceinstalled@@ -924,8 +924,8 @@ 	& User.hasGroup user (Group "gpio") 	& Apt.installed ["i2c-tools"] 	& User.hasGroup user (Group "i2c")-	& "/etc/modules-load.d/homepower.conf" `File.hasContent` ["i2c-dev"]-	& Cron.niceJob "homepower upload"+	& "/etc/modules-load.d/house.conf" `File.hasContent` ["i2c-dev"]+	& Cron.niceJob "house upload" 		(Cron.Times "1 * * * *") user d rsynccommand 		`requires` Ssh.userKeyAt (Just sshkeyfile) user ctx sshkey 		`requires` File.ownerGroup (takeDirectory sshkeyfile)@@ -934,7 +934,7 @@ 		`requires` Ssh.knownHost hosts "kitenet.net" user 	&  File.hasPrivContentExposed "/etc/darksky-forecast-url" anyContext   where-	d = "/var/www/html/homepower"+	d = "/home/joey/house" 	sshkeyfile = d </> ".ssh/key" 	build = check (not <$> doesFileExist (d </> "controller")) $ 		userScriptProperty (User "joey")@@ -955,11 +955,11 @@ 			, "libghc-reactive-banana-dev" 			, "libghc-hinotify-dev" 			]-	pollerservicename = "homepower"+	pollerservicename = "house-poller" 	pollerservicefile = "/etc/systemd/system/" ++ pollerservicename ++ ".service" 	pollerserviceinstalled = pollerservicefile `File.hasContent` 		[ "[Unit]"-		, "Description=home power poller"+		, "Description=house poller" 		, "" 		, "[Service]" 		, "ExecStart=" ++ d ++ "/poller"@@ -970,13 +970,13 @@ 		, "" 		, "[Install]" 		, "WantedBy=multi-user.target"-		, "WantedBy=homepower-controller.target"+		, "WantedBy=house-controller.target" 		]-	controllerservicename = "homepower-controller"+	controllerservicename = "house-controller" 	controllerservicefile = "/etc/systemd/system/" ++ controllerservicename ++ ".service" 	controllerserviceinstalled = controllerservicefile `File.hasContent` 		[ "[Unit]"-		, "Description=home power controller"+		, "Description=house controller" 		, "" 		, "[Service]" 		, "ExecStart=" ++ d ++ "/controller"@@ -988,11 +988,11 @@ 		, "[Install]" 		, "WantedBy=multi-user.target" 		]-	watchdogservicename = "homepower-watchdog"+	watchdogservicename = "house-watchdog" 	watchdogservicefile = "/etc/systemd/system/" ++ watchdogservicename ++ ".service" 	watchdogserviceinstalled = watchdogservicefile `File.hasContent` 		[ "[Unit]"-		, "Description=home power watchdog"+		, "Description=house watchdog" 		, "" 		, "[Service]" 		, "ExecStart=" ++ d ++ "/watchdog"@@ -1004,11 +1004,11 @@ 		, "[Install]" 		, "WantedBy=multi-user.target" 		]-	setupservicename = "homepower-setup"+	setupservicename = "house-setup" 	setupservicefile = "/etc/systemd/system/" ++ setupservicename ++ ".service" 	setupserviceinstalled = setupservicefile `File.hasContent` 		[ "[Unit]"-		, "Description=home power monitor setup"+		, "Description=house setup" 		, "" 		, "[Service]" 		, "ExecStart=" ++ d ++ "/setup"@@ -1019,12 +1019,21 @@ 		, "" 		, "[Install]" 		, "WantedBy=multi-user.target"-		, "WantedBy=homepower.target"+		, "WantedBy=house-poller.target"+		, "WantedBy=house-controller.target"+		, "WantedBy=house-watchdog.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/ joey@kitenet.net:/srv/web/homepower.joeyh.name/rrds/"+	rsynccommand = "rsync -e 'ssh -i" ++ sshkeyfile ++ "' -avz rrds/ joey@kitenet.net:/srv/web/house.joeyh.name/rrds/" +	websitesymlink :: Property UnixLike+	websitesymlink = check (not . isSymbolicLink <$> getSymbolicLinkStatus "/var/www/html")+		(property "website symlink" $ makeChange $ do+			removeDirectoryRecursive "/var/www/html"+			createSymbolicLink d "/var/www/html"+		)+ homerouterWifiInterfaceOld :: String homerouterWifiInterfaceOld = "wlx00c0ca82eb78" -- thinkpenguin wifi adapter @@ -1063,7 +1072,7 @@ 		, "interface=" ++ homerouterWifiInterface 		, "interface=eth0" 		, "domain=kitenet.net"-		-- lease time is short because the homepower+		-- lease time is short because the house 		-- controller wants to know when clients disconnect 		, "dhcp-range=10.1.1.100,10.1.1.150,10m" 		, "no-hosts"
src/Propellor/Property/Ssh.hs view
@@ -279,9 +279,12 @@ -- | Sets up a user with the specified pubic key, and a private -- key from the privdata. ----- A file can be specified to write the key to somewhere other than+-- A FilePath can be specified to write the key to somewhere other than -- the default locations. Allows a user to have multiple keys for -- different roles.+--+-- When the FilePath is relative, is put inside the User's +-- ~/.ssh/ directory. userKeyAt :: IsContext c => Maybe FilePath -> User -> c -> (SshKeyType, PubKeyText) -> Property (HasInfo + UnixLike) userKeyAt dest user@(User u) context (keytype, pubkeytext) = 	combineProperties desc $ props@@ -306,14 +309,18 @@ 	installprop writer ext key = do 		f <- liftIO $ keyfile ext 		return $ combineProperties desc $ props+			& File.dirExists (takeDirectory f) 			& writer f (keyFileContent key) 			& File.ownerGroup f user (userGroup user) 			& File.ownerGroup (takeDirectory f) user (userGroup user) 	keyfile ext = case dest of-		Nothing -> do-			home <- homeDirectory <$> getUserEntryForName u-			return $ home </> ".ssh" </> "id_" ++ fromKeyType keytype ++ ext-		Just f -> return $ f ++ ext+		Nothing -> relhomessh $ "id_" ++ fromKeyType keytype ++ ext+		Just f+			| isRelative f -> relhomessh (f ++ ext)+			| otherwise -> return (f ++ ext)+	relhomessh f = do+		home <- homeDirectory <$> getUserEntryForName u+		return $ home </> ".ssh" </> f  fromKeyType :: SshKeyType -> String fromKeyType SshRsa = "rsa"
src/Propellor/Property/Systemd.hs view
@@ -278,15 +278,20 @@ 	-- Chroot provisioning is run in systemd-only mode, 	-- which sets up the chroot and ensures systemd and dbus are 	-- installed, but does not handle the other properties.-	chrootprovisioned = Chroot.provisioned' chroot True+	chrootprovisioned = Chroot.provisioned' chroot True [FilesystemContained]  	-- Use nsenter to enter container and and run propellor to 	-- finish provisioning. 	containerprovisioned :: RevertableProperty Linux Linux 	containerprovisioned =-		tightenTargets (Chroot.propellChroot chroot (enterContainerProcess c) False)+		tightenTargets (Chroot.propellChroot chroot (enterContainerProcess c) False containercaps) 			<!> 		doNothing++	containercaps = +		[ FilesystemContained+		, HostnameContained+		]  	chroot = Chroot.Chroot loc builder Chroot.propagateChrootInfo h 
src/Propellor/Property/Uboot.hs view
@@ -3,7 +3,7 @@ import Propellor.Base import Propellor.Types.Info import Propellor.Types.Bootloader-import Propellor.Property.Chroot+import Propellor.Types.Container import Propellor.Property.Mount import qualified Propellor.Property.Apt as Apt @@ -14,7 +14,7 @@ -- -- This includes writing it to the boot sector. sunxi :: BoardName -> Property (HasInfo + DebianLike)-sunxi boardname = setInfoProperty (check (not <$> inChroot) go) info+sunxi boardname = setInfoProperty (check (not <$> hasContainerCapability FilesystemContained) go) info 	`requires` Apt.installed ["u-boot", "u-boot-sunxi"]   where 	go :: Property Linux
src/Propellor/Property/User.hs view
@@ -148,6 +148,10 @@ homedir :: User -> IO FilePath homedir (User user) = homeDirectory <$> getUserEntryForName user +primaryGroup :: User -> IO Group+primaryGroup (User u) = Group <$> groupName <$>+	(getGroupEntryForID =<< (userGroupID <$> getUserEntryForName u))+ hasGroup :: User -> Group -> Property DebianLike hasGroup (User user) (Group group') = tightenTargets $ check test go 	`describe` unwords ["user", user, "in group", group']@@ -187,6 +191,14 @@ 		, "debian-tor" 		, "lpadmin" 		]++-- | Ensures that a file is owned by a user, and also by that user's primary+-- group.+ownsWithPrimaryGroup :: User -> FilePath -> Property UnixLike+ownsWithPrimaryGroup user@(User u) f =+	property' (f ++ " has owner " ++ u) $ \w -> do+		group <- liftIO $ primaryGroup user+		ensureProperty w $ File.ownerGroup f user group  -- | Controls whether shadow passwords are enabled or not. shadowConfig :: Bool -> Property DebianLike
src/Propellor/Types/CmdLine.hs view
@@ -2,6 +2,7 @@  import Propellor.Types.OS import Propellor.Types.PrivData+import Propellor.Types.Container  import System.Posix.Types @@ -25,7 +26,7 @@ 	| Relay HostName 	| DockerInit HostName 	| DockerChain HostName String-	| ChrootChain HostName FilePath Bool Bool+	| ChrootChain HostName FilePath Bool Bool [ContainerCapability] 	| GitPush Fd Fd 	| Check 	| Build
src/Propellor/Types/Container.hs view
@@ -1,7 +1,9 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies, FlexibleInstances #-}  module Propellor.Types.Container where +import Propellor.Types.Info+ -- | A value that can be bound between the host and a container. -- -- For example, a Bound Port is a Port on the container that is bound to@@ -28,3 +30,18 @@ same :: v -> Bound v same v = Bound v v +-- | Capabilities of a container.+data ContainerCapability+	= HostnameContained+	-- ^ The container has its own hostname (and domain name)+	-- separate from the system that contains it.+	| FilesystemContained+	-- ^ The container has its own root filesystem, rather than sharing+	-- the root filesystem of the system that contains it.+	deriving (Typeable, Eq, Read, Show)++-- | A [ContainerCapability] can be used as Info.+-- It does not propagate out to the Host.+-- When not in a container, the Info value will be [].+instance IsInfo [ContainerCapability] where+        propagateInfo _ = PropagateInfo False