summaryrefslogtreecommitdiff
path: root/doc/todo
diff options
context:
space:
mode:
Diffstat (limited to 'doc/todo')
-rw-r--r--doc/todo/Bug_in_Property.Ssh.authorizedKey.mdwn8
-rw-r--r--doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties.mdwn25
-rw-r--r--doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_1_c8240ba3abf5cf458eba8ed7e31eaccf._comment25
-rw-r--r--doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_2_9303138a3be2fb639498737afe60b87d._comment11
-rw-r--r--doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_3_92c583f883fae2b447c1598356efade2._comment41
-rw-r--r--doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_4_2049a1ce601ba77f4139f844d0fd91b2._comment13
-rw-r--r--doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_5_4caff287eb767d481bb7ef87e62c508b._comment10
-rw-r--r--doc/todo/HostingProvider_for_AWS.mdwn1
-rw-r--r--doc/todo/HostingProvider_for_AWS/comment_1_9db50a3f4fef8e10261e3e29dbd90e73._comment22
-rw-r--r--doc/todo/Manage_DNS_with_Route53.mdwn1
-rw-r--r--doc/todo/Manage_DNS_with_Route53/comment_1_dfa93678644b72781afda4fdc9d0da31._comment21
-rw-r--r--doc/todo/Manage_DNS_with_Route53/comment_2_a6c1ace47d5387d0b1559266ca124525._comment8
-rw-r--r--doc/todo/Manage_DNS_with_Route53/comment_3_a521a1b875526d8b65e76f11ed367a36._comment8
-rw-r--r--doc/todo/Propellor.Property.Ssh:_it_should_be_possible_to_call_permitRootLogin_with___34__forced-commands-only__34___and___34__without-password__34__.mdwn5
-rw-r--r--doc/todo/Push_2.4.0_to_Hackage.mdwn4
-rw-r--r--doc/todo/Wishlist:_User.hasLoginShell.mdwn9
-rw-r--r--doc/todo/Wishlist:_User.hasLoginShell/comment_1_c02e8783b91c3c0326bf1b317be4694f._comment59
-rw-r--r--doc/todo/bytes_in_privData__63__.mdwn17
-rw-r--r--doc/todo/bytes_in_privData__63__/comment_1_42c107179b091f74ef55aff1fc240c5e._comment19
-rw-r--r--doc/todo/bytes_in_privData__63__/comment_2_60f577b476adc6ee1e4f18e11843df90._comment7
-rw-r--r--doc/todo/bytes_in_privData__63__/comment_3_55f34128de77b7947d32fac71071e033._comment7
-rw-r--r--doc/todo/bytes_in_privData__63__/comment_4_f34a8f82c7bce7224e4edc59410c741f._comment19
-rw-r--r--doc/todo/bytes_in_privData__63__/comment_5_f4db6ffad054feb7eb299708fcd7d05c._comment15
-rw-r--r--doc/todo/bytes_in_privData__63__/comment_6_545e1c26a042b9f8347496a1bfb61548._comment48
-rw-r--r--doc/todo/bytes_in_privData__63__/comment_7_d6c4c2645696eac448e906d812c2de62._comment25
-rw-r--r--doc/todo/concurrency.mdwn111
-rw-r--r--doc/todo/depend_on_concurrent-output.mdwn10
-rw-r--r--doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__.mdwn9
-rw-r--r--doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__/comment_1_892385793c38976d0c446906dd004772._comment10
-rw-r--r--doc/todo/docker_todo_list.mdwn2
-rw-r--r--doc/todo/dynamic_Info.mdwn4
-rw-r--r--doc/todo/editor_for_privdata__63__.mdwn4
-rw-r--r--doc/todo/editor_for_privdata__63__/comment_2_4fcbdf36f32ca7cf82593a8992167aff._comment9
-rw-r--r--doc/todo/etckeeper.mdwn1
-rw-r--r--doc/todo/etckeeper/comment_1_8766da27c69bbae357d497e0e557fad2._comment9
-rw-r--r--doc/todo/fail_if_modification_not_commited_when_using_--spin.mdwn3
-rw-r--r--doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_1_7267d62ccc8db44bccb935836536e8a1._comment30
-rw-r--r--doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_2_e4d170a14d689bef5d9174b251a4fe6f._comment7
-rw-r--r--doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_3_c69eaa9c6ae5b07b5c2dd2591de965a3._comment19
-rw-r--r--doc/todo/git_push_over_propellor_ssh_channel.mdwn13
-rw-r--r--doc/todo/hooks/comment_1_4ca9e46f36d0fae334d9c2f2c211d0e3._comment14
-rw-r--r--doc/todo/info_propigation_out_of_nested_properties.mdwn111
-rw-r--r--doc/todo/issue_after_upgrading_shared_library.mdwn25
-rw-r--r--doc/todo/issue_after_upgrading_shared_library/comment_1_8d9144d57871cb5d234710d1ab1b7183._comment20
-rw-r--r--doc/todo/issue_after_upgrading_shared_library/comment_2_01a3d5e006158302e12862cacee3327e._comment7
-rw-r--r--doc/todo/issue_after_upgrading_shared_library/comment_2_6025ec35330fbac220f2888e60be1e78._comment17
-rw-r--r--doc/todo/lxc_containers_support.mdwn1
-rw-r--r--doc/todo/missing_dependencies.mdwn39
-rw-r--r--doc/todo/missing_dependencies/comment_1_826a75052e87c04489aa07c3d322a54f._comment15
-rw-r--r--doc/todo/onChange_failure_handling.mdwn41
-rw-r--r--doc/todo/port_info_for_properties_for_firewall.mdwn24
-rw-r--r--doc/todo/publish_propellor_as_library_to_hackage.mdwn4
-rw-r--r--doc/todo/publish_propellor_as_library_to_hackage/comment_1_00a865bf7977c0e49f54a365f4b60ce8._comment27
-rw-r--r--doc/todo/publish_propellor_as_library_to_hackage/comment_2_29cc276929020e68eae8ae04110a3f5f._comment17
-rw-r--r--doc/todo/publish_propellor_as_library_to_hackage/comment_3_efbe0ef77be957c37e745ec64452ae99._comment10
-rw-r--r--doc/todo/publish_propellor_as_library_to_hackage/comment_4_6ebf2e30596ddf6eba91717576837019._comment8
-rw-r--r--doc/todo/publish_propellor_as_library_to_hackage/comment_5_4a4e94c637e0380adc1a43ec3d0633e1._comment8
-rw-r--r--doc/todo/publish_propellor_as_library_to_hackage/comment_6_19470170c3ef461f446b0af1d8501640._comment8
-rw-r--r--doc/todo/revertable_Ssh.authorizedKey.mdwn1
-rw-r--r--doc/todo/revertable_Ssh.authorizedKey/comment_1_6c11976a814a7f4a830bc11ae9bf534e._comment11
-rw-r--r--doc/todo/spin_and_ipv6_addresses.mdwn1
-rw-r--r--doc/todo/spin_without_remote_compilation.mdwn1
-rw-r--r--doc/todo/spin_without_remote_compilation/comment_1_10d797b43df9252c34a02c3fd249374b._comment45
-rw-r--r--doc/todo/spin_without_remote_compilation/comment_2_1c3176559695d33bd7e183b9734e430f._comment8
-rw-r--r--doc/todo/ssh__95__user_+_sudo/comment_4_7fc635a8d6e4c903eaefa7383d2c37ac._comment8
-rw-r--r--doc/todo/support_tarball_source_images.mdwn5
-rw-r--r--doc/todo/support_tarball_source_images/comment_1_6c019767a6a678d7d9f7ad924e948d94._comment17
-rw-r--r--doc/todo/support_tarball_source_images/comment_2_2d620f837f825f3041d9c66612e2ab4c._comment8
-rw-r--r--doc/todo/support_tarball_source_images/comment_3_411e4884c47fa6c371e6c6d2c5472752._comment8
-rw-r--r--doc/todo/support_tarball_source_images/comment_4_df41bdafff9277fb105ea2da0b0af5d9._comment37
-rw-r--r--doc/todo/support_tarball_source_images/comment_5_fec2c4bf3d0ea806c94b0720b5e80aea._comment8
-rw-r--r--doc/todo/support_tarball_source_images/comment_6_7f06f7f03d943649d24b8c5708bbb952._comment7
-rw-r--r--doc/todo/systemd_unit_integration.mdwn1
-rw-r--r--doc/todo/systemd_unit_integration/comment_1_cc7f255bc8ca5a6e46f0f08889ceac06._comment10
-rw-r--r--doc/todo/type_level_port_conflict_detection.mdwn7
-rw-r--r--doc/todo/typo_in_propagate.mdwn6
76 files changed, 1227 insertions, 27 deletions
diff --git a/doc/todo/Bug_in_Property.Ssh.authorizedKey.mdwn b/doc/todo/Bug_in_Property.Ssh.authorizedKey.mdwn
new file mode 100644
index 00000000..7a59fc20
--- /dev/null
+++ b/doc/todo/Bug_in_Property.Ssh.authorizedKey.mdwn
@@ -0,0 +1,8 @@
+If Ssh.authorizedKey in propellor 2.0.0 is used to create .ssh/authorized_keys for
+a user other than root, it will be owned by root:root and won't
+work for the user. Adding a key to an existing authorized_keys
+file doesn't change its ownership and therefore works fine.
+
+-- weinzwang
+
+> Thanks, [[fixed|done]] this and will make a release.
diff --git a/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties.mdwn b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties.mdwn
new file mode 100644
index 00000000..57cbc343
--- /dev/null
+++ b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties.mdwn
@@ -0,0 +1,25 @@
+# `File.containsConfPair` property
+
+A property to set `key = value` pairs under particular `[sections]` in config files. For example, in stock Debian Jessie `/etc/lightdm/lightdm.conf` contains the lines
+
+ [SeatDefaults]
+ #autologin-user=
+
+With the property
+
+ "/etc/lightdm/lightdm.conf" `File.containsConfPair` ("SeatDefaults", "autologin-user", "swhitton")
+
+this will get set to
+
+ [SeatDefaults]
+ autologin-user=swhitton
+
+# `LightDM.autoLogin` property
+
+An application of `File.containsConfPair` to edit `/etc/lightdm/lightdm.conf` to enable autologin for a specified user: a property encapsulating the above example.
+
+# Patches
+
+Please see the two commits in branch `confpairs` in the repo at `git@github.com:spwhitton/propellor.git`.
+
+> [[merged|done]] --[[Joey]]
diff --git a/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_1_c8240ba3abf5cf458eba8ed7e31eaccf._comment b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_1_c8240ba3abf5cf458eba8ed7e31eaccf._comment
new file mode 100644
index 00000000..a5a2b80c
--- /dev/null
+++ b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_1_c8240ba3abf5cf458eba8ed7e31eaccf._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-08-04T14:23:33Z"
+ content="""
+Thanks for submitting these patches!
+
+Looking at `containsConfPair`, it assumes an ini-style file,
+so is a little misplaced in Property.File. which is otherwise about generic
+text files.
+
+So, it would probably make sense to move it to a new Property.IniFile
+module.
+
+However, [[forum/parsing_a_config_file]] recently pointed out that
+the tor config file has a similar need. It's not ini format, but
+shares the same basic idea of a "section" line which is followed by
+lines setting things specific to that section.
+
+So, it would be great if `containsConfPair` could be generalized to also
+cover that tor config file use case. I think this would be pretty easy;
+just make it take one string containing the whole section line (including
+square brackets for ini file, or whatever for tor config file), and a
+second string containing the whole setting line.
+"""]]
diff --git a/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_2_9303138a3be2fb639498737afe60b87d._comment b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_2_9303138a3be2fb639498737afe60b87d._comment
new file mode 100644
index 00000000..7b01dd71
--- /dev/null
+++ b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_2_9303138a3be2fb639498737afe60b87d._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ subject="comment 2"
+ date="2015-08-05T21:29:04Z"
+ content="""
+Thanks for the input!
+
+I agree that generalising to lines under sections is a good idea, but I don't think it can be as simple as a property taking the full section header and the full settings line. That's because there is a need to update the values of keys under sections: in the example LightDM case, the line `autologin-user=someone` must *replace* any `autologin-user=someone_else`. So the function needs to know the key, not just the whole line.
+
+So to generalise containsConfPair, it might take a section header, key, value and a specification of what kind of config file it is. That specification would be a type containing the comment character, the formatting of section headers and the use of spaces, colons or equals signs between keys and values. What do you think to this?
+"""]]
diff --git a/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_3_92c583f883fae2b447c1598356efade2._comment b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_3_92c583f883fae2b447c1598356efade2._comment
new file mode 100644
index 00000000..a45bc921
--- /dev/null
+++ b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_3_92c583f883fae2b447c1598356efade2._comment
@@ -0,0 +1,41 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2015-08-06T14:54:14Z"
+ content="""
+I'd suggest making it take some helper functions.
+
+Something like these:
+
+ type SectionStart = String -> Bool -- ^ find the line that is the start of the wanted section (eg, == "<Foo>")
+ type SectionEnd = String -> Bool -- ^ find a line that is within the section, but that indicates the end of the section (eg == "</Foo>")
+ type SectionPast = String -> Bool -- ^ find a line that indicates we are past the section (eg, a new section header)
+ type AdjustSection = [String] -> [String] -- ^ run on all lines in the section, including the SectionStart line and any SectionEnd line; can add/delete/modify lines, or even delete entire section
+ type InsertSection = [String] -> [String] -- ^ if SectionStart does not find the section in the file, this is used to insert the section somewhere within it
+
+ adjustSection :: SectionStart -> SectionEnd -> AdjustSection -> InsertSection -> FilePath -> Property
+
+Which seems sufficiently generic; it can even be used to delete entire sections!
+
+Let's see..
+
+ iniHeader header = '[':header++"]"
+
+ adjustIniSection :: String -> AdjustSection -> InsertSection -> Property
+ adjustIniSection header = adjustSection
+ (== iniHeader header)
+ (const False)
+ ("[" `isPrefixOf`)
+
+ containsConfPair header key value = adjustIniSection header
+ go
+ (++ [confheader, confline]) -- add missing section at end
+ where
+ confheader = iniHeader header
+ confline = key ++ "=" ++ value
+ go ls = undefined -- TODO find key= line and change it, or add confline
+
+ removeSection header = adjustIniSection header
+ (const []) -- remove all lines of section
+ id -- add no lines if section is missing
+"""]]
diff --git a/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_4_2049a1ce601ba77f4139f844d0fd91b2._comment b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_4_2049a1ce601ba77f4139f844d0fd91b2._comment
new file mode 100644
index 00000000..f4e0921f
--- /dev/null
+++ b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_4_2049a1ce601ba77f4139f844d0fd91b2._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="spwhitton"
+ subject="comment 4"
+ date="2015-08-17T00:57:54Z"
+ content="""
+Thanks for the ideas. I've implemented them as a new commit to my confpairs branch. Please take a look.
+
+Two points:
+
+1. I dropped the SectionEnd helper function. My implementation of adjustSection didn't need it and I couldn't think up a case where it would be needed.
+
+2. I'm using a tuple `(section, key, value)` as the second argument to `ConfFile.containsIniPair`, rather than just using four arguments as you suggested. If `ConfFile.containsIniPair` takes four arguments, then it cannot be used infix when attached to other properties with the `&` operator, without using extra brackets.
+"""]]
diff --git a/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_5_4caff287eb767d481bb7ef87e62c508b._comment b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_5_4caff287eb767d481bb7ef87e62c508b._comment
new file mode 100644
index 00000000..40f14ec2
--- /dev/null
+++ b/doc/todo/File.containsConfPair___38___LightDM.autoLogin_properties/comment_5_4caff287eb767d481bb7ef87e62c508b._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2015-08-20T14:37:43Z"
+ content="""
+And merged, thanks.
+
+The SectionEnd would be useful for eg, bind-style or apache-style config
+files. However, those probably need a better parser than this one anyway.
+"""]]
diff --git a/doc/todo/HostingProvider_for_AWS.mdwn b/doc/todo/HostingProvider_for_AWS.mdwn
new file mode 100644
index 00000000..fc381afe
--- /dev/null
+++ b/doc/todo/HostingProvider_for_AWS.mdwn
@@ -0,0 +1 @@
+I'd really love to be able to use propellor to manage my AWS services.
diff --git a/doc/todo/HostingProvider_for_AWS/comment_1_9db50a3f4fef8e10261e3e29dbd90e73._comment b/doc/todo/HostingProvider_for_AWS/comment_1_9db50a3f4fef8e10261e3e29dbd90e73._comment
new file mode 100644
index 00000000..71ded884
--- /dev/null
+++ b/doc/todo/HostingProvider_for_AWS/comment_1_9db50a3f4fef8e10261e3e29dbd90e73._comment
@@ -0,0 +1,22 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-05-14T16:19:00Z"
+ content="""
+So there's something here that propellor doesn't yet have a concept of,
+and that's spinning up a VM. Propellor can deploy itself to an existing VM
+pretty well, but getting the VM running isn't something it tries to do.
+
+I imagine that --spin could be extended to support this though.
+Make a Property like `vm AWS`, which tells propellor that the host
+is a VM, and that the VM is hosted on AWS. Then when you run propellor
+--spin, it could set up the VM if it doesn't exist yet.
+
+I don't use AWS currently, so don't have plans to work on this myself,
+although I think it would be a great direction to move in. Happy to help
+with advice, code review, etc.
+
+<http://hackage.haskell.org/package/aws>
+or <http://hackage.haskell.org/package/amazonka>
+are good haskell libraries for working with AWS.
+"""]]
diff --git a/doc/todo/Manage_DNS_with_Route53.mdwn b/doc/todo/Manage_DNS_with_Route53.mdwn
new file mode 100644
index 00000000..b35a37cb
--- /dev/null
+++ b/doc/todo/Manage_DNS_with_Route53.mdwn
@@ -0,0 +1 @@
+I currently use Route53 to manage the DNS for my service. I'd really like to use Propellor to take care of that for me.
diff --git a/doc/todo/Manage_DNS_with_Route53/comment_1_dfa93678644b72781afda4fdc9d0da31._comment b/doc/todo/Manage_DNS_with_Route53/comment_1_dfa93678644b72781afda4fdc9d0da31._comment
new file mode 100644
index 00000000..8836beaa
--- /dev/null
+++ b/doc/todo/Manage_DNS_with_Route53/comment_1_dfa93678644b72781afda4fdc9d0da31._comment
@@ -0,0 +1,21 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-05-14T16:18:37Z"
+ content="""
+I think this would be great. Patches accepted.
+
+If I were going to implement this, I'd use
+<http://hackage.haskell.org/package/amazonka-route53>
+to write the propellor Property.
+
+A question is, what host would the Property be attached to?
+One way to do it would be to make the property be called something like
+`route53Controller`. So then you pick a host, or hosts, and give them this
+property for a domain, and those hosts then take care of making the
+necessary API calls to route53. Presumably some API keys will be needed
+on those hosts, which can be provided via the privdata.
+
+I'm happy to offer advice on implementation, but don't plan to code this up
+myself, as I'm happily self-hosting my DNS servers.
+"""]]
diff --git a/doc/todo/Manage_DNS_with_Route53/comment_2_a6c1ace47d5387d0b1559266ca124525._comment b/doc/todo/Manage_DNS_with_Route53/comment_2_a6c1ace47d5387d0b1559266ca124525._comment
new file mode 100644
index 00000000..9b5150bf
--- /dev/null
+++ b/doc/todo/Manage_DNS_with_Route53/comment_2_a6c1ace47d5387d0b1559266ca124525._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~jml"
+ nickname="jml"
+ subject="comment 2"
+ date="2015-05-15T08:53:34Z"
+ content="""
+Glad you think so. I had a very quick poke around and also discovered [aws-ec2](https://hackage.haskell.org/package/aws-ec2) as well as the amazonka package. Any particular reason for preferring amazonka to aws-ec2?
+"""]]
diff --git a/doc/todo/Manage_DNS_with_Route53/comment_3_a521a1b875526d8b65e76f11ed367a36._comment b/doc/todo/Manage_DNS_with_Route53/comment_3_a521a1b875526d8b65e76f11ed367a36._comment
new file mode 100644
index 00000000..00bb6b04
--- /dev/null
+++ b/doc/todo/Manage_DNS_with_Route53/comment_3_a521a1b875526d8b65e76f11ed367a36._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="mithrandi@311efa1b2b5c4999c2edae7da06fb825899e8a82"
+ nickname="mithrandi"
+ subject="comment 3"
+ date="2015-06-08T01:22:14Z"
+ content="""
+aws-ec2 doesn't seem to support Route53, unless I'm missing something.
+"""]]
diff --git a/doc/todo/Propellor.Property.Ssh:_it_should_be_possible_to_call_permitRootLogin_with___34__forced-commands-only__34___and___34__without-password__34__.mdwn b/doc/todo/Propellor.Property.Ssh:_it_should_be_possible_to_call_permitRootLogin_with___34__forced-commands-only__34___and___34__without-password__34__.mdwn
new file mode 100644
index 00000000..f02ff328
--- /dev/null
+++ b/doc/todo/Propellor.Property.Ssh:_it_should_be_possible_to_call_permitRootLogin_with___34__forced-commands-only__34___and___34__without-password__34__.mdwn
@@ -0,0 +1,5 @@
+It should be possible to call Propellor.Property.Ssh.permitRootLogin with "forced-commands-only" and "without-password", in addition to "True" or "False". It requires to change the type of the function (and maybe to create a new datatype?)...
+
+ permitRootLogin :: Bool -> Property NoInfo
+
+> [[done]] --[[Joey]]
diff --git a/doc/todo/Push_2.4.0_to_Hackage.mdwn b/doc/todo/Push_2.4.0_to_Hackage.mdwn
new file mode 100644
index 00000000..a176f416
--- /dev/null
+++ b/doc/todo/Push_2.4.0_to_Hackage.mdwn
@@ -0,0 +1,4 @@
+https://propellor.branchable.com/news/version_2.4.0/ says that version 2.4.0, but as of today, 2.3.0 is the latest version on Hackage: http://hackage.haskell.org/package/propellor
+
+> Seems the upload must have failed and I didn't notice. re-uploaded;
+> [[done]] --[[Joey]]
diff --git a/doc/todo/Wishlist:_User.hasLoginShell.mdwn b/doc/todo/Wishlist:_User.hasLoginShell.mdwn
new file mode 100644
index 00000000..cf8aa73c
--- /dev/null
+++ b/doc/todo/Wishlist:_User.hasLoginShell.mdwn
@@ -0,0 +1,9 @@
+As far as I can tell there is no easy way to set a user's
+login shell. A Property User.hasLoginShell, which ensures
+that a user has a specified login shell and that said shell
+is in /etc/shells would be really helpful. Sadly, I lack the
+skills to put this together myself :(
+
+-- weinzwang
+
+> patched in and so [[done]] --[[Joey]]
diff --git a/doc/todo/Wishlist:_User.hasLoginShell/comment_1_c02e8783b91c3c0326bf1b317be4694f._comment b/doc/todo/Wishlist:_User.hasLoginShell/comment_1_c02e8783b91c3c0326bf1b317be4694f._comment
new file mode 100644
index 00000000..52043406
--- /dev/null
+++ b/doc/todo/Wishlist:_User.hasLoginShell/comment_1_c02e8783b91c3c0326bf1b317be4694f._comment
@@ -0,0 +1,59 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-04-19T16:07:24Z"
+ content="""
+Propellor makes it very easy to put together a property like this.
+
+Let's start with a property that combines the two properties you mentioned:
+
+ hasLoginShell :: UserName -> FilePath -> Property
+ hasLoginShell user shell = shellSetTo user shell `requires` shellEnabled shell
+
+The shellEnabled property can be easily written using propellor's file
+manipulation properties.
+
+ -- Need to add an import to the top of the source file.
+ import qualified Propellor.Property.File as File
+
+ shellEnabled :: FilePath -> Property
+ shellEnabled shell = "/etc/shells" `File.containsLine` shell
+
+And then, we want to actually change the user's shell. The `chsh(1)`
+program can do that, so we can simply tell propellor the command line to
+run:
+
+ shellSetTo :: UserName -> FilePath -> Property
+ shellSetTo user shell = cmdProperty "chsh" ["--shell", shell, user]
+
+The only remaining problem with this is that shellSetTo runs chsh every
+time, and propellor will always display that it's made a change each time
+it runs, even when it didn't really do much. Now, there's an easy way to
+avoid that problem, we could just tell propellor that it's a trivial
+property, and then it will run chsh every time and not think it made any
+change:
+
+ shellSetTo :: UserName -> FilePath -> Property
+ shellSetTo user shell = trivial $
+ cmdProperty "chsh" ["--shell", shell, user]
+
+But, it's not much harder to do this right. Let's make the property
+check if the user's shell is already set to the desired value and avoid
+doing anything in that case.
+
+ shellSetTo :: UserName -> FilePath -> Property
+ shellSetTo user shell = check needchangeshell $
+ cmdProperty "chsh" ["--shell", shell, user]
+ where
+ needchangeshell = do
+ currshell <- userShell <$> getUserEntryForName user
+ return (currshell /= shell)
+
+And that will probably all work, although I've not tested it. You might
+want to throw in some uses of `describe` to give the new properties
+more useful descriptions.
+
+I hope this has been helpful as an explanation of how to add properties to
+Propellor, and if you get these properties to work, a patch adding them
+to Propellor.User would be happily merged.
+"""]]
diff --git a/doc/todo/bytes_in_privData__63__.mdwn b/doc/todo/bytes_in_privData__63__.mdwn
new file mode 100644
index 00000000..27297fd5
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__.mdwn
@@ -0,0 +1,17 @@
+It seems like I can't set the content of a PrivFile to arbitrary bytes.
+
+ $ propellor --set 'PrivFile "mysecret.key"' 'mycontext' < ~/mysecret.key
+ find . | grep -v /.git/ | grep -v /tmp/ | grep -v /dist/ | grep -v /doc/ | egrep '\.hs$' | xargs hothasktags | perl -ne 'print; s/Propellor\.Property\.//; print' | sort > tags 2>/dev/null || true
+ cabal build
+ Building propellor-2.2.1...
+ Preprocessing library propellor-2.2.1...
+ In-place registering propellor-2.2.1...
+ Preprocessing executable 'propellor' for propellor-2.2.1...
+ Preprocessing executable 'propellor-config' for propellor-2.2.1...
+ [70 of 70] Compiling Main ( src/config.hs, dist/build/propellor-config/propellor-config-tmp/Main.o )
+ Linking dist/build/propellor-config/propellor-config ...
+ ln -sf dist/build/propellor-config/propellor-config propellor
+
+
+ Enter private data on stdin; ctrl-D when done:
+ propellor: <stdin>: hGetContents: invalid argument (invalid byte sequence)
diff --git a/doc/todo/bytes_in_privData__63__/comment_1_42c107179b091f74ef55aff1fc240c5e._comment b/doc/todo/bytes_in_privData__63__/comment_1_42c107179b091f74ef55aff1fc240c5e._comment
new file mode 100644
index 00000000..5c1508fd
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__/comment_1_42c107179b091f74ef55aff1fc240c5e._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-04-20T01:04:26Z"
+ content="""
+I imagine that adding `fileEncoding stdin` to setPrivData will fix
+this crash, but I'd expect there are also other problems with encodings
+for privdata that haskell doesn't like. Similar fixes would probably
+be needed in several other places.
+
+Probably cleaner and better to convert
+`PrivData` from a String to a ByteString, and so avoid encodings
+being applied to it. I think this could be done without changing the
+file format; the privdata file uses Read/Show for serialization,
+and happily ByteString uses the same Read/Show format as String does.
+
+So, changing the type and following the compile errors should get you
+there, I think!
+"""]]
diff --git a/doc/todo/bytes_in_privData__63__/comment_2_60f577b476adc6ee1e4f18e11843df90._comment b/doc/todo/bytes_in_privData__63__/comment_2_60f577b476adc6ee1e4f18e11843df90._comment
new file mode 100644
index 00000000..10ff956a
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__/comment_2_60f577b476adc6ee1e4f18e11843df90._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="gueux"
+ subject="comment 2"
+ date="2015-04-21T12:59:42Z"
+ content="""
+Would you accept a patch converting PrivData from String to ByteString?
+"""]]
diff --git a/doc/todo/bytes_in_privData__63__/comment_3_55f34128de77b7947d32fac71071e033._comment b/doc/todo/bytes_in_privData__63__/comment_3_55f34128de77b7947d32fac71071e033._comment
new file mode 100644
index 00000000..a1c7f62f
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__/comment_3_55f34128de77b7947d32fac71071e033._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2015-04-21T16:52:06Z"
+ content="""
+Absolutely. Thought that went w/o saying. ;)
+"""]]
diff --git a/doc/todo/bytes_in_privData__63__/comment_4_f34a8f82c7bce7224e4edc59410c741f._comment b/doc/todo/bytes_in_privData__63__/comment_4_f34a8f82c7bce7224e4edc59410c741f._comment
new file mode 100644
index 00000000..bd7a0618
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__/comment_4_f34a8f82c7bce7224e4edc59410c741f._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="gueux"
+ subject="comment 4"
+ date="2015-04-23T09:21:07Z"
+ content="""
+I tried to do the conversion, but then it started a kind of chain reaction... (PrivData=ByteString to writeFileProtected to Line=ByteString to ... to readProcess to ...) Should I use FilePath=String? ... To be honest, the patch became a lot bigger that what I am comfortable with. :-)
+
+I guess you should have a look at it...
+
+At least, I think there is a type bug in Propellor.Property.File:
+
+ hasPrivContent' :: (IsContext c, IsPrivDataSource s) => (String -> FilePath -> IO ()) -> s -> FilePath -> c -> Property HasInfo
+
+but it should be
+
+ hasPrivContent' :: (IsContext c, IsPrivDataSource s) => (FilePath -> String -> IO ()) -> s -> FilePath -> c -> Property HasInfo
+
+(it is hidden by FilePath = String)
+"""]]
diff --git a/doc/todo/bytes_in_privData__63__/comment_5_f4db6ffad054feb7eb299708fcd7d05c._comment b/doc/todo/bytes_in_privData__63__/comment_5_f4db6ffad054feb7eb299708fcd7d05c._comment
new file mode 100644
index 00000000..45c97b97
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__/comment_5_f4db6ffad054feb7eb299708fcd7d05c._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2015-04-23T13:25:50Z"
+ content="""
+Can you put the patch up somewhere? I'll take a look. Might see a way to
+short-curcuit the bytestring before everything becomes one..
+
+One way might be:
+
+ writeFileProtected :: FileContent content => FilePath -> content -> IO ()
+
+Which would also at least partly avoid foot-shooting over which parameter is which.
+(Fixed that type signature.)
+"""]]
diff --git a/doc/todo/bytes_in_privData__63__/comment_6_545e1c26a042b9f8347496a1bfb61548._comment b/doc/todo/bytes_in_privData__63__/comment_6_545e1c26a042b9f8347496a1bfb61548._comment
new file mode 100644
index 00000000..29b07e5c
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__/comment_6_545e1c26a042b9f8347496a1bfb61548._comment
@@ -0,0 +1,48 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2015-04-28T19:24:12Z"
+ content="""
+I've followed the same path in the wip-bytestring-privdata branch.
+
+It needs to round trip through String anyway to handle Read/Show
+serialization the same as before. I think this is doable without falling
+over on invalid encodings, but it's certianly ugly.
+
+And yeah, changing Line to ByteString and all the other follow-on changes
+just don't seem right. Everything that uses withPrivData would need to deal
+with it being a ByteString, and would need to worry about encoding problems
+when it needed to convert to a String, or Text, or whatever.
+
+So this feels like kicking the can down the road in the wrong direction...
+
+----
+
+Maybe it would be better to handle this by adding a type to wrap up an
+encoded ByteString in the PrivData. Could use base64 or something like
+that for the encoding. Then only consumers of these ByteStrings would be a
+little complicated by needing to unwrap it.
+
+Then it would be handly to give --set, --dump and --edit some
+special handling of fields encoded like that. They could operate on raw
+ByteStrings when handling such fields, and take care of the encoding
+details.
+
+Add a new constructor to PrivDataField for binary files:
+
+ | PrivBinaryFile FilePath
+
+And a function to get the encoder and decoder:
+
+ type Encoder = ByteString -> PrivData
+ type Decoder = PrivData -> ByteString
+
+ privDataEncoding :: PrivDataField -> Maybe (Encoder, Decoder)
+
+Then --set, --dump, and --edit could use that to encode and decode the
+data.
+
+And finally, a `withBinaryPrivData` that uses ByteString.
+
+(Maybe this could be made more type safe though..)
+"""]]
diff --git a/doc/todo/bytes_in_privData__63__/comment_7_d6c4c2645696eac448e906d812c2de62._comment b/doc/todo/bytes_in_privData__63__/comment_7_d6c4c2645696eac448e906d812c2de62._comment
new file mode 100644
index 00000000..07bc8145
--- /dev/null
+++ b/doc/todo/bytes_in_privData__63__/comment_7_d6c4c2645696eac448e906d812c2de62._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""mostly done"""
+ date="2015-09-15T00:26:10Z"
+ content="""
+A recent change converted PrivData to a newtype.
+There are no longer any things that directly use PrivData; all use
+should be via accessor functions like privDataLines and privDataVal.
+Which helps with this.
+
+So, I've instead implemented a `privDataByteString :: PrivData -> ByteString`,
+and I've adjusted the privdata serialization so it shouldn't crash
+on arbitrarily encoded data when eg, a binary file is fed into `propellor --set`.
+
+(Note that I was wrong earlier when I said it'd be safe to change the
+serialization to use ByteString; it must use String. While `"foo"`
+can be Read as a ByteString same as a string, `"foo\1000"`,
+when Read as a ByteString, truncates the big unicode character to
+a single byte. So, PrivData is still stored as Strings internally.)
+
+The final step would be to make `hasPrivContent` use `privDataByteString`
+instead of `privDataLines`. Which needs some more work to add Properties to
+ensure a file contains a ByteString. This should be pretty easy to do,
+but I lost steam..
+"""]]
diff --git a/doc/todo/concurrency.mdwn b/doc/todo/concurrency.mdwn
new file mode 100644
index 00000000..fa0e22ea
--- /dev/null
+++ b/doc/todo/concurrency.mdwn
@@ -0,0 +1,111 @@
+Should be possible to add this, to construct a bunch of properties and
+run them in parallel:
+
+ concurrently :: IsProp p => (a -> p) -> [a] -> p
+
+Another version also nice to have:
+
+ race :: IsProp p => p -> p -> p
+
+Basic implementation should be pretty easy; propellor does not have a lot of
+mutable state to get in the way.
+
+The only hard part is, ensuring a property may cause arbitrary output,
+and it's not line-buffered necessarily, so there could be messy
+interleaving. I'm not sure how to deal with this, short of forking
+off a sub-process to ensure the property.
+
+----
+
+If forkProcess could be used, it could fork a subprocess that knows the
+action it's to perform, and jiggers stdio to feed through a pipe back to the
+parent.
+
+But, I have had bad luck in the past using forkProcess in haskell,
+in combination with the -threaded runtime.
+
+ forkProcess comes with a giant warning: since any other running threads
+ are not copied into the child process, it's easy to go wrong: e.g.
+ by accessing some shared resource that was held by another thread in
+ the parent.
+
+It may well be that since propellor has very
+little shared resources, and properties are run quite independently of
+one-another, a forkProcess to run a property might not be a problem.
+
+At least, until someone gets creative:
+
+ foo = property "foo" $ do
+ v <- liftIO newEmptyMVar
+ ensureProperty $
+ foo v `race` bar v -- FAIL
+
+We could detect if inside ensureProperty and refuse to do anything
+concurrent because the user might be up to such tricks.
+
+---
+
+Instead of forking, execing a new process would work. But, how to tell that
+sub-process which property it's supposed to ensure? There's no property
+serialization, and not even a Eq to use.
+
+Hmm, if it could come up with a stable, unique Id for each property, then
+the sub-process could be told the Id, and it'd then just look through its
+Host to find the property.
+
+This could be done by propellor's defaultMain, using Data.Unique (or a
+reimplementation that lets us get at the actual integer, rather than a hash
+of it). As long as it processes properties in a consistent order, that will
+generate the same Id for a property each time (until propellor is
+recompiled of course). The Id can be paired with the description of the
+property, to catch any version skew.
+
+But, this seems to not get all the way there. Having Id's for the top-level
+properties doesn't help in a situation like:
+
+ & propertyList "foo"
+ [ x `race` y
+ , a `race` b
+ ]
+
+x y a b are not top-level properties of a Host, so won't get unique Id's.
+Unless we can build up some tree of Id's that can be walked from the
+top-level down to the sub-properties, this won't work. Help?
+
+Also, what about mixing concurrency with ensureProperty?
+
+ foo = property "foo" $ do
+ liftIO defCon5
+ ensureProperty $
+ missleDefense `race` diplomacy
+ where
+ missleDefense = ...
+ diplomacy = ...
+
+Here there's no way for a propellor sub-process to know it needs to
+run part of foo to get to diplomacy. I think it would be ok to fall back to
+sequential mode in this case. So, the sub-process could signal with a
+special exit code that it couldn't find the requested Id, and then `race`
+can just wait for missleDefense to finish, and then run diplomacy.
+(Granted, this order may not be ideal in this specific case..)
+
+----
+
+Final option is to say, there are two sources of output when
+ensuring a property:
+
+* Propellor's own output, which is mostly gated through a few functions,
+ although of course the user can print anything they want too.
+* Output from running commands. Mostly done via cmdProperty, although
+ the user's also free to run commands in other ways.
+
+So, the Propellor monad could have a flag added to say that all output
+should be captured rather than output now, and just do that on a
+best-effort basis.
+
+Could even redirect stderr and stdout to a pipe, to capture any errant
+output. We'd not be able to tell which of the concurrent actions was
+responsible for such output, but it could be printed out, with appropriate
+warnings, at the end.
+
+[[!tag user/joey]]
diff --git a/doc/todo/depend_on_concurrent-output.mdwn b/doc/todo/depend_on_concurrent-output.mdwn
new file mode 100644
index 00000000..fdc66b04
--- /dev/null
+++ b/doc/todo/depend_on_concurrent-output.mdwn
@@ -0,0 +1,10 @@
+Currently a module from concurrent-output is inlined into propellor. This
+should be converted to a dependency.
+
+Waiting on concurrent-output reaching Debian stable.
+
+Once this is done, can switch GHC-Options back to -O0 from -O.
+-O is only needed to get stream fusion in the concurrent-output code;
+-O0 is better because ghc takes less memory to build propellor.
+
+[[!tag user/joey]]
diff --git a/doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__.mdwn b/doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__.mdwn
new file mode 100644
index 00000000..2973e662
--- /dev/null
+++ b/doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__.mdwn
@@ -0,0 +1,9 @@
+Detecting and using `GHC_PACKAGE_PATH` would allow "stack exec" support. This way propellor would be able to be built with
+
+ stack build
+
+and run with
+
+ stack exec -- propellor ...
+
+see [[https://github.com/yesodweb/yesod/issues/1018]] and [[https://github.com/yesodweb/yesod/commit/a7cccf2a7c5df8b26da9ea4fdcb6bac5ab3a3b75]]
diff --git a/doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__/comment_1_892385793c38976d0c446906dd004772._comment b/doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__/comment_1_892385793c38976d0c446906dd004772._comment
new file mode 100644
index 00000000..3154a895
--- /dev/null
+++ b/doc/todo/detect_and_use___96__GHC__95__PACKAGE__95__PATH__96__/comment_1_892385793c38976d0c446906dd004772._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-06-29T20:25:10Z"
+ content="""
+I don't entirely understand this, though
+<https://github.com/haskell/cabal/pull/2270> seems to give some background.
+Patches welcome I suppose, although would't it be better to fix the tooling
+and not things like propellor that just use the tools?
+"""]]
diff --git a/doc/todo/docker_todo_list.mdwn b/doc/todo/docker_todo_list.mdwn
index 72ded426..1321445d 100644
--- a/doc/todo/docker_todo_list.mdwn
+++ b/doc/todo/docker_todo_list.mdwn
@@ -1,5 +1,3 @@
* There is no way for a property of a docker container to require
some property be met outside the container. For example, some servers
need ntp installed for a good date source.
-* The SimpleSh was added before `docker exec` existed, and could probably
- be eliminated by using that.
diff --git a/doc/todo/dynamic_Info.mdwn b/doc/todo/dynamic_Info.mdwn
new file mode 100644
index 00000000..52ffdfe7
--- /dev/null
+++ b/doc/todo/dynamic_Info.mdwn
@@ -0,0 +1,4 @@
+nomeata suggested using Data.Dynamic for Info, so there doesn't need to be
+a big record centralizing all sorts of info. --[[Joey]]
+
+[[done]] --[[Joey]]
diff --git a/doc/todo/editor_for_privdata__63__.mdwn b/doc/todo/editor_for_privdata__63__.mdwn
new file mode 100644
index 00000000..8b91338c
--- /dev/null
+++ b/doc/todo/editor_for_privdata__63__.mdwn
@@ -0,0 +1,4 @@
+Would adding a way to call $EDITOR to edit privdata be possible?
+It would make sense for editing data like logcheck files.
+
+> [[done]]
diff --git a/doc/todo/editor_for_privdata__63__/comment_2_4fcbdf36f32ca7cf82593a8992167aff._comment b/doc/todo/editor_for_privdata__63__/comment_2_4fcbdf36f32ca7cf82593a8992167aff._comment
new file mode 100644
index 00000000..bbe93fe3
--- /dev/null
+++ b/doc/todo/editor_for_privdata__63__/comment_2_4fcbdf36f32ca7cf82593a8992167aff._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="http://joeyh.name/"
+ subject="comment 2"
+ date="2014-11-11T21:16:09Z"
+ content="""
+Already exists in `propellor --edit`
+
+Documentation patches accepted! :)
+"""]]
diff --git a/doc/todo/etckeeper.mdwn b/doc/todo/etckeeper.mdwn
new file mode 100644
index 00000000..7dc80cef
--- /dev/null
+++ b/doc/todo/etckeeper.mdwn
@@ -0,0 +1 @@
+It would be cool to have an etckeeper module :-).
diff --git a/doc/todo/etckeeper/comment_1_8766da27c69bbae357d497e0e557fad2._comment b/doc/todo/etckeeper/comment_1_8766da27c69bbae357d497e0e557fad2._comment
new file mode 100644
index 00000000..f080f70e
--- /dev/null
+++ b/doc/todo/etckeeper/comment_1_8766da27c69bbae357d497e0e557fad2._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2014-11-06T15:46:56Z"
+ content="""
+All I've needed for this is `& Apt.installed ["etckeeper"]`
+
+Patches welcome, I suppose.
+"""]]
diff --git a/doc/todo/fail_if_modification_not_commited_when_using_--spin.mdwn b/doc/todo/fail_if_modification_not_commited_when_using_--spin.mdwn
new file mode 100644
index 00000000..046f4a6f
--- /dev/null
+++ b/doc/todo/fail_if_modification_not_commited_when_using_--spin.mdwn
@@ -0,0 +1,3 @@
+Sometimes I forget to commit a modification, and running "propellor --spin" automatically commits this stuff. It would be better if "propellor --spin" failed (or, even better, warned the user) that there are uncommited changes, and "propellor --spin" would just always add an empty commit.
+
+> --merge added; [[done]] --[[Joey]]
diff --git a/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_1_7267d62ccc8db44bccb935836536e8a1._comment b/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_1_7267d62ccc8db44bccb935836536e8a1._comment
new file mode 100644
index 00000000..19b2fab6
--- /dev/null
+++ b/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_1_7267d62ccc8db44bccb935836536e8a1._comment
@@ -0,0 +1,30 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2014-11-23T18:41:40Z"
+ content="""
+Letting --spin commit is part of my workflow. It's great when you're just
+changing config.hs to quickly blast out the changes.
+
+Granted, it is not so nice when doing Property development, as changes get
+fragmented across the spins used to test them. I'd be happy to find some
+way to improve that. Perhaps a way could be found to get this structure of
+git commits:
+
+ manual commit------------------------->manual commit--merge
+ \--spin--spin--spin--spin--spin------------/
+
+Where the second manual commit has an identical tree committed as does the
+spin just underneath it, and so the following merge doesn't change any files,
+just grafts the two branches back together.
+
+I guess that could be handled by haing a checkpoint command, that squashes
+all the previous spins since the last checkpoint together into one commit,
+lets the user edit the commit message of that, and the juggles the branches
+into place and creates the merge commit -- which then becomes the new last
+checkpoint.
+
+I'll take patches for such a thing, or more simply a way to configure --spin's
+auto-committing behavior. However, I don't want to change the default
+behavior to not commit.
+"""]]
diff --git a/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_2_e4d170a14d689bef5d9174b251a4fe6f._comment b/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_2_e4d170a14d689bef5d9174b251a4fe6f._comment
new file mode 100644
index 00000000..3e8e5f62
--- /dev/null
+++ b/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_2_e4d170a14d689bef5d9174b251a4fe6f._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="gueux"
+ subject="comment 2"
+ date="2014-11-23T20:23:24Z"
+ content="""
+Your solution seems a lot better :-).
+"""]]
diff --git a/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_3_c69eaa9c6ae5b07b5c2dd2591de965a3._comment b/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_3_c69eaa9c6ae5b07b5c2dd2591de965a3._comment
new file mode 100644
index 00000000..8ad6ab49
--- /dev/null
+++ b/doc/todo/fail_if_modification_not_commited_when_using_--spin/comment_3_c69eaa9c6ae5b07b5c2dd2591de965a3._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2014-11-23T21:12:19Z"
+ content="""
+Here's a almost-script to do it, which worked when it did it by hand:
+
+<pre>
+get old-head (git show-ref HEAD -s)
+get curr-branch (refs/heads/master eg)
+find old-commit (look back through git log for the first commit that was not "propellor spin")
+git reset old-commit
+git commit -a # user gets to edit commit message for all the spins and any staged changes here
+git merge -S -s ours old-head
+get current-commit (result of merge)
+git update-ref curr-branch current-commit
+git checkout curr-branch
+</pre>
+"""]]
diff --git a/doc/todo/git_push_over_propellor_ssh_channel.mdwn b/doc/todo/git_push_over_propellor_ssh_channel.mdwn
new file mode 100644
index 00000000..c6d42fcf
--- /dev/null
+++ b/doc/todo/git_push_over_propellor_ssh_channel.mdwn
@@ -0,0 +1,13 @@
+Propellor currently needs a central git server. And it has a special-cased
+protocol during bootstrap that transfers the git repo over to a new host,
+using the ssh connection that will be used to run propellor.
+
+This could be improved by making a git push be done whenever
+`propellor spin $host` runs. The remote propellor runs `git receive-pack`;
+the local one runs `git send-pack`.
+
+Then there would be no need for a central git repo. Although still very
+useful if you have multiple propellor driven hosts and you want to just git
+commit and let cron sort them out.
+
+> [[done]]! --[[Joey]]
diff --git a/doc/todo/hooks/comment_1_4ca9e46f36d0fae334d9c2f2c211d0e3._comment b/doc/todo/hooks/comment_1_4ca9e46f36d0fae334d9c2f2c211d0e3._comment
new file mode 100644
index 00000000..a2a2416d
--- /dev/null
+++ b/doc/todo/hooks/comment_1_4ca9e46f36d0fae334d9c2f2c211d0e3._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-10-20T16:40:43Z"
+ content="""
+There's `endAction` which can be used to register an action to run after
+all properties have run. This could pretty easily be extended to take
+a MVar associated with the action and use it to only run the action once.
+
+However, running actions at the end of the propellor run doesn't let other
+properties depend on the results of those actions. If an property
+configures apache, and another property somehow depends on apache being
+configured, deferring the apache restart to an endAction wouldn't work.
+"""]]
diff --git a/doc/todo/info_propigation_out_of_nested_properties.mdwn b/doc/todo/info_propigation_out_of_nested_properties.mdwn
index e6427069..4176213a 100644
--- a/doc/todo/info_propigation_out_of_nested_properties.mdwn
+++ b/doc/todo/info_propigation_out_of_nested_properties.mdwn
@@ -1,36 +1,97 @@
> Now [[fixed|done]]!! --[[Joey]]
-Currently, Info about a Host's Properties is manually gathered and
-propigated. propertyList combines the Info of the Properties in the list.
-Docker.docked extracts relevant Info from the Properties of the container
-(but not al of it, intentionally!).
+Currently, Info about a Host's Properties is propagated to the host by
+examining the tree of Properties.
-This works, but it's error-prone. Consider this example:
+This works, but there's one problem. Consider this example:
withOS desc $ \o -> case o of
(Just (System (Debian Unstable) _)) -> ensureProperty foo
_ -> ensureProperty bar
-Here, the Info of `foo` is not propigated out. Nor is `bar`'s Info.
-Of course, only one of them will be run, and only its info should be propigated
-out..
+Here, the Info of `foo` is not propagated out. Nor is `bar`'s Info.
+It's not really clear if just one Info, or both should be propagated out.
-This commonly afflicts eg, privData. For example, `User.hasPassword'`
-has this problem, and this prevents --list-fields from listing privdata
-that's not set from that property.
+----
One approach might be to make the Propellor monad be able to be run in two
-modes. In one mode, it actually perform IO, etc. In the other mode, all
-liftIO is a no-op, but all Info encountered is accumulated using a Reader
-monad. This might need two separate monad definitions.
-
-That is surely doable, but the withOS example above shows a problem with it --
-the OS is itself part of a Host's info, so won't be known until all its
-properties have been examined for info!
-
-Perhaps that can be finessed. We don't really need to propigate out OS info.
-Just DNS and PrivDataField Info. So info could be collected in 2 passes,
-first as it's done now by static propertyInfo values. Then take that
-and use it as the Info when running the Properties in the Reader monad.
-Combine what the Reader accumulates with the static info to get the full
-info.
+modes. In run mode, it actually performs IO, etc. In introspection mode, all
+liftIO is a no-op, but all Info encountered is accumulated using a Reader.
+This might need two separate monad definitions.
+
+That is surely doable, but consider this example:
+
+ property "demo" = do
+ needfoo <- liftIO checkFoo
+ if needfoo
+ then ensureProperty foo
+ else ensureProperty . bar =<< liftIO (getBarParam)
+
+In introspection mode, the liftIO is a no-op, but needs to return a Bool.
+That seems unlikely (how to pick which?), but even if some defaulting is
+used, only one of foo or bar's info will be seen.
+
+Worse, the bar property is not fully known until IO can be performed to get
+its parameter.
+
+----
+
+Another approach could be something like this:
+
+ withInfoFrom foo $ \callfoo ->
+ withInfoFrom bar $ \callbar ->
+ property "demo" = do
+ needfoo <- liftIO checkFoo
+ if needfoo
+ then callfoo
+ else callbar
+
+Here withInfoFrom adds foo and bar as child properties of the demo property
+that (may) call them.
+
+This approach is not fully type safe; it would be possible to call
+withInfoFrom in a way that didn't let it propagate the info.
+
+And again this doesn't solve the problem that IO can be needed to get
+a parameter of a child property.
+
+----
+
+Another approach would be to add a new SimpleProperty, which is a property
+that has no Info. Only allow calling ensureProperty on this new type.
+
+(Or, remove propertyInfo from Property, and add a new InfoProperty that
+has the info.)
+
+But, propertyList can only contain one type at a time,
+not a mixed list of Property and SimpleProperty.
+
+Could a GADT be used instead?
+
+ {-# LANGUAGE GADTs #-}
+ {-# LANGUAGE EmptyDataDecls #-}
+
+ data HasInfo
+ data NoInfo
+
+ data Property = IProperty (GProperty HasInfo) | SProperty (GProperty NoInfo)
+
+ data GProperty i where
+ GIProperty :: Desc -> Propellor Result -> Info -> GProperty HasInfo
+ GSProperty :: Desc -> Propellor Result -> GProperty NoInfo
+
+ ensureProperty :: GProperty NoInfo -> Propellor Result
+ ensureProperty (GSProperty d r) = r
+
+That works. I made a `gadtwip` git branch that elaborated on that,
+to the point that Property.File compiles, but is otherwise
+unfinished. Most definitions of `Property` need to be changed to
+`GProperty NoInfo`, so that ensureProperty can call them. It's a big,
+intrusive change, and it may complicate propellor too much.
+
+I've tried to make this change a couple times now, and not been completely
+successful so far.
+
+(I may need to make instances of Prop for `GProperty NoInfo` and `GProperty
+HasInfo`, if that's possible, and make more Property combinators work on
+Prop.)
diff --git a/doc/todo/issue_after_upgrading_shared_library.mdwn b/doc/todo/issue_after_upgrading_shared_library.mdwn
new file mode 100644
index 00000000..52e72d4a
--- /dev/null
+++ b/doc/todo/issue_after_upgrading_shared_library.mdwn
@@ -0,0 +1,25 @@
+After upgrading my server to jessie, I noticed that propellor does not work anymore. The issue seems to be that, libffi was upgraded from libffi5:amd64 to libffi6:amd64
+
+ $ ./propellor --spin myserver
+ Building propellor-2.2.1...
+ Preprocessing library propellor-2.2.1...
+ In-place registering propellor-2.2.1...
+ Preprocessing executable 'propellor' for propellor-2.2.1...
+ Preprocessing executable 'propellor-config' for propellor-2.2.1...
+ Propellor build ... done
+
+ You need a passphrase to unlock the secret key for
+ user: bla
+
+ [master 2aabb40] propellor spin
+ Git commit ... done
+ Counting objects: 1, done.
+ Writing objects: 100% (1/1), 852 bytes | 0 bytes/s, done.
+ Total 1 (delta 0), reused 0 (delta 0)
+ To root@myserver:/var/lib/git/private/propellor.git
+ b16f1a6..2aabb40 master -> master
+ Push to central git repository ... done
+ ./propellor: error while loading shared libraries: libffi.so.5: cannot open shared object file: No such file or directory
+ propellor: user error (ssh ["-o","ControlPath=/home/myuser/.ssh/propellor/myserver.sock","-o","ControlMaster=auto","-o","ControlPersist=yes","root@myserver","sh -c 'if [ ! -d /usr/local/propellor/.git ] ; then (if ! git --version >/dev/null; then apt-get update && apt-get --no-install-recommends --no-upgrade -y install git; fi && echo STATUSNeedGitClone) || echo STATUSNeedPrecompiled ; else cd /usr/local/propellor && if ! test -x ./propellor; then ( apt-get update ; apt-get --no-upgrade --no-install-recommends -y install gnupg ; apt-get --no-upgrade --no-install-recommends -y install ghc ; apt-get --no-upgrade --no-install-recommends -y install cabal-install ; apt-get --no-upgrade --no-install-recommends -y install libghc-async-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-missingh-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-hslogger-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-unix-compat-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-ansi-terminal-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-ifelse-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-network-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-quickcheck2-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-mtl-dev ; apt-get --no-upgrade --no-install-recommends -y install libghc-monadcatchio-transformers-dev ; cabal update ; cabal install --only-dependencies ) || true && cabal configure && cabal build && ln -sf dist/build/propellor-config/propellor-config propellor; fi && ./propellor --boot myserver ; fi'"] exited 127)
+
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/todo/issue_after_upgrading_shared_library/comment_1_8d9144d57871cb5d234710d1ab1b7183._comment b/doc/todo/issue_after_upgrading_shared_library/comment_1_8d9144d57871cb5d234710d1ab1b7183._comment
new file mode 100644
index 00000000..77c7df83
--- /dev/null
+++ b/doc/todo/issue_after_upgrading_shared_library/comment_1_8d9144d57871cb5d234710d1ab1b7183._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-04-02T01:14:06Z"
+ content="""
+I think I saw this once myself (have no servers older than jessie left
+now).
+
+I believe the problem can be worked around by running make clean
+in /usr/local/propellor on the server.
+
+I'm not clear yet on a good way for --spin to detect that propellor
+has failed due to this, rather than some other problem, and try
+a clean and rebuild.
+
+Hmm, xmonad should have a similar problem, since it builds a haskell
+program locally. I wonder how the debian package deals with it there.
+
+Note there's a libffi6, so this will presumably happen again..
+"""]]
diff --git a/doc/todo/issue_after_upgrading_shared_library/comment_2_01a3d5e006158302e12862cacee3327e._comment b/doc/todo/issue_after_upgrading_shared_library/comment_2_01a3d5e006158302e12862cacee3327e._comment
new file mode 100644
index 00000000..3f7a7bbc
--- /dev/null
+++ b/doc/todo/issue_after_upgrading_shared_library/comment_2_01a3d5e006158302e12862cacee3327e._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="gueux"
+ subject="comment 2"
+ date="2015-04-02T09:24:07Z"
+ content="""
+Indeed, \"make clean\" on the server worked. I don't know it could be made more robust to this kind of upgrade...
+"""]]
diff --git a/doc/todo/issue_after_upgrading_shared_library/comment_2_6025ec35330fbac220f2888e60be1e78._comment b/doc/todo/issue_after_upgrading_shared_library/comment_2_6025ec35330fbac220f2888e60be1e78._comment
new file mode 100644
index 00000000..bc89ad7f
--- /dev/null
+++ b/doc/todo/issue_after_upgrading_shared_library/comment_2_6025ec35330fbac220f2888e60be1e78._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2015-04-02T14:27:26Z"
+ content="""
+So I thought of two approaches.
+
+1. Propellor could copy in all the shared libraries. It already contains
+ code to do this. But, this would add overhead to every build. And it
+ might not guard against all snafus.
+
+2. Make propellor --check that should exit 0. Make --spin check that
+ propellor works and rebuild if not. Also make the runPropellor cron job
+ do that.
+
+I've gone with option #2.
+"""]]
diff --git a/doc/todo/lxc_containers_support.mdwn b/doc/todo/lxc_containers_support.mdwn
new file mode 100644
index 00000000..5e9da306
--- /dev/null
+++ b/doc/todo/lxc_containers_support.mdwn
@@ -0,0 +1 @@
+Adding lxc containers support would be great, as an alternative to docker, chroot, or systemd containers.
diff --git a/doc/todo/missing_dependencies.mdwn b/doc/todo/missing_dependencies.mdwn
new file mode 100644
index 00000000..55490a86
--- /dev/null
+++ b/doc/todo/missing_dependencies.mdwn
@@ -0,0 +1,39 @@
+After upgrading to 2.4.0, I get this error:
+
+ ./propellor --spin myserver
+ Building propellor-2.4.0...
+ Preprocessing library propellor-2.4.0...
+ In-place registering propellor-2.4.0...
+ Preprocessing executable 'propellor' for propellor-2.4.0...
+ Preprocessing executable 'propellor-config' for propellor-2.4.0...
+ Propellor build ... done
+ Git commit ... done
+ Enter passphrase for /home/user/.ssh/id_rsa:
+ Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)
+ Counting objects: 253, done.
+ Delta compression using up to 4 threads.
+ Compressing objects: 100% (253/253), done.
+ Writing objects: 100% (253/253), 173.59 KiB | 0 bytes/s, done.
+ Total 253 (delta 172), reused 0 (delta 0)
+ To root@myserver:/var/lib/git/private/propellor.git
+ d81fb7d..6f7f041 master -> master
+ Push to central git repository ... done
+ From myserver:/var/lib/git/private/propellor
+ d81fb7d..6f7f041 master -> origin/master
+ Pull from central git repository ... done
+ ** warning: git branch origin/master is not signed with a trusted gpg key; refusing to deploy it! (Running with previous configuration instead.)
+ Sending privdata (87652 bytes) to myserver ... done
+ From .
+ * branch HEAD -> FETCH_HEAD
+ Sending git update to myserver ... done
+ Warning: The package list for 'hackage.haskell.org' is 47 days old.
+ Run 'cabal update' to get the latest list of available packages.
+ Resolving dependencies...
+ Configuring propellor-2.4.0...
+ cabal: At least the following dependencies are missing:
+ exceptions -any
+ propellor: failed to make dist/setup-config
+ Shared connection to myserver closed.
+ propellor: remote propellor failed
+
+As in https://propellor.branchable.com/todo/issue_after_upgrading_shared_library/, manually running "make clean" on the server fixed the issue
diff --git a/doc/todo/missing_dependencies/comment_1_826a75052e87c04489aa07c3d322a54f._comment b/doc/todo/missing_dependencies/comment_1_826a75052e87c04489aa07c3d322a54f._comment
new file mode 100644
index 00000000..2ccb179d
--- /dev/null
+++ b/doc/todo/missing_dependencies/comment_1_826a75052e87c04489aa07c3d322a54f._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-05-22T18:13:15Z"
+ content="""
+`exceptions` is indeed a new dependency.
+
+This is supposed to be handled by Propellor.Bootstrap.checkDepsCommand
+which is run by --spin.
+
+Maybe check if your propellor.cabal includes the `exceptions` dependency,
+and check if `cabal configure` fails. If it does, it seems like that code
+would fire, and should install the missing dependency. It worked when I
+upgraded my systems with it, is all I know.
+"""]]
diff --git a/doc/todo/onChange_failure_handling.mdwn b/doc/todo/onChange_failure_handling.mdwn
new file mode 100644
index 00000000..46a81caf
--- /dev/null
+++ b/doc/todo/onChange_failure_handling.mdwn
@@ -0,0 +1,41 @@
+> Please consider the following three properties
+> - p1,
+> - p2 and
+> - p3 = onChange p1 p2.
+>
+> If p1 returns MadeChange and p2 FailedChange, then p3 is FailedChange.
+> If we apply this property again without any changes, then p3 is
+> NoChange.
+>
+> This behavior could create problematic situations since p3 can be
+> required by another property which thinks that p3 has been applied
+> whereas it's not the case...
+>
+> -- Antoine
+
+Very well stated.
+
+I looked over existing uses of onChange in propellor, and many of them
+seem safe.
+
+The safe ones are where there's eg, a daemon, with a Property that it's
+running, and another Property that configures it in some way with
+onChange restart. If the restart fails, then the daemon is presumably
+left not running (unless it failed to stop the daemon somehow); a state
+that the former Property will attempt to take care of (or at least
+continue to indicate failure on) the next time propellor runs.
+
+Hmm, there are also lots of uses of onChange reloaded. If the new
+configuration of a daemon is broken, this can fail to reload it, and
+leave the daemon running with the old configuration. So that's more
+problimatic, and then there are some more problimatic yet uses of
+onChange, like the one that runs apt-get update after a change to
+sources.list.
+
+--[[Joey]]
+
+----
+
+The `onChangeFlagOnFail` combinator is a safer alternative to `onChange`
+that avoids this problem. But, it can be difficult to come up with unique
+names for the flag files it uses.
diff --git a/doc/todo/port_info_for_properties_for_firewall.mdwn b/doc/todo/port_info_for_properties_for_firewall.mdwn
new file mode 100644
index 00000000..efaaba05
--- /dev/null
+++ b/doc/todo/port_info_for_properties_for_firewall.mdwn
@@ -0,0 +1,24 @@
+The firewall module could be improved if properties that set up a service
+on a port included info (see Propellor.Info and Propellor.Types.Info)
+about the port(s) used.
+
+While currently the ports have to be explicitly listed:
+
+ & Apache.installed
+ & Firewall.installed
+ & Firewall.addRule (Rule INPUT ACCEPT (Proto TCP :- Port 80))
+ & Firewall.addRule (Rule INPUT ACCEPT (Proto TCP :- Port 443))
+
+Instead the ports would be derived from the installed services.
+
+ & Apache.installed
+ & Firewall.installed
+
+There could also be some combinators to adjust the exposed
+ports of a property.
+
+ & localOnly Apache.installed
+ & exposedPorts [443,80] (Apt.serviceInstalledRunning "apache2")
+
+Such port enformation is also going to be needed as a basis of
+[[type_level_port_conflict_detection]]. --[[Joey]]
diff --git a/doc/todo/publish_propellor_as_library_to_hackage.mdwn b/doc/todo/publish_propellor_as_library_to_hackage.mdwn
new file mode 100644
index 00000000..709ee35b
--- /dev/null
+++ b/doc/todo/publish_propellor_as_library_to_hackage.mdwn
@@ -0,0 +1,4 @@
+Currently, AFAIK, one needs to fork propellor repo, add its own configuration and compile propellor binary from all the source tree.
+It would be handy and more modular to allow one to have a propellor configuration linked to propellor as a library, hosted on hackage.
+
+> [[done]] --[[Joey]]
diff --git a/doc/todo/publish_propellor_as_library_to_hackage/comment_1_00a865bf7977c0e49f54a365f4b60ce8._comment b/doc/todo/publish_propellor_as_library_to_hackage/comment_1_00a865bf7977c0e49f54a365f4b60ce8._comment
new file mode 100644
index 00000000..8d56f0f1
--- /dev/null
+++ b/doc/todo/publish_propellor_as_library_to_hackage/comment_1_00a865bf7977c0e49f54a365f4b60ce8._comment
@@ -0,0 +1,27 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-02-28T15:01:24Z"
+ content="""
+Unusual as it is for propellor's configuration git repo to include the full
+source code to propellor, I like this approach. It lets users change any
+existing property that is not generic enough, or makes assumptions they
+don't like, or needs porting to their OS of choice.
+
+But still, propellor is
+[on hackage](http://hackage.haskell.org/package/propellor), as
+a library. It can be used that way if you want to.
+
+I don't think that any of propellor's code cares how it's distributed,
+except for src/wrapper.hs (which cabal will install as
+~/.cabal/bin/propellor), which sets up the ~/.propellor/ repository. You
+can bypass using that wrapper if you like, and cabal install propellor and
+create your own ~/.propellor/ repository containing only your own
+config.hs, and build and use propellor that way.
+
+Where that approach becomes a problem is that propellor --spin currently
+relies on propellor's Makefile being in the repository, when bootstrapping
+propellor on a remote host. So you'll need to include a copy of that in
+your repo for --spin to work. I'd like to get rid of the need for the
+Makefile. (Only the build and deps targets are used by --spin.)
+"""]]
diff --git a/doc/todo/publish_propellor_as_library_to_hackage/comment_2_29cc276929020e68eae8ae04110a3f5f._comment b/doc/todo/publish_propellor_as_library_to_hackage/comment_2_29cc276929020e68eae8ae04110a3f5f._comment
new file mode 100644
index 00000000..af61b1db
--- /dev/null
+++ b/doc/todo/publish_propellor_as_library_to_hackage/comment_2_29cc276929020e68eae8ae04110a3f5f._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2015-02-28T17:08:28Z"
+ content="""
+Ok, I got --spin to not use the Makefile any more. So with the 2.2.0
+release, if you want to make ~/.propellor contain only a config.hs
+file and a foo.cabal file, that will work. The cabal file would contain
+something like:
+
+<pre>
+Executable propellor-config
+ Main-Is: config.hs
+ GHC-Options: -Wall -threaded -O0
+ Build-Depends: propellor, base >= 4.5, base < 5
+</pre>
+"""]]
diff --git a/doc/todo/publish_propellor_as_library_to_hackage/comment_3_efbe0ef77be957c37e745ec64452ae99._comment b/doc/todo/publish_propellor_as_library_to_hackage/comment_3_efbe0ef77be957c37e745ec64452ae99._comment
new file mode 100644
index 00000000..09628e53
--- /dev/null
+++ b/doc/todo/publish_propellor_as_library_to_hackage/comment_3_efbe0ef77be957c37e745ec64452ae99._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmtnXa0F3OsNh8H7yf5EEbtuufPZG-3StI"
+ nickname="Arnaud"
+ subject="You rocks!"
+ date="2015-03-05T15:24:49Z"
+ content="""
+Apologies for wrong information, I did not check if propellor was on hackage. Anyway, thanks a lot for caring to \"fix\" that, will give it a try this week and keep you posted.
+
+Thanks a lot
+"""]]
diff --git a/doc/todo/publish_propellor_as_library_to_hackage/comment_4_6ebf2e30596ddf6eba91717576837019._comment b/doc/todo/publish_propellor_as_library_to_hackage/comment_4_6ebf2e30596ddf6eba91717576837019._comment
new file mode 100644
index 00000000..737e7066
--- /dev/null
+++ b/doc/todo/publish_propellor_as_library_to_hackage/comment_4_6ebf2e30596ddf6eba91717576837019._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmtnXa0F3OsNh8H7yf5EEbtuufPZG-3StI"
+ nickname="Arnaud"
+ subject="Propellor 2.2.0 not on hackage"
+ date="2015-03-08T20:21:42Z"
+ content="""
+So I cannot depend on it right now. Do you know when it will be available there?
+"""]]
diff --git a/doc/todo/publish_propellor_as_library_to_hackage/comment_5_4a4e94c637e0380adc1a43ec3d0633e1._comment b/doc/todo/publish_propellor_as_library_to_hackage/comment_5_4a4e94c637e0380adc1a43ec3d0633e1._comment
new file mode 100644
index 00000000..85f95c17
--- /dev/null
+++ b/doc/todo/publish_propellor_as_library_to_hackage/comment_5_4a4e94c637e0380adc1a43ec3d0633e1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2015-03-09T17:00:35Z"
+ content="""
+SImply because 2.2.0 had not been released yet. (UNRELEASED in
+changelog..)
+"""]]
diff --git a/doc/todo/publish_propellor_as_library_to_hackage/comment_6_19470170c3ef461f446b0af1d8501640._comment b/doc/todo/publish_propellor_as_library_to_hackage/comment_6_19470170c3ef461f446b0af1d8501640._comment
new file mode 100644
index 00000000..143f1dea
--- /dev/null
+++ b/doc/todo/publish_propellor_as_library_to_hackage/comment_6_19470170c3ef461f446b0af1d8501640._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawmtnXa0F3OsNh8H7yf5EEbtuufPZG-3StI"
+ nickname="Arnaud"
+ subject="comment 6"
+ date="2015-03-10T06:28:52Z"
+ content="""
+Sorry, I did not read the changelog. Thanks for all the hard work on propellor.
+"""]]
diff --git a/doc/todo/revertable_Ssh.authorizedKey.mdwn b/doc/todo/revertable_Ssh.authorizedKey.mdwn
new file mode 100644
index 00000000..f92eaee8
--- /dev/null
+++ b/doc/todo/revertable_Ssh.authorizedKey.mdwn
@@ -0,0 +1 @@
+I recently lost the security key I store my primary SSH key on, and had to remove that key from all authorized_keys files I had access to. It would be great if Ssh.authorizedKey was revertable, so that this could be done simply by adding a ! before existing Ssh.authorizedKey lines.
diff --git a/doc/todo/revertable_Ssh.authorizedKey/comment_1_6c11976a814a7f4a830bc11ae9bf534e._comment b/doc/todo/revertable_Ssh.authorizedKey/comment_1_6c11976a814a7f4a830bc11ae9bf534e._comment
new file mode 100644
index 00000000..e03f1143
--- /dev/null
+++ b/doc/todo/revertable_Ssh.authorizedKey/comment_1_6c11976a814a7f4a830bc11ae9bf534e._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-10-06T19:01:13Z"
+ content="""
+This should be easy enough to implement; just implement a property that
+ensures the file lacks an authorized key (probably using `File.lacksLine`)
+and then combine the two properties with `<!>` to get a RevertableProperty.
+
+I'd accept a patch that does that.
+"""]]
diff --git a/doc/todo/spin_and_ipv6_addresses.mdwn b/doc/todo/spin_and_ipv6_addresses.mdwn
index 8693f16e..602d311b 100644
--- a/doc/todo/spin_and_ipv6_addresses.mdwn
+++ b/doc/todo/spin_and_ipv6_addresses.mdwn
@@ -6,3 +6,4 @@ using short names for such hosts with --spin. And, propellor only looks at
configured ipv4 properties of a host when deciding if the DNS hostname is
out of date, and falling back to contacting the host by IPv6 address.
+> [[fixed|done]] --[[Joey]]
diff --git a/doc/todo/spin_without_remote_compilation.mdwn b/doc/todo/spin_without_remote_compilation.mdwn
new file mode 100644
index 00000000..6ccc6414
--- /dev/null
+++ b/doc/todo/spin_without_remote_compilation.mdwn
@@ -0,0 +1 @@
+In some cases, building Propellor on the target machine is undesireable; for example, the host has limited memory available, or the load imposed by GHC on CPU / I/O usage is unacceptably disruptive to other services running on the host. When spinning from a compatible host, Propellor could instead have an option to copy the locally-built binary to the target host. I'm not sure exactly how to determine "compatible" in this case, so it would probably have to be left to the user to determine whether they can do it or not.
diff --git a/doc/todo/spin_without_remote_compilation/comment_1_10d797b43df9252c34a02c3fd249374b._comment b/doc/todo/spin_without_remote_compilation/comment_1_10d797b43df9252c34a02c3fd249374b._comment
new file mode 100644
index 00000000..6c6f3b6f
--- /dev/null
+++ b/doc/todo/spin_without_remote_compilation/comment_1_10d797b43df9252c34a02c3fd249374b._comment
@@ -0,0 +1,45 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-10-16T16:05:44Z"
+ content="""
+This is already implemented in propellor, but is currently only used
+when the remote host doesn't have git installed and apt fails to install
+it. I've used it for converting non-Debian systems to Debian eg.
+See Propellor.Spin.sendPrecompiled
+
+Going beyond what's there now is not a feature I need myself, and not a
+priority for me to implement, but I can help to some extent if you're going
+to work on it.
+
+Both the controller and host architecture matter of course in determining
+whether it will work. For example, an i386 controller will produce a
+propellor bundle that works on amd64. An amd64 controller's bundle *may*
+work on an i386 host, but only if its hardware and kernel happen to support
+64 bit. The simplest solution I can think of is to send the precompiled
+binary over to the host and check if it runs there before replacing any
+older propellor binary with it.
+
+The other question is, how to tell propellor when to use this mode. Some
+ideas, which build on each other.
+
+* --spin --precompiled
+
+* Add a `precompiled` property to the host that needs precompiled propellor.
+ The property can set Info, which --spin can look at to know if it needs
+ to use sendPrecompiled for this host, without needing --precompiled
+
+* Could also add a property that says a host is the controller for other
+ hosts. So, anytime propellor is run on the controller host, it
+ automatically spins the other hosts. And if the hosts it's spinning
+ have the `precompiled` property, the controller will honor it.
+
+Note that propellor's cron job will probably fail on a precompiled host,
+since even if it manages to pull changes from the central git repo
+(unlikely as a precompiled propellor currently isn't set up as a git repo),
+it can't locally compile them.
+
+So, in order to have a centralized repository with precompiled hosts,
+you need a controller that can handle sending the updated builds of
+propellor to them.
+"""]]
diff --git a/doc/todo/spin_without_remote_compilation/comment_2_1c3176559695d33bd7e183b9734e430f._comment b/doc/todo/spin_without_remote_compilation/comment_2_1c3176559695d33bd7e183b9734e430f._comment
new file mode 100644
index 00000000..3f6bf4a7
--- /dev/null
+++ b/doc/todo/spin_without_remote_compilation/comment_2_1c3176559695d33bd7e183b9734e430f._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2015-10-16T18:23:21Z"
+ content="""
+Since the controller idea was useful beyond supporting precompiled hosts,
+I've implemented it first, in Propellor.Property.Spin.controller.
+"""]]
diff --git a/doc/todo/ssh__95__user_+_sudo/comment_4_7fc635a8d6e4c903eaefa7383d2c37ac._comment b/doc/todo/ssh__95__user_+_sudo/comment_4_7fc635a8d6e4c903eaefa7383d2c37ac._comment
new file mode 100644
index 00000000..af5e120a
--- /dev/null
+++ b/doc/todo/ssh__95__user_+_sudo/comment_4_7fc635a8d6e4c903eaefa7383d2c37ac._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://launchpad.net/~jml"
+ nickname="jml"
+ subject="comment 4"
+ date="2015-05-15T08:57:04Z"
+ content="""
+Just want to add that it's not only a security issue: it's also a convenience issue. Many machines are configured by default to not allow remote root logins, but to allow user logins followed by sudo. If propellor can't do that, then there's an extra step in the whole process that can't be easily automated within propellor.
+"""]]
diff --git a/doc/todo/support_tarball_source_images.mdwn b/doc/todo/support_tarball_source_images.mdwn
new file mode 100644
index 00000000..13796623
--- /dev/null
+++ b/doc/todo/support_tarball_source_images.mdwn
@@ -0,0 +1,5 @@
+It would be nice to support tarball source images (such as those generated by [buildroot](http://buildroot.org/)). Basically, instead of running debootstrap, just `tar xf` to the right directory.
+
+Having propellor generate the buildroot would be nice as well, but isn't needed right away.
+
+> [[merged|done]] --[[Joey]]
diff --git a/doc/todo/support_tarball_source_images/comment_1_6c019767a6a678d7d9f7ad924e948d94._comment b/doc/todo/support_tarball_source_images/comment_1_6c019767a6a678d7d9f7ad924e948d94._comment
new file mode 100644
index 00000000..192c1a69
--- /dev/null
+++ b/doc/todo/support_tarball_source_images/comment_1_6c019767a6a678d7d9f7ad924e948d94._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2015-10-20T16:06:52Z"
+ content="""
+I've introduced a ChrootBootstrapper type class, of which Debootstrapped
+is just one member. Everything that bootstraps chroots uses this
+type class, so you can write a separate module that uses buildroot, or
+whatever. And you're welcome to contribute such a module to propellor.
+
+As far as having propellor generate a tarball of a chroot, the way to do
+that is something like:
+
+ chroot dir `onChange` mktarball dir
+
+Ie, compose the chroot creation property with one that tars it up.
+"""]]
diff --git a/doc/todo/support_tarball_source_images/comment_2_2d620f837f825f3041d9c66612e2ab4c._comment b/doc/todo/support_tarball_source_images/comment_2_2d620f837f825f3041d9c66612e2ab4c._comment
new file mode 100644
index 00000000..9da5739e
--- /dev/null
+++ b/doc/todo/support_tarball_source_images/comment_2_2d620f837f825f3041d9c66612e2ab4c._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2015-10-20T16:27:07Z"
+ content="""
+I've done all I plan to do about this particular todo, so look forward to
+modules being contributed for other ways to bootstrap chroots.
+"""]]
diff --git a/doc/todo/support_tarball_source_images/comment_3_411e4884c47fa6c371e6c6d2c5472752._comment b/doc/todo/support_tarball_source_images/comment_3_411e4884c47fa6c371e6c6d2c5472752._comment
new file mode 100644
index 00000000..65027028
--- /dev/null
+++ b/doc/todo/support_tarball_source_images/comment_3_411e4884c47fa6c371e6c6d2c5472752._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://mathstuf.id.fedoraproject.org/"
+ nickname="mathstuf"
+ subject="comment 3"
+ date="2015-10-21T03:57:19Z"
+ content="""
+Here's my attempt at adding support for this: <https://github.com/mathstuf/propellor/tree/add-tarball-system>. `MinimalTarball` may be too verbose. Maybe `TarballImage`?
+"""]]
diff --git a/doc/todo/support_tarball_source_images/comment_4_df41bdafff9277fb105ea2da0b0af5d9._comment b/doc/todo/support_tarball_source_images/comment_4_df41bdafff9277fb105ea2da0b0af5d9._comment
new file mode 100644
index 00000000..21c39d32
--- /dev/null
+++ b/doc/todo/support_tarball_source_images/comment_4_df41bdafff9277fb105ea2da0b0af5d9._comment
@@ -0,0 +1,37 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 4"""
+ date="2015-10-21T21:07:53Z"
+ content="""
+I don't think it makes sense to add MinimalTarball as an operating System.
+
+If you make ChrootTarball contain the FilePath to the tarball,
+then ChrootBootstrapper ChrootTarball instance doesn't need to look
+at the system parameter at all; instead it can just look inside the
+ChrootTarball to get the path to it, and extract that.
+
+So, the user would write, say:
+
+ bootstrapped (System (Debian Unstable) "amd64") (ChrootTarball "/tmp/debian.tar.gz") "/chroot"
+
+What might make sense it to change the first parameter of boostrapped
+to Maybe System, for cases where you don't want to specify it.
+
+----
+
+It would probably also be good to document what kind of tarball is
+expected. Ie, that it can be compressed, and should not consist
+of a single subdirectory, but one subdirectory for each top-level
+root directory.
+
+----
+
+Also, as a minor point, I don't think you need to pass standardPathEnv;
+it should be fine to use boolSystem with the regular enviroment as
+far as I can see. In fact, you could probably simplify extractTarball
+by implementing it like this:
+
+ check (unpopulated target) $
+ cmdProperty "tar" params
+ `requires` File.dirExists target
+"""]]
diff --git a/doc/todo/support_tarball_source_images/comment_5_fec2c4bf3d0ea806c94b0720b5e80aea._comment b/doc/todo/support_tarball_source_images/comment_5_fec2c4bf3d0ea806c94b0720b5e80aea._comment
new file mode 100644
index 00000000..4b999d73
--- /dev/null
+++ b/doc/todo/support_tarball_source_images/comment_5_fec2c4bf3d0ea806c94b0720b5e80aea._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://mathstuf.id.fedoraproject.org/"
+ nickname="mathstuf"
+ subject="comment 5"
+ date="2015-10-23T03:13:55Z"
+ content="""
+Updated. Thanks for the review. Much cleaner now :) .
+"""]]
diff --git a/doc/todo/support_tarball_source_images/comment_6_7f06f7f03d943649d24b8c5708bbb952._comment b/doc/todo/support_tarball_source_images/comment_6_7f06f7f03d943649d24b8c5708bbb952._comment
new file mode 100644
index 00000000..0de08eb7
--- /dev/null
+++ b/doc/todo/support_tarball_source_images/comment_6_7f06f7f03d943649d24b8c5708bbb952._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2015-10-23T05:31:07Z"
+ content="""
+Came out very nice indeed. Merged, thanks!
+"""]]
diff --git a/doc/todo/systemd_unit_integration.mdwn b/doc/todo/systemd_unit_integration.mdwn
new file mode 100644
index 00000000..6714ef08
--- /dev/null
+++ b/doc/todo/systemd_unit_integration.mdwn
@@ -0,0 +1 @@
+Properties for systemd unit files and support for dropping new units (e.g., a custom `.timer` unit) in should be supported. Support for `systemd-networkd` setup would be nice as well.
diff --git a/doc/todo/systemd_unit_integration/comment_1_cc7f255bc8ca5a6e46f0f08889ceac06._comment b/doc/todo/systemd_unit_integration/comment_1_cc7f255bc8ca5a6e46f0f08889ceac06._comment
new file mode 100644
index 00000000..73f3ead5
--- /dev/null
+++ b/doc/todo/systemd_unit_integration/comment_1_cc7f255bc8ca5a6e46f0f08889ceac06._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="https://mathstuf.id.fedoraproject.org/"
+ nickname="mathstuf"
+ subject="comment 1"
+ date="2015-10-25T19:39:51Z"
+ content="""
+Oh, useful links:
+
+[Arch wiki](https://wiki.archlinux.org/index.php/Systemd-networkd#Usage_with_containers) [CoreOS blog post](https://coreos.com/blog/intro-to-systemd-networkd/)
+"""]]
diff --git a/doc/todo/type_level_port_conflict_detection.mdwn b/doc/todo/type_level_port_conflict_detection.mdwn
new file mode 100644
index 00000000..6708ac3a
--- /dev/null
+++ b/doc/todo/type_level_port_conflict_detection.mdwn
@@ -0,0 +1,7 @@
+See <http://stackoverflow.com/questions/26027765/using-types-to-prevent-conflicting-port-numbers-in-a-list> --[[Joey]]
+
+Needs ghc newer than 7.6.3. It may be possible to port Data.Type.Equality
+and Data.Type.Bool to older versions; I got them to compile but they didn't
+work right. --[[Joey]]
+
+[[!tag user/joey]]
diff --git a/doc/todo/typo_in_propagate.mdwn b/doc/todo/typo_in_propagate.mdwn
new file mode 100644
index 00000000..bcc74300
--- /dev/null
+++ b/doc/todo/typo_in_propagate.mdwn
@@ -0,0 +1,6 @@
+Several comments and function names use the word "propigate" which seems to be a very uncommon spelling of "propagate". For example, Webster's dictionary knows about "[propagate](http://www.merriam-webster.com/dictionary/propagate)" but not about "propigate".
+
+Thus I propose to change the spelling into "propagate". I already did the change in the last commit on the branch `typo` in the repository `https://github.com/felgru/propellor.git`, from where you can pull the change.
+
+> A typo I often make, and not intentionally as with the propell*o*r
+> spelling. [[merged|done]] --[[Joey]]