Render partial templates with Ansible

2023-08-29

I manage the Klipper configuration for my Troodon 2.0 printer with Ansible. Rendering template files is old hat, but in this case printer.cfg is appended with generated sensor data after running Z probe calibration or PID tuning. template only renders complete files though, so I had to find a way to only render the top of the config file.

This config file is lengthy, and I didn't want to embed everything in blockinfile's content field in the tasks file, so I figured out you can call out to the template Ansible lookup plugin for a template in the current roles. This works great, now I can store the config file in a template and render it without embedding the config file content in the tasks file.

- name: troodon2 | Render non-generated parts of printer.cfg file
  blockinfile:
    dest: /home/pi/printer_data/config/printer.cfg
    content: "{{ lookup('template', 'templates/printer.cfg.j2') }}"
    # content: "{{ lookup('file', 'files/printer.cfg') }}"  # files can also be used
    state: present
  notify:
  - restart klipper

This results in a block being rendered in the printer.cfg, while leaving the generated sensor data alone, like so:

# BEGIN ANSIBLE MANAGED BLOCK
# This file contains common pin mappings for the BigTreeTech Octopus X7
# To use this config, the firmware should be compiled for the STM32F407 with a "32KiB bootloader"
...
[gcode_macro CLEAR_ACTIVE_SPOOL]
description: Clear active spool
gcode:
  {action_call_remote_method(
    "spoolman_set_active_spool",
    spool_id=None
  )}
# END ANSIBLE MANAGED BLOCK

#*# <---------------------- SAVE_CONFIG ---------------------->
#*# DO NOT EDIT THIS BLOCK OR BELOW. The contents are auto-generated.
#*#
#*# [stepper_z]
#*# position_endstop = 0.980
...