# 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.
#
# Runs over SSH, not a bare local-exec command: OpenTofu itself runs from
# the Office1 operator VM (D-103), not on the vcloud host where the bridge
# interfaces exist, so the command has to hop there explicitly. Assumes
# passwordless SSH + passwordless sudo to var.vcloud_host_ssh_target as this
# repo's usual jumphost-session conventions provide -- 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 = "ssh ${var.vcloud_host_ssh_target} 'sudo tc qdisc replace dev ${var.bridge_name} root netem ${var.netem_args}'"
}
provisioner "local-exec" {
when = destroy
command = "ssh ${self.input.ssh_target} 'sudo tc qdisc del dev ${self.input.bridge_name} root' || true"
}
}