Enrico Zini: Playbooks, host vars, group vars
This is part of a series of posts on ideas for an ansible-like provisioning
system, implemented in Transilience.
Host variables
Ansible allows to specify per-host variables, and I like that. Let's try to
model a host as a dataclass:
This should have enough information to create a connection to the host, and can
be subclassed to add host-specific dataclass fields.
Host variables can then be provided as default constructor arguments when
instantiating Roles:
Group variables
It looks like I can model groups and group variables by using dataclasses as
mixins:
Doing things like filtering all hosts that are members of a given group can be
done with a simple
And an actual playbook will now look like something like this:
It looks quite straightforward to me, works on any number of hosts, and has a
proper command line interface:
Next step: check mode!
@dataclass class Host: """ A host to be provisioned. """ name: str type: str = "Mitogen" args: Dict[str, Any] = field(default_factory=dict) def _make_system(self) -> System: cls = getattr(transilience.system, self.type) return cls(self.name, **self.args)
# Add host/group variables to role constructor args host_fields = f.name: f for f in fields(host) for field in fields(role_cls): if field.name in host_fields: role_kwargs.setdefault(field.name, getattr(host, field.name)) role = role_cls(**role_kwargs)
@dataclass class Webserver: server_name: str = "www.example.org" @dataclass class Srv1(Webserver): ...
isinstance or issubclass test.
Playbooks
So far Transilience is executing on one host at a time, and Ansible can execute
on a whole host inventory.
Since the most part of running a playbook is I/O bound, we can parallelize
hosts using threads, without worrying too much about the performance impact of
GIL.
Let's introduce a Playbook class as the main entry point for a playbook:
class Playbook: def setup_logging(self): ... def make_argparser(self): description = inspect.getdoc(self) if not description: description = "Provision systems" parser = argparse.ArgumentParser(description=description) parser.add_argument("-v", "--verbose", action="store_true", help="verbose output") parser.add_argument("--debug", action="store_true", help="verbose output") return parser def hosts(self) -> Sequence[Host]: """ Generate a sequence with all the systems on which the playbook needs to run """ return () def start(self, runner: Runner): """ Start the playbook on the given runner. This method is called once for each system returned by systems() """ raise NotImplementedError(f" self.__class__.__name__ .start is not implemented") def main(self): parser = self.make_argparser() self.args = parser.parse_args() self.setup_logging() # Start all the runners in separate threads threads = [] for host in self.hosts(): runner = Runner(host) self.start(runner) t = threading.Thread(target=runner.main) threads.append(t) t.start() # Wait for all threads to complete for t in threads: t.join()
from dataclasses import dataclass import sys from transilience import Playbook, Host @dataclass class MyServer(Host): srv_root: str = "/srv" site_admin: str = "enrico@enricozini.org" class VPS(Playbook): """ Provision my VPS """ def hosts(self): yield MyServer(name="server", args= "method": "ssh", "hostname": "host.example.org", "username": "root", ) def start(self, runner): runner.add_role("fail2ban") runner.add_role("prosody") runner.add_role( "mailserver", postmaster="enrico", myhostname="mail.example.org", aliases= ... ) if __name__ == "__main__": sys.exit(VPS().main())
./provision --help usage: provision [-h] [-v] [--debug] Provision my VPS optional arguments: -h, --help show this help message and exit -v, --verbose verbose output --debug verbose output
A while ago, I got
(+1) to bump the suggestions that you find interesting. And click on the Watch button on the homepage to receive notifications when others submit suggestions so that you can evaluate those suggestions and possibly improve them through your comments.
In the end, this can only help those that are looking for ways to contribute to Debian: maybe some of them will formalize a concrete action plan and
Powershell and nushell take unix piping beyond raw streams of text to
structured or typed data. Is it possible to keep a traditional shell
like bash and still get typed pipes?
I think it is possible, and I'm now surprised noone seems to have done it
yet. This is a fairly detailed design for how to do it. I've not
implemented it yet. RFC.
Let's start with a command called
The Python programming language is one of the most popular and in huge demand. It is free, has a large community, is intended for the development of projects of varying complexity, is easy to learn, and opens up great opportunities for programmers. To work comfortably with it, you need special Python tools, which are able to simplify your work. We have selected the best Python tools that will be relevant in 2021.
In May I was assigned 13.5 hours of work by Freexian's Debian LTS
initiative and carried over 4.5 hours from earlier months. I worked
16 hours and will carry over the remainder.
I finished reviewing the futex code in the PREEMPT_RT patchset for
Linux 4.9, and identified several places where it had been
mis-merged with the recent futex security fixes. I sent a patch for
these upstream, which was accepted and applied in v4.9.268-rt180.
I have continued updating the Linux 4.9 package to later upstream
stable versions, and backported some missing security fixes. I have
still not made a new upload, but intend to do so this week.
OK, this is not an easy post. I have been maintaining Cinnamon in Debian for quite some time, since around the times version 4 came out. The soon (hahaha) to be released Bullseye will carry the last release of the 4-track, but version 5 is already waiting, After Bullseye, the future of Cinnamon in Debian currently looks bleak.
Since my switch to
Today, Fre(i)e Software GmbH has been contracted for packaging
A while back there was a thread on one of our company mailing lists about
Continuing with
I'm writing up a
Two TODO items in the margin
Collated TODOs in a list