PyObjects renderer allows you to use normal Python functions to repeat actions. In this article, we’ll implement a Package-File-Service pattern as a reusable Python function.
To follow this article, you must be fluent with Linux command line interface, know Salt Stack, PyObjects renderer and Python programming language. The code has been written on Salt Beryllium.
This article is beta quality, as I had to change some strings to different from the system I used this on. The code itself is alpha, don’t go deploying it on your production servers yet.
The End Result
You don’t need many files:
$ find /srv/salt/dhcpd/ dhcpd.sls # your module pfs.sls # pfs.sls library, download it from this page dhcpd.conf.jinja # your template
Your module only needs 3 lines (yes, three) to implement package-file-service.
#!pyobjects from salt://manage/pxemaster/pfs.sls import pfs pfs("isc-dhcp-server", files="/etc/dhcp/dhcpd.conf", module="dhcpd")
You can run it normally.
$ sudo salt-call --local state.sls manage/pxemaster/ -l debug --state-output=mixed
It’s a real package-file-service pattern, so that the daemon is reloaded automatically as needed.
Advanced Usage
This is the library that implements the pfs(service, file) pattern.
There are many ways to call pfs(). Short alias name with a single file:
pfs("isc-dhcp-server", files="/etc/dhcp/dhcpd.conf", module="dhcpd"))
You must provide the template file dhcpd.conf.jinja in the same directory. Template name is the file basename (path removed) and suffix “.jinja” added. You are free to use jinja markup or leave it out.
Long function name (exactly the same function as pfs()):
packageFileService("isc-dhcp-server", files="/etc/dhcp/dhcpd.conf", module="dhcpd")
Multiple configuration files. Notice how files parameter must be list when there are multiple files:
pfs("isc-dhcp-server", files=["/etc/dhcp/dhcpd.conf", "/tmp/foobar"], module="dhcpd")
If your service (daemon) has different name from the package, use service parameter
pfs("foo-utils", "/etc/food", service="food", , module="dhcpd")
Currently, you pfs.sls doesn’t automatically detect your module (the directory under /srv/salt/ containing your init.sls). Instead, you can provide it with the module parameter.
Download pfs.sls
You can copy pfs.sls from below. The pfs.sls code licenced under GPL 3 or later.
#!pyobjects # Copyright 2015 Tero Karvinen http://TeroKarvinen.com def packageFileService(package, files, service=None, module=None, context=None): "Package-file-service pattern as function. " from os.path import basename # import must be inside the function declaration assert type(package)==str if type(files)==str: files=[files] assert type(files)==list if service==None: service=package assert len(module)>0 # autodetect not yet implemented with Pkg.installed(package): Service.running(service, enable=True) with Service(service, "watch_in"): # TODO: automatic relative source salt:// path, see config("arg") and others for target in files: source="salt://%s/%s.jinja" % (module, basename(target)) File.managed(target, source=source, template="jinja", context=context) pfs = packageFileService