From 00b0916cc01004fd4474ee667ad34cf6eb48e967 Mon Sep 17 00:00:00 2001 From: ejc3 Date: Sun, 25 Oct 2026 12:56:09 +0000 Subject: [PATCH] Render the secondary IPv4 command without Python indentation --- firecracker-dev.tf | 9 ++++----- scripts/fcvm-secondary-ipv4-command.tftpl | 3 +++ scripts/test-fcvm-secondary-ipv4.py | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 scripts/fcvm-secondary-ipv4-command.tftpl diff --git a/firecracker-dev.tf b/firecracker-dev.tf index 770e2811..6ef988a7 100644 --- a/firecracker-dev.tf +++ b/firecracker-dev.tf @@ -340,11 +340,10 @@ resource "aws_ssm_association" "firecracker_dev_secondary_ipv4" { } parameters = { - commands = <<-EOT - python3 - '${one(setsubtract(aws_network_interface.firecracker_dev[0].private_ips, [aws_network_interface.firecracker_dev[0].private_ip]))}' <<'PYSECONDARY' - ${indent(6, chomp(file("${path.module}/scripts/fcvm-secondary-ipv4.py")))} - PYSECONDARY - EOT + commands = templatefile("${path.module}/scripts/fcvm-secondary-ipv4-command.tftpl", { + address = one(setsubtract(aws_network_interface.firecracker_dev[0].private_ips, [aws_network_interface.firecracker_dev[0].private_ip])) + script = chomp(file("${path.module}/scripts/fcvm-secondary-ipv4.py")) + }) executionTimeout = "120" } } diff --git a/scripts/fcvm-secondary-ipv4-command.tftpl b/scripts/fcvm-secondary-ipv4-command.tftpl new file mode 100644 index 00000000..efcdfd7b --- /dev/null +++ b/scripts/fcvm-secondary-ipv4-command.tftpl @@ -0,0 +1,3 @@ +python3 - '${address}' <<'PYSECONDARY' +${script} +PYSECONDARY diff --git a/scripts/test-fcvm-secondary-ipv4.py b/scripts/test-fcvm-secondary-ipv4.py index c82c521d..d39e1f7d 100644 --- a/scripts/test-fcvm-secondary-ipv4.py +++ b/scripts/test-fcvm-secondary-ipv4.py @@ -2,6 +2,8 @@ """The added address survives boot and never restarts the live primary interface.""" import importlib.util import json +import os +import sys from pathlib import Path import subprocess import tempfile @@ -60,6 +62,22 @@ def run(args, **kwargs): module.configure('10.0.1.42; reboot', config, run) self.assertFalse(config.exists()) + def test_managed_shell_command_passes_unindented_python_on_stdin(self): + template = ROOT / 'scripts/fcvm-secondary-ipv4-command.tftpl' + command = template.read_text().replace('${address}', '10.0.1.42').replace( + '${script}', (ROOT / 'scripts/fcvm-secondary-ipv4.py').read_text().rstrip()) + with tempfile.TemporaryDirectory() as directory: + interpreter = Path(directory) / 'python3' + interpreter.write_text(f'#!{sys.executable}\nimport sys\n' + 'assert sys.argv[1:] == ["-", "10.0.1.42"]\n' + 'compile(sys.stdin.read(), "", "exec")\n') + interpreter.chmod(0o700) + subprocess.run(['/bin/sh', '-ec', command], check=True, capture_output=True, + text=True, env={**os.environ, 'PATH': directory}) + association = (ROOT / 'firecracker-dev.tf').read_text().split( + 'resource "aws_ssm_association" "firecracker_dev_secondary_ipv4"', 1)[1] + self.assertIn('templatefile("${path.module}/scripts/fcvm-secondary-ipv4-command.tftpl"', association) + def test_managed_association_runs_the_script_on_the_arm_host(self): tf = (ROOT / 'firecracker-dev.tf').read_text() self.assertIn('resource "aws_ssm_association" "firecracker_dev_secondary_ipv4"', tf)