# netem-link: applies `tc qdisc ... netem` WAN-simulation parameters to a
# modules/mesh-link bridge (D-100). Confirmed mechanism this session,
# fetched directly from OpenTofu's own official docs (opentofu.org, tag
# current as of 2026-07-09): `libvirt_network` has no netem-equivalent
# argument at all, so this has to happen as a provisioner-only side effect,
# not a libvirt resource. OpenTofu's own docs recommend `terraform_data`
# over the older `null_resource` for exactly this "provisioner with no
# logical managed resource to attach to" case -- used here, not null_resource.
#
# Execution locus (amended 2026-07-21): the original design assumed OpenTofu
# runs from the Office1 operator VM (D-103) and therefore ALWAYS hopped via
# SSH. D-128 fixed the outer root's execution ON the vcloud host itself
# (Plane 1), where the mesh bridges live -- so an SSH self-hop would demand a
# new standing self-ssh credential for nothing. `vcloud_host_ssh_target` is
# now OPTIONAL: empty (the default) runs `sudo tc` directly on the machine
# invoking `tofu apply` (correct for the D-128 outer root); non-empty keeps
# the original SSH hop for any future root that runs remotely. Passwordless
# sudo for the tc verbs is assumed either way -- provided on vcloud by the
# operator-installed scoped fragment /etc/sudoers.d/netem-tc (repo copy
# scripts/sudoers.d/netem-tc; operator-ruled 2026-07-21), not configured here.
#
# UNVERIFIED, flagged plainly: this whole resource has not been run for
# real this session (no `tofu` binary, no live vcloud host, no bridge to
# test against). `tc qdisc replace` (not `add`) is used deliberately so a
# re-apply is idempotent rather than erroring "RTNETLINK answers: File
# exists" -- a standard, well-known tc usage pattern, not something specific
# to this repo.
resource "terraform_data" "netem" {
triggers_replace = [var.bridge_name, var.netem_args]
# `input` exists ONLY to make the values reachable from the destroy-time
# provisioner below. A destroy provisioner may reference ONLY `self`,
# `count.index`, or `each.key` -- never `var.*`. The original code
# interpolated var.vcloud_host_ssh_target and var.bridge_name directly into
# the destroy command, which OpenTofu rejects at INIT time:
#
# Error: Invalid reference from destroy provisioner
# Destroy-time provisioners and their connection configurations may only
# reference attributes of the related resource, via 'self', ...
#
# So this module could not even initialize, let alone apply. Stashing the
# values in `input` and reading them back as `self.input.*` is the canonical
# fix (OpenTofu's own guidance for exactly this case). (DOCFIX-194, 2026-07-13.)
input = {
ssh_target = var.vcloud_host_ssh_target
bridge_name = var.bridge_name
}
provisioner "local-exec" {
command = var.vcloud_host_ssh_target != "" ? "ssh ${var.vcloud_host_ssh_target} 'sudo tc qdisc replace dev ${var.bridge_name} root netem ${var.netem_args}'" : "sudo tc qdisc replace dev ${var.bridge_name} root netem ${var.netem_args}"
}
provisioner "local-exec" {
when = destroy
command = self.input.ssh_target != "" ? "ssh ${self.input.ssh_target} 'sudo tc qdisc del dev ${self.input.bridge_name} root' || true" : "sudo tc qdisc del dev ${self.input.bridge_name} root || true"
}
}