propellor-5.17: property-based host configuration management in haskell
Safe HaskellSafe-Inferred
LanguageHaskell2010

Propellor.Property.Conductor

Description

This module adds conductors to propellor. A conductor is a Host that is responsible for running propellor on other hosts

This eliminates the need to manually run propellor --spin to update the conducted hosts, and can be used to orchestrate updates to hosts.

The conductor needs to be able to ssh to the hosts it conducts, and run propellor, as root. To this end, the knownHost property is automatically added to the conductor, so it knows the host keys of the relevant hosts. Also, each conducted host is configured to let its conductor ssh in as root, by automatically adding the authorizedKeysFrom property.

It's left up to you to use userKeys to configure the ssh keys for the root user on conductor hosts, and to use hostKeys to configure the host keys for the conducted hosts.

For example, if you have some webservers and a dnsserver, and want the master host to conduct all of them:

 import Propellor
 import Propellor.Property.Conductor
 import qualified Propellor.Property.Ssh as Ssh
 import qualified Propellor.Property.Cron as Cron
 
 main = defaultMain (orchestrate hosts)

 hosts =
 	[ master
	, dnsserver
	] ++ webservers
 
 dnsserver = host "dns.example.com"
	& Ssh.hostKeys hostContext [(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB3BJ2GqZiTR2LEoDXyYFgh/BduWefjdKXAsAtzS9zeI")]
	& ...
 
 webservers =
    [ host "www1.example.com"
		& Ssh.hostKeys hostContext [(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICfFntnesZcYz2B2T41ay45igfckXRSh5uVffkuCQkLv")]
		& ...
	, ...
	]

 master = host "master.example.com"
	& Ssh.userKeys (User "root") [(SshEd25519, "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFWD0Hau5FDLeNrDHKilNMKm9c68R3WD+NJOp2jPWvJV")]
	& conducts webservers
		`before` conducts dnsserver
	& Cron.runPropellor

Notice that, in the above example, the the webservers are conducted first. Only once the webservers have successfully been set up is the dnsserver updated. This way, when adding a new web server, the dns won't list it until it's ready.

There can be multiple conductors, and conductors can conduct other conductors if you need such a hierarchy. (Loops in the hierarchy, such as a host conducting itself, are detected and automatically broken.)

While it's allowed for a single host to be conducted by multiple conductors, the results can be discordent. Since only one propellor process can be run on a host at a time, one of the conductors will fail to communicate with it.

Note that a conductor can see all PrivData of the hosts it conducts.

Synopsis

Documentation

orchestrate :: [Host] -> [Host] Source #

Pass this a list of all your hosts; it will finish setting up orchestration as configured by the conducts properties you add to hosts.

main = defaultMain $ orchestrate hosts

class Conductable c where Source #

Class of things that can be conducted.

There are instances for single hosts, and for lists of hosts. With a list, each listed host will be conducted in turn. Failure to conduct one host does not prevent conducting subsequent hosts in the list, but will be propagated as an overall failure of the property.