Tuesday December 12th, 2023 NCLUG Meeting

Sean Reifschneider jafo00 at gmail.com
Wed Dec 13 22:32:37 UTC 2023


I came very close to using Salt instead of Ansible ~7 years ago when I was
switching from puppet.  Ansible has served us well.

Just to clarify, I'm not proposing uPlaybook as a replacement to Ansible or
Salt, the "u" stands for "micro", and it's really focused more towards a
shell scripting alternative, or creating scaffolding or project templates.
The primary features it has over shell scripts is: templating, declarative
(and triggering handlers on change), and built-in argument handling.

Using Jinja2 templating in the playbooks is an interesting idea.  They must
do some tricks to help error messages point at the original line number
rather than the template line number.  I agree that Ansible looping is not
ideal, but it is workable.

In the previous iteration of uPlaybook, it was YAML driven (which seemed
logical as a "micro ansible", but I took some different directions with
looping and conditionals.  You could have a "block" of tasks, and that
block could have a loop on it.  "if", "elif", and "else" were similar
"blocks" and could have conditionals on them:

    - block:
      tasks:
        - echo:
          msg: "Host {{hostname}}"
       loop:
        - vars:
          hostname: foo
        - vars:
          hostname: bar
    - if:
      condition: "do_remove"
      tasks:
        - rm:
          path: whatever/path/to/remove

While this in some ways was a nice change from Ansible's looping, it made
me feel like it might be a little less insane, but it was still clearly
insane.  So that's why I started experimenting with what it might look like
to be a different syntax.

As I said above, not going to replace Salt or Ansible, but I do think it
has some pretty interesting use cases.  I plan to give it a shot for
setting up my workstation when 24.04 comes out, because I've never been
very good at keeping that up to date by using Ansible, just because it was
kind of cumbersome to run against the local machine without an inventory,
and cumbersome to set up all the tasks.  Maybe I'll still run into that
though.

But, if as a thought experiment, you have any thoughts about it, I value
your opinion.

Sean

On Wed, Dec 13, 2023 at 10:52 AM Aaron D. Johnson <adj at fnord.greeley.co.us>
wrote:

> Sean Reifschneider writes:
> > So on the topic of Salt and YAML...  Months ago I showed off a "mini
> > Ansible", which had some of the Ansible ideas for declarative system
> > configuration, similar to what Salt does, though focused on a single
> > computer or smaller (where Ansible and the like are focused on
> > working with a fleet of machines).
> >
> > I came to realize that, despite working with YAML in Ansible for
> > ~5-7 years now, I really despise YAML for this.
>
> I picked up Salt as my preferred solution on account of it being my
> team's tool of choice at work.  Overall, I am pretty happy with it.
> In a large environment, I do especially enjoy it's fine grained
> targetting options.  For instance, being able to say "run this chunk
> of code against any system with an AMD processor" or "run the Ethernet
> LLDP, ethtool, network bonding states against bare-metal machines
> only."
>
> I didn't go into this last night, but the times I have seen looping
> and conditional constructs in Ansible playbooks, it was a less than
> great experience.
>
> The Salt alternative to this is that, while the state files are in
> fact in YAML syntax, they are first fed through the Jinja templating
> engine which allow the user to do something like this fragment:
>
>     # Loop over each defined VRRP interface, drop a Jinja-templated
>     # systemd unit file for it, then start and enable said service.
>     {% for iface in pillar['vrrp']['interfaces'].keys() %}
>     /usr/local/lib/systemd/system/vrrp-{{- iface -}}.service:
>       file.managed:
>         - source:
> salt://files/per-role/ipv4-router-vrrp/vrrp-interface.service.jinja
>         - template: jinja
>         - user: root
>         - group: root
>         - mode: 0644
>         - backup: minion
>         # These are all passed to the Jinja source file for expansion
>         - iface: {{ iface }}
>         - auth_secret: {{
> pillar['vrrp']['interfaces'][iface]['auth-secret'] }}
>         - virtual_ipv4: {{
> pillar['vrrp']['interfaces'][iface]['virtual-ipv4'] }}
>         - virtual_router_id: {{
> pillar['vrrp']['interfaces'][iface]['virtual-router-id'] }}
>         - virtual_router_priority: {{
> pillar['vrrp']['interfaces'][iface]['virtual-router-priority'] }}
>
>     vrrp-{{- iface -}}.service:
>       service.running:
>         - enable: True
>     {% endfor %}
>
> The curly braces introduce each Jinja element.  {% ... %} for logic
> and {{ ... }} for simple variable substitution.  While this is not the
> prettiest block of code ever written, I do find it not-too-terrible.
>
> > Back at the beginning of October I started an experiment: What would
> > it be like if Ansible had a Python syntax?  I've come up with
> > something I'm fairly happy with that achieves this, though again at
> > a much smaller scale.  One of the examples from the tutorial is:
> >
> >     from uplaybook import pyinfra, fs, core
> >
> >     def restart_apache():
> >         pyinfra.systemd.service(service="apache2", restarted=True)
> >
> >     pyinfra.apt.packages(packages=["apache2", "libapache2-mod-uwsgi"])
> >     for module_name in ["proxy", "uwsgi"]:
> >         fs.ln(src="/etc/apache2/mods-available/{{ module_name }}.load",
> >               path="/etc/apache2/mods-enabled",
> >               symbolic=True).notify(restart_apache)
>
> I'd much rather use this syntax to the equivalent Ansible playbook
> YAML loop.  Am pretty well settled on Salt at this point in time,
> though.  So many options out there...  :)
>
> Thanks!
>
> - Aaron
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.nclug.org/pipermail/nclug/attachments/20231213/2a42fba5/attachment.htm>


More information about the NCLUG mailing list