new page
This commit is contained in:
parent
e49af37fe8
commit
4020a3e707
|
@ -5,6 +5,7 @@ Other documentation:
|
||||||
|
|
||||||
* [[man page|usage]]
|
* [[man page|usage]]
|
||||||
* [[Haskell Newbie]]
|
* [[Haskell Newbie]]
|
||||||
|
* [[Writing Properties]]
|
||||||
* [[Centralized Git Repository]]
|
* [[Centralized Git Repository]]
|
||||||
* [[Components]]
|
* [[Components]]
|
||||||
* [[Contributing]]
|
* [[Contributing]]
|
||||||
|
|
|
@ -114,7 +114,8 @@ That's really all there is to configuring Propellor. Once you
|
||||||
have a `config.hs` ready to try out, you can run `propellor --spin $host`
|
have a `config.hs` ready to try out, you can run `propellor --spin $host`
|
||||||
on one of the hosts configured in it.
|
on one of the hosts configured in it.
|
||||||
|
|
||||||
See the [[README]] for a further quick start.
|
See the [[README]] for a further quick start and [[Writing Properties]]
|
||||||
|
for guidance on extending propellor with your own custom properties.
|
||||||
|
|
||||||
(If you'd like to learn a little Haskell after all, check out
|
(If you'd like to learn a little Haskell after all, check out
|
||||||
[Learn You a Haskell for Great Good](http://learnyouahaskell.com/).)
|
[Learn You a Haskell for Great Good](http://learnyouahaskell.com/).)
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
Propellor comes with a lot of properties you can use. But eventually,
|
||||||
|
you'll want to write a property of your own.
|
||||||
|
|
||||||
|
This isn't hard. Often propellor has some properties you can use to build
|
||||||
|
the property you want. Need to modify the content of a file? Use any of
|
||||||
|
the properties in
|
||||||
|
[Propellor.Property.File](http://hackage.haskell.org/package/propellor-2.2.1/docs/Propellor-Property-File.htm)
|
||||||
|
Need to run some commands? Use [Propellor.Property.Cmd](http://hackage.haskell.org/package/propellor-2.2.1/docs/Propellor-Property-Cmd.html).
|
||||||
|
|
||||||
|
To combine properties, the easiest way is to use `requires`.
|
||||||
|
|
||||||
|
someproperty `requires` otherproperty
|
||||||
|
|
||||||
|
[Propellor.Property.List](http://hackage.haskell.org/package/propellor-2.2.1/docs/Propellor-Property-List.html)
|
||||||
|
has a `propertyList` combinator that's also useful.
|
||||||
|
|
||||||
|
[Propellor.Property](http://hackage.haskell.org/package/propellor-2.2.1/docs/Propellor-Property.html)
|
||||||
|
has some other functions to modify Properties in useful ways.
|
||||||
|
For example, `check` makes a Property call an `IO Bool` to check if the
|
||||||
|
Property needs be run.
|
||||||
|
|
||||||
|
## example: User.hasLoginShell
|
||||||
|
|
||||||
|
> 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
|
||||||
|
|
||||||
|
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.
|
Loading…
Reference in New Issue