summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/changelog10
-rw-r--r--doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_5_61d7ef8a61ac7b922c810825d794da5f._comment8
-rw-r--r--doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_6_ceddc6d118b7ea71ec8f498960a5fe97._comment8
-rw-r--r--doc/news/Linux.Conf.Au.presentation.mdwn5
-rw-r--r--doc/news/version_3.3.1.mdwn8
-rw-r--r--doc/news/version_4.3.1.mdwn4
-rw-r--r--doc/news/version_4.3.3.mdwn17
-rw-r--r--doc/news/version_4.3.4.mdwn7
-rw-r--r--doc/todo/differential_update_via_RevertableProperty.mdwn146
-rw-r--r--doc/todo/merge_request:_Timezone.hs.mdwn7
-rw-r--r--doc/todo/sbuild_setup_should_use_apt-cacher-ng.mdwn23
-rw-r--r--propellor.cabal3
-rw-r--r--src/Propellor/Property/LightDM.hs2
-rw-r--r--src/Propellor/Property/Versioned.hs112
-rw-r--r--src/Propellor/Types.hs4
15 files changed, 338 insertions, 26 deletions
diff --git a/debian/changelog b/debian/changelog
index c313a2c6..a60c5f18 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+propellor (4.3.4) unstable; urgency=medium
+
+ * Propellor.Property.Versioned: New module which allows different
+ versions of a property or host to be written down in a propellor config
+ file. Has many applications, including staged upgrades and rollbacks.
+ * LightDM.autoLogin: Use [Seat:*] rather than the old [SeatDefaults].
+ The new name has been supported since lightdm 1.15.
+
+ -- Joey Hess <id@joeyh.name> Sat, 15 Jul 2017 17:22:53 -0400
+
propellor (4.3.3) unstable; urgency=medium
* Hosts can be configured to build propellor using stack, by adding
diff --git a/doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_5_61d7ef8a61ac7b922c810825d794da5f._comment b/doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_5_61d7ef8a61ac7b922c810825d794da5f._comment
new file mode 100644
index 00000000..35c894b0
--- /dev/null
+++ b/doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_5_61d7ef8a61ac7b922c810825d794da5f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 5"
+ date="2017-07-14T10:58:33Z"
+ content="""
+The new \"bootstrapWith (Robustly Stack)\" and \"bootstrapWith OSOnly\" properties completely address my concerns. Thanks!
+"""]]
diff --git a/doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_6_ceddc6d118b7ea71ec8f498960a5fe97._comment b/doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_6_ceddc6d118b7ea71ec8f498960a5fe97._comment
new file mode 100644
index 00000000..32ed86f8
--- /dev/null
+++ b/doc/forum/Why_downloading_package_list_from_hackage.haskell.org__63__/comment_6_ceddc6d118b7ea71ec8f498960a5fe97._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="gueux"
+ avatar="http://cdn.libravatar.org/avatar/2982bac2c2cd94ab3860efb189deafc8"
+ subject="comment 6"
+ date="2017-07-14T11:16:10Z"
+ content="""
+(I did not try to build propellor again on this 128Mo host yet, though)
+"""]]
diff --git a/doc/news/Linux.Conf.Au.presentation.mdwn b/doc/news/Linux.Conf.Au.presentation.mdwn
deleted file mode 100644
index 54180979..00000000
--- a/doc/news/Linux.Conf.Au.presentation.mdwn
+++ /dev/null
@@ -1,5 +0,0 @@
-<video controls src="http://mirror.linux.org.au/pub/linux.conf.au/2017/Type_driven_configuration_management_with_Propellor.webm"></video>
-
-[video](http://mirror.linux.org.au/pub/linux.conf.au/2017/Type_driven_configuration_management_with_Propellor.webm)
-
-Also see this writeup in [Linux Weekly News](https://lwn.net/Articles/713653/)
diff --git a/doc/news/version_3.3.1.mdwn b/doc/news/version_3.3.1.mdwn
deleted file mode 100644
index 84ab72f1..00000000
--- a/doc/news/version_3.3.1.mdwn
+++ /dev/null
@@ -1,8 +0,0 @@
-propellor 3.3.1 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * Apt: Removed the mirrors.kernel.org line from stdSourcesList etc.
- The mirror CDN has a new implementation that should avoid the problems
- with httpredir that made an extra mirror sometimes be needed.
- * Switch Debian CDN address to deb.debian.org.
- * Tor.hiddenService: Fix bug in torrc's HiddenServicePort configuration.
- Thanks, Félix Sipma"""]] \ No newline at end of file
diff --git a/doc/news/version_4.3.1.mdwn b/doc/news/version_4.3.1.mdwn
deleted file mode 100644
index 5c07307d..00000000
--- a/doc/news/version_4.3.1.mdwn
+++ /dev/null
@@ -1,4 +0,0 @@
-propellor 4.3.1 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * Added Propellor.Property.FreeDesktop module.
- * Added reservedSpacePercentage to the PartSpec EDSL."""]] \ No newline at end of file
diff --git a/doc/news/version_4.3.3.mdwn b/doc/news/version_4.3.3.mdwn
new file mode 100644
index 00000000..b51ab5df
--- /dev/null
+++ b/doc/news/version_4.3.3.mdwn
@@ -0,0 +1,17 @@
+propellor 4.3.3 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * Hosts can be configured to build propellor using stack, by adding
+ a property:
+ &amp; bootstrapWith (Robustly Stack)
+ * Hosts can be configured to build propellor using cabal, but using
+ only packages installed from the operating system. This
+ will work on eg Debian:
+ &amp; bootstrapWith OSOnly
+ * Iproved fix for bug that sometimes made --spin fail with
+ "fatal: Couldn't find remote ref HEAD". The previous fix didn't work
+ reliably.
+ * User: add systemGroup and use it for systemAccountFor'
+ Thanks, Félix Sipma.
+ * Export a Restic.backup' property.
+ Thanks, Félix Sipma.
+ * Updated stack config to lts-8.22."""]] \ No newline at end of file
diff --git a/doc/news/version_4.3.4.mdwn b/doc/news/version_4.3.4.mdwn
new file mode 100644
index 00000000..5d308401
--- /dev/null
+++ b/doc/news/version_4.3.4.mdwn
@@ -0,0 +1,7 @@
+propellor 4.3.4 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * Propellor.Property.Versioned: New module which allows different
+ versions of a property or host to be written down in a propellor config
+ file. Has many applications, including staged upgrades and rollbacks.
+ * LightDM.autoLogin: Use [Seat:*] rather than the old [SeatDefaults].
+ The new name has been supported since lightdm 1.15."""]] \ No newline at end of file
diff --git a/doc/todo/differential_update_via_RevertableProperty.mdwn b/doc/todo/differential_update_via_RevertableProperty.mdwn
new file mode 100644
index 00000000..3eb9bc7a
--- /dev/null
+++ b/doc/todo/differential_update_via_RevertableProperty.mdwn
@@ -0,0 +1,146 @@
+Long ago, nomeata pointed out that RevertableProperty required the user to
+keep track of different versions of a Host, in a way that should be able to
+be automated. When the user decides to revert a RevertableProperty, they
+have to keep the reverted property on the Host until propellor runs there,
+and only then can remove it.
+
+What if instead, there was a way to store the old version of a Host
+somewhere. Let's not worry about where or how, but assume we have
+`(old, new) :: (Host, Host)`
+
+Propellor could compare `old` and `new`, and if it finds a
+RevertableProperty in `old` that is not in `new`, add it in reverted form
+to `new'`.
+
+Also, if propellor finds a Property in `old` that is not in `new`, it can
+tell the user that this Property needs to be reverted, but cannot be, so
+`new` won't fully describe the state of the host. --[[Joey]]
+
+----
+
+There are a lot of ways such a capability could be used, especially if
+there were a way to pull the old version of a Host out of a previous
+version of config.hs or something like that. But leaving aside such magic,
+here are some nice use cases:
+
+* Suppose we want to generate several disk images, which are somewhat
+ similar, but differ in some properties. Rather than building a separate
+ chroot for each, we can build a chroot for the first, update the first
+ disk image, compare that with the second and update the chroot
+ accordingly, and so on.
+* When propellor is used to build a OS installer disk image, that installer
+ could know the properties used to create it, and the properties of the
+ system that is desired to be installed. To install, it can rsync the
+ installer disk contents to `/target` and then run propellor in `/target`,
+ differentially updating it as needed.
+
+----
+
+Here's the catch: It can't be implemented currently! The comparison of
+properties needs an `Eq` instance for Property (and RevertableProperty).
+But, a property contains an action in the IO monad, which can't have an
+`Eq` instance, and so there's no good way to compare properties.
+
+Making propellor use an ESDL could get us `Eq`. But it would make it rather
+clumsy to write properties, something like this.
+
+<pre>
+appendfoo f = WriteFile f (ListAppend "foo" (ReadFile f))
+</pre>
+
+(Perhaps a deeply embedded DSL would be better.)
+
+Could a Free monad get us `Eq`? Well, there can apparently be free monads that
+have an `Eq` instance, but I tried building one for a simple teletype, and
+failed, which does not bode well. Here's the code; this fails to compile
+because of a missing instance `(Eq1 ((->) String))`, and of course comparing
+functions for equality is not generally feasible.
+
+<pre>
+{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}
+
+import Control.Monad.Free
+import Prelude.Extras
+
+data TeletypeF x
+ = PutStrLn String x
+ | GetLine (String -> x)
+
+instance Functor TeletypeF where
+ fmap f (PutStrLn str x) = PutStrLn str (f x)
+ fmap f (GetLine k) = GetLine (f . k)
+
+instance (Eq1 ((->) String)) => Eq1 TeletypeF where
+ PutStrLn a x ==# PutStrLn b y = a == b && x == y
+ GetLine a ==# GetLine b = a ==# b
+
+type Teletype = Free TeletypeF
+
+putStrLn' :: String -> Teletype ()
+putStrLn' str = liftF $ PutStrLn str ()
+
+getLine' :: Teletype String
+getLine' = liftF $ GetLine id
+
+foo :: Teletype ()
+foo = do
+ putStrLn' "name?"
+ name <- getLine'
+ putStrLn' ("hello, " ++ name)
+
+fooisfoo :: Bool
+fooisfoo = foo ==# foo
+</pre>
+
+-----
+
+## the best we can do without Eq
+
+Is, perhaps:
+
+ data Version = A | B | C
+ deriving (Enum, Ord)
+
+ foo :: Versioned Hoso
+ foo = versionedHost "foo" $ do
+ ver A someprop
+ <|> othervers otherprop
+ ver A somerevertableprop
+ ver [B, C] newprop
+
+That's ... pretty ok, would hit as least some of the use cases described
+above. Seems to need a Reader+Writer monad to implement it,
+without passing the Version around explicitly.
+
+Is it allowable for `newprop` to not be revertable?
+Once `foo` gets that property, it is never removed if we're moving only
+forwards. On the other hand, perhaps the user will want to roll back to
+version A. Allowing rollbacks seems good, so `inVersion` should only
+accept `RevertableProperty`.
+
+Another interesting case is this:
+
+ foo = versionedHost "foo" $ do
+ ver A bar
+ always otherprop
+ ver [B, C] bar
+
+Is version A of foo identical to verion B? If so, this should be allowed to
+compile even when `bar` cannot be reverted. On the other hand, perhaps
+ordering of the properties matters, in which case the systems are subtly
+different, and there's no way to get from A to B.
+
+It's certianly possible for ordering to matter in propellor properties,
+although it's generally a bug when it does. So, it seems ok for this
+case to be rejected.
+
+As well as `Versioned Host`, it would be possible to have
+`Versioned (Property metatypes)`.
+Indeed, that would make sense to he used internally in the
+examples above. And that allows composition of properties with versioning:
+
+ someprop :: Versioned (Property DebianLike)
+ someprop = versionedProperty $ do
+ ver A foo <|> ver [B, C] bar
+
+> [[done]] in Propellor.Property.Versioned. --[[Joey]]
diff --git a/doc/todo/merge_request:_Timezone.hs.mdwn b/doc/todo/merge_request:_Timezone.hs.mdwn
new file mode 100644
index 00000000..3f67da2c
--- /dev/null
+++ b/doc/todo/merge_request:_Timezone.hs.mdwn
@@ -0,0 +1,7 @@
+Please consider merging branch `timezone` of repo `https://git.spwhitton.name/propellor`.
+
+Adds `Timezone.configured`.
+
+I think that this works fine on stretch, but on Jessie there is some oddness. For example, if you set the timezone of a host to `US/Arizona`, the apt reconfiguration will put `America/Phoenix` in /etc/timezone, resulting in the property reporting a change every time that it is run. I think this is harmless.
+
+--spwhitton
diff --git a/doc/todo/sbuild_setup_should_use_apt-cacher-ng.mdwn b/doc/todo/sbuild_setup_should_use_apt-cacher-ng.mdwn
index 450416f2..62f619db 100644
--- a/doc/todo/sbuild_setup_should_use_apt-cacher-ng.mdwn
+++ b/doc/todo/sbuild_setup_should_use_apt-cacher-ng.mdwn
@@ -1,11 +1,20 @@
-The properties in `Sbuild.hs` should use apt-cacher-ng instead of a bind mount of `/var/cache/apt/archives`. This has at least three advantages:
+Please consider merging branch `apt-cacher-ng` of repo `https://git.spwhitton.name/propellor`.
-1. more than one instance of sbuild can run at once
+Sample text for changelog/description of changes:
-2. sbuild can run even if apt is doing something else with its cache
-
-3. the `piupartsConf` properties are no longer needed.
+ * Add Apt.proxy property to set a host's apt proxy.
+ * Add Apt.useLocalCacher property to set up apt-cacher-ng.
+ * Rework Sbuild properties to use apt proxies/cachers instead of bind-mounting
+ the host's apt cache. This makes it possible to run more than one build at
+ a time, and lets sbuild run even if apt's cache is locked by the host's apt.
+ - If Apt.proxy is set, it is assumed that the proxy does some sort of
+ caching, and sbuild chroots are set up to use the same proxy.
+ - If Apt.proxy is not set, we install apt-cacher-ng, and point sbuild
+ chroots at the local apt cacher.
+ - Drop Sbuild.piupartsConfFor, Sbuild.piupartsConf, Sbuild.shareAptCache
+ (API change)
+ No longer needed now that we are using apt proxies/cachers.
+ - Update sample config in haddock for Propellor.Property.Sbuild.
+ Please compare both your config.hs and your ~/.sbuildrc against the haddock.
--spwhitton
-
-[[!tag user/spwhitton]]
diff --git a/propellor.cabal b/propellor.cabal
index 3c2477b9..733dda3e 100644
--- a/propellor.cabal
+++ b/propellor.cabal
@@ -1,5 +1,5 @@
Name: propellor
-Version: 4.3.3
+Version: 4.3.4
Cabal-Version: >= 1.20
License: BSD2
Maintainer: Joey Hess <id@joeyh.name>
@@ -154,6 +154,7 @@ Library
Propellor.Property.Unbound
Propellor.Property.User
Propellor.Property.Uwsgi
+ Propellor.Property.Versioned
Propellor.Property.XFCE
Propellor.Property.ZFS
Propellor.Property.ZFS.Process
diff --git a/src/Propellor/Property/LightDM.hs b/src/Propellor/Property/LightDM.hs
index 69538d89..44f0e9f0 100644
--- a/src/Propellor/Property/LightDM.hs
+++ b/src/Propellor/Property/LightDM.hs
@@ -12,6 +12,6 @@ installed = Apt.installed ["lightdm"]
-- | Configures LightDM to skip the login screen and autologin as a user.
autoLogin :: User -> Property DebianLike
autoLogin (User u) = "/etc/lightdm/lightdm.conf" `ConfFile.containsIniSetting`
- ("SeatDefaults", "autologin-user", u)
+ ("Seat:*", "autologin-user", u)
`describe` "lightdm autologin"
`requires` installed
diff --git a/src/Propellor/Property/Versioned.hs b/src/Propellor/Property/Versioned.hs
new file mode 100644
index 00000000..58d3e8d5
--- /dev/null
+++ b/src/Propellor/Property/Versioned.hs
@@ -0,0 +1,112 @@
+{-# LANGUAGE RankNTypes, FlexibleContexts, TypeFamilies #-}
+
+-- | Versioned properties and hosts.
+--
+-- When importing and using this module, you will need to enable some
+-- language extensions:
+--
+-- > {-# LANGUAGE RankNTypes, FlexibleContexts, TypeFamilies #-}
+--
+-- This module takes advantage of `RevertableProperty` to let propellor
+-- switch cleanly between versions. The way it works is all revertable
+-- properties for other versions than the current version are first
+-- reverted, and then propellor ensures the property for the current
+-- version. This method should work for any combination of revertable
+-- properties.
+--
+-- For example:
+--
+-- > demo :: Versioned Int (RevertableProperty DebianLike DebianLike)
+-- > demo ver =
+-- > ver ( (== 1) --> Apache.modEnabled "foo"
+-- > `requires` Apache.modEnabled "foosupport"
+-- > <|> (== 2) --> Apache.modEnabled "bar"
+-- > <|> (> 2) --> Apache.modEnabled "baz"
+-- > )
+-- >
+-- > foo :: Host
+-- > foo = host "foo.example.com" $ props
+-- > & demo `version` (2 :: Int)
+--
+-- Similarly, a whole Host can be versioned. For example:
+--
+-- > bar :: Versioned Int Host
+-- > bar ver = host "bar.example.com" $ props
+-- > & osDebian Unstable X86_64
+-- > & ver ( (== 1) --> Apache.modEnabled "foo"
+-- > <|> (== 2) --> Apache.modEnabled "bar"
+-- > )
+-- > & ver ( (>= 2) --> Apt.unattendedUpgrades )
+--
+-- Note that some versioning of revertable properties may cause
+-- propellor to do a lot of unnecessary work each time it's run.
+-- Here's an example of such a problem:
+--
+-- > slow :: Versioned Int -> RevertableProperty DebianLike DebianLike
+-- > slow ver =
+-- > ver ( (== 1) --> (Apt.installed "foo" <!> Apt.removed "foo")
+-- > <|> (== 2) --> (Apt.installed "bar" <!> Apt.removed "bar")
+-- > )
+--
+-- Suppose that package bar depends on package foo. Then at version 2,
+-- propellor will remove package foo in order to revert version 1, only
+-- to re-install it since version 2 also needs it installed.
+
+module Propellor.Property.Versioned (Versioned, version, (-->), (<|>)) where
+
+import Propellor
+
+-- | Something that has multiple versions of type `v`.
+type Versioned v t = VersionedBy v -> t
+
+type VersionedBy v
+ = forall metatypes. Combines (RevertableProperty metatypes metatypes) (RevertableProperty metatypes metatypes)
+ => (CombinedType (RevertableProperty metatypes metatypes) (RevertableProperty metatypes metatypes) ~ RevertableProperty metatypes metatypes)
+ => (VerSpec v metatypes -> RevertableProperty metatypes metatypes)
+
+-- | Access a particular version of a Versioned value.
+version :: (Versioned v t) -> v -> t
+version f v = f (processVerSpec v)
+
+-- A specification of versions.
+--
+-- Why is this not a simple list like
+-- [(v -> Bool, RevertableProperty metatypes metatypes)] ?
+-- Using a list would mean the empty list would need to be dealt with,
+-- and processVerSpec does not have a Monoid instance for
+-- RevertableProperty metatypes metatypes in scope, and due to the way the
+-- Versioned type works, the compiler cannot find such an instance.
+--
+-- Also, using this data type allows a nice syntax for creating
+-- VerSpecs, via the `<&>` and `alt` functions.
+data VerSpec v metatypes
+ = Base (v -> Bool, RevertableProperty metatypes metatypes)
+ | More (v -> Bool, RevertableProperty metatypes metatypes) (VerSpec v metatypes)
+
+processVerSpec
+ :: Combines (RevertableProperty metatypes metatypes) (RevertableProperty metatypes metatypes)
+ => (CombinedType (RevertableProperty metatypes metatypes) (RevertableProperty metatypes metatypes) ~ RevertableProperty metatypes metatypes)
+ => v
+ -> VerSpec v metatypes
+ -> RevertableProperty metatypes metatypes
+processVerSpec v (Base (c, p))
+ | c v = p
+ | otherwise = revert p
+processVerSpec v (More (c, p) vs)
+ | c v = processVerSpec v vs `before` p
+ | otherwise = revert p `before` processVerSpec v vs
+
+-- | Specify a function that checks the version, and what
+-- `RevertableProperty` to use if the version matches.
+(-->) :: (v -> Bool) -> RevertableProperty metatypes metatypes -> VerSpec v metatypes
+c --> p = Base (c, p)
+
+-- | Add an alternate version.
+(<|>) :: VerSpec v metatypes -> VerSpec v metatypes -> VerSpec v metatypes
+Base a <|> Base b = More a (Base b)
+Base a <|> More b c = More a (More b c)
+More b c <|> Base a = More a (More b c)
+More a b <|> More c d = More a (More c (b <|> d))
+
+infixl 8 -->
+infixl 2 <|>
diff --git a/src/Propellor/Types.hs b/src/Propellor/Types.hs
index 155662c2..b7c7c7f7 100644
--- a/src/Propellor/Types.hs
+++ b/src/Propellor/Types.hs
@@ -107,6 +107,10 @@ adjustPropertySatisfy (Property t d s i c) f = Property t d (f <$> s) i c
-- | A property that can be reverted. The first Property is run
-- normally and the second is run when it's reverted.
+--
+-- See `Propellor.Property.Versioned.Versioned`
+-- for a way to use RevertableProperty to define different
+-- versions of a host.
data RevertableProperty setupmetatypes undometatypes = RevertableProperty
{ setupRevertableProperty :: Property setupmetatypes
, undoRevertableProperty :: Property undometatypes