I’m creating this post to continue the discussion born from Advanced project ideas post, to keep that post focused on a general brainstorming ideas.
So, introducing: Zensible. An idea from @mutech.
I’m creating this post to continue the discussion born from Advanced project ideas post, to keep that post focused on a general brainstorming ideas.
So, introducing: Zensible. An idea from @mutech.
Let’s start from POC
And first step is:
identifying REAL-LIFE PROBLEMS that the software WILL SOLVE
I’m quite a bit away from knowing what the concept to be proven would actually be. “Making it better” is too vague. So far I collected a good amount of ideas and solution fragments on the website.
One thing I want Zensible to be able to do is to import Ansible playbooks.
So taking a moderately complex playbook using mostly builtin features and implementing something that can run it without Python and without deploying software remotely (if possible) would be a good test case.
Then using this to step through various iterations, implementing things the way we want it to be done and collecting some experience would be a good basis for comparing the real difference between Ansible and something.
And it’s always good to have a decent test.
A first iteration could use an SSH connection and implement ansible builtins as shell commands and file operation on that connection, for one system.
That would provide a base line showing how far Ansible is away from a direct implementation. The least I would expect from that is much better performance.
That’s however quite a bit of work, because it would require a kind of “expect” framework (an old tcl thing automating shell interactions, there are probably better things out there) on a PTY via ssh. That’s at least needed to get a reliable support for sudo and to be able to work with interactive commands (that’s a bit fringy).
I’m more inclined to write specs for some of the core concepts at the moment, but that’s what I would look into to get fast results and something tangible.
Finally had some time to go through the website. I’m also not quite knowledgeable of Ansible so thanks a lot for the rundown.
For what I understood, Ansible takes a machine’ state (e.g., user ‘foo’ does not exist) and you write declaratively the goal state (user ‘foo’ exists) and Ansible automagically brings the machine to the goal state. If it was already in the goal state it does nothing.
It’s limiting when you are in a complex scenario where it would be better to define the “how” to reach the goal state, with some logic to be executed.
With Zensible you want to introduce the concept of “Systems” to replace the Ansible “Tasks” (the goal states that you define in yaml). Systems would be a way to define the goal state like in Ansible + being able to define the actions to reach that state.
So I imagine we would be in the state “no foo user exists”, then write a system for the state “user exists, (actions: [useradd,…])”. Kinda like a finite state machine where the actions are the transitions between states.
In your website, the systems section also go over the concept of “Queries”, a way to obtain info on the current state of a machine (in a JSON format). It could be upgraded to a first-class citizen instead of keeping it as a sub-section in systems. It seems pretty important!
Some questions:
Perhaps systems should be comprised of “Goal State”, “Actions” (to reach the state) and “Queries” to check the state before and after every action? I see them more as triples.
Should actions be actual linux commands or an abstraction? Like an “add user” action, but behind the scenes it’s a series of shell commands. In this case the community can create pluggable, downloadable, actions (in an ideal world where no one writes malicious actions).
I might have gotten the idea of actions wrong the entire time so let me know!
BTW why not just “zenbook” instead of “zensibook”?
The term “system” refers to anything that has a state. Think “object” from OO world, but not (necessarily) inheritance.
Queries are methods to access the state in whole or part.
Actions are methods to (potentially) change the state.
In a Zenbook (you’re right, the ‘si’ is not needed), you would describe the desired state of a system, f.e. a host (in whole or part).
An Ansible task would be a Zensible assertion (a user with some properties exists).
If Zensible finds that reality does not match the assertion, it checks if it finds actions that can change that. If so, it does it, if not somebody has to change that by defining a new action that can implement the required changes.
The action can then be published and from then on can be used.
So far, I just described what people would do in any programming language. I’m using OO terms because the focus is on the three concepts of real state (the thing), desired state (the assertion) and actions to transform the state.
It’s important that queries don’t have side effects though.
I’m using “system” instead of “object” because I try to avoid OO flame wars.
Heavy use of contracts (pre/post conditions and system invariants) is important to allow zensible to automatically select algorithms to create desired state. This will of course not always work, but I hope that it could in at least many cases.
It’s also important to support concurrency and make dry-runs more meaningful.
Does this answer the question about “Goal states”? We thought of the same thing, but use different terminology here.
Actions are an abstraction. There can also be many implementations of an action (as long as they all implement the same contract). Especially different implementations for platforms/versions/etc. So you could have one implementation that edits /etc/passwd and another using useradd/mod/del.
It should be easy to implement an action, f.e. as a shell script fragment.
The same is true for queries.
One of the side aspects of my approach is to be able to estimate the impact of state.
Say a software needs a directory be present. That means that if a process wants to delete, rename or modify the directory, Zensibe can check if anything it knows about depends on the state of the directory. If so, it looks at the thing. To make the change safely, it might need to stop or pause the software’s service.
If all of this is expressed by means of contracts, Zensible can detect such dependencies and act on them.
I don’t know how far that concept can go in practice. Really looking forward to give it a try.
You would also not need “become root”, because Zensible should be able to determine that an action requires privileges. So if you connect as normal user and want to create a new user, you would violate a precondition “user is admin”. Then Zensible can check if there is a method to elevate the permission and choose to sudo root. The precondition could also be “user in group admin” and less than root could suffice.
Again, I don’t know how much of that is practically doable…
Alright now I’m grasping the idea a bit better. There is a lot on the plate here, I think the best way to go is as @g41797 said: start with POCs. Perhaps a small one like ‘create a file’? I imagine something like:
Pre-condition: file pointed with path /home/example.txt does not exist
Action: touch file with that path
Post-condition: file exists with path /home/example.txt
The query to do this check would be a simple exist check.
This would be the most stripped down example I can think of and it already pulls in all the ideas of “initial state”, “goal state”, “actions” and “queries”.
To define the host to connect to (and perform the deeds), we could do a super simple parse of an inventory file with a single line: “host: < ip >”.
I’m the kind of person that learns more by doing that’s why I’m trying to come up with a small roadmap to get something going .
I find it incredibly hard to explain my vision for how that’s supposed to work.
That’s a bad sign.
But yes, I see you adopt my lingo, that’s great!
I started working on a POC that has a practical use for me, the setup of the web server. I did that manually, and I try to replicate that.
Right now I’m stuck in SSH. That’s something Zensible will need everywhere and it needs a whole lot of fine grained control over it. So that will take a bit. That also opens up a whole lot of questions about Zig (I’m still a Zig noob) and how to do things properly, so I’m going to slow down on communication about Zensible and get my head into hacking.
After SSH, I will try to get to executing remote shell commands in order to be able to simulate manual actions via the shell. That’s ugly automation, but it’s also very productive and a good way to get to results fast.
That’s when the whole contract thing will come into play and I can define queries and actions in terms of script fragments.
The next step is to use these queries and actions to specify systems. In your POC the systems involved would be “host”, “file system” and “file”. I’m going to need that for my POC anyway.
Then comes the big issue, how to specify that in terms of inventory and play/zenbook.
For a starter I will probably just use Ansible syntax (a yaml inventory and playbook) and convert that into whatever internal data structures my systems and workflow engine (or whatever the thing driving automation should be called) can work with easiest. Since Ansible imports will be an important feature, I can just as well get started with that and save myself the headache to cook up a “language” before I know what it’s supposed to do and how.