Renaming Resources
MerakiRenaming a resource in nac-meraki is a supported operation — networks, devices, admins,
group policies, and other resources can all be renamed by updating the data model YAML.
Because Terraform tracks resources by their for_each key, which is built from the
resource name, a rename requires an additional step to tell Terraform that the resource
has moved to a new key rather than been deleted and replaced.
How Terraform Tracks Resources
Section titled “How Terraform Tracks Resources”In nac-meraki, each resource’s state key includes its name. A network named
Branch Office London is tracked as:
module.meraki.meraki_network.organizations_networks["EU/My Org/Branch Office London"]Renaming it to London Branch in the data model changes the key to:
module.meraki.meraki_network.organizations_networks["EU/My Org/London Branch"]Without any additional instruction, Terraform reads this as the old resource being removed and a new one being added. For a network, this cascades to every child resource underneath it — VLANs, switch ports, wireless SSIDs, firewall rules, group policies — all of which are also rekeyed and would be destroyed and recreated.
The Correct Process: moved Blocks
Section titled “The Correct Process: moved Blocks”The standard Terraform mechanism for handling a key change without destroying
infrastructure is the moved block. It instructs Terraform to update the state key
in place:
moved { from = module.meraki.meraki_network.organizations_networks["EU/My Org/Branch Office London"] to = module.meraki.meraki_network.organizations_networks["EU/My Org/London Branch"]}This block is placed in a moved.tf file in the Terraform working directory (alongside
main.tf) before running terraform apply. Terraform reads it during apply and updates
the state accordingly — no resources are destroyed or recreated. The result is
0 to destroy, 0 to add for the renamed resources, with 1 to change per renamed
resource reflecting the name update pushed to the Meraki API.
Once the apply succeeds, moved.tf must be removed. It is only valid for the single
apply that carries the rename — leaving it in place may cause errors on subsequent plans.
Affected Resource Types
Section titled “Affected Resource Types”A moved block is not required for every rename. For most resources, a delete and
recreate is acceptable — the disruption is brief and the resource comes back with the
new name. A moved block is recommended when the destroy/recreate impact is significant.
The clearest cases where a moved block is strongly recommended are network and device
renames — a single rename cascades to every child resource underneath, causing widespread
destruction and recreation of VLANs, switch ports, SSIDs, firewall rules, and more.
Administrator renames are another example where briefly recreating the resource could
revoke access mid-apply.
For all other resource types, evaluate the blast radius before deciding — if a delete
and recreate is acceptable in your environment, no moved block is needed.
Cascading resources — highest impact
Section titled “Cascading resources — highest impact”For meraki_network and meraki_device, the name is embedded in the key of every
child resource. A single rename cascades to all resources underneath:
| Resource | What cascades |
|---|---|
meraki_network | All network sub-resources: group policies, VLAN profiles, VLANs, switch ports, SSIDs, firewall rules, floor plans, webhooks, etc. |
meraki_device | All device sub-resources: routing interfaces, static routes, etc. |
A moved block is required for every affected resource — the parent and each child
individually. For a network rename, this can mean dozens of blocks across VLANs,
switch ports, SSIDs, firewall rules, and more.
Network sub-resources
Section titled “Network sub-resources”These resources have their own name in the key (in addition to the network name).
Each requires a separate moved block when renamed:
| Resource | Mutable name in key |
|---|---|
meraki_network_group_policy | group policy name |
meraki_network_vlan_profile | VLAN profile name |
meraki_network_floor_plan | floor plan name |
meraki_network_webhooks_payload_template | payload template name |
meraki_network_webhooks_http_server | HTTP server name |
Device sub-resources
Section titled “Device sub-resources”| Resource | Mutable name in key |
|---|---|
meraki_switch_routing_interface | routing interface name |
meraki_switch_routing_static_route | static route name |
meraki_switch_access_policy | access policy name |
meraki_switch_port_schedule | port schedule name |
meraki_switch_stack | stack name |
meraki_switch_stack_routing_interface | routing interface name |
meraki_switch_stack_routing_static_route | static route name |
Organization-level resources
Section titled “Organization-level resources”| Resource | Mutable name in key |
|---|---|
meraki_organization_admin | admin name |
meraki_organization_adaptive_policy_group | adaptive policy group name |
meraki_organization_adaptive_policy_acl | adaptive policy ACL name |
meraki_organization_adaptive_policy | policy name |
meraki_organization_policy_object | policy object name |
meraki_organization_policy_object_group | policy object group name |
meraki_organization_auth_radius_server | RADIUS server name |
Appliance and wireless resources
Section titled “Appliance and wireless resources”| Resource | Mutable name in key |
|---|---|
meraki_appliance_static_route | static route name |
meraki_appliance_ssid | SSID name |
meraki_appliance_rf_profile | RF profile name |
meraki_wireless_rf_profile | RF profile name |
meraki_wireless_ssid | SSID name |
meraki_wireless_ssid_identity_psk | identity PSK name |
For all non-cascading resource types, the destroy/recreate impact is limited to the
resource itself. The moved block approach works for all of them.
Simplifying with meraki_rename.py
Section titled “Simplifying with meraki_rename.py”Writing moved blocks manually is straightforward for a single rename but becomes
tedious when multiple resources are involved — particularly for networks, where dozens
of child resources each need their own block.
The scripts/meraki_rename.py script automates this by reading a Terraform plan JSON
and generating the complete moved.tf for you. For cascading resource types
(meraki_network, meraki_device), it automatically discovers all child resource pairs
from the plan and generates individual moved blocks for each — you only need a
single top-level entry in renames.yaml.
Modes of operation
Section titled “Modes of operation”| Mode | Command | Output |
|---|---|---|
| Dry run | --dry-run | renames.yaml listing detected candidates for review |
| Generate | --renames renames.yaml | moved.tf from a reviewed renames.yaml |
| All-in-one | --no-review | renames.yaml + moved.tf in one step |
Two-step workflow (recommended)
Section titled “Two-step workflow (recommended)”Step 1 — detect rename candidates and write renames.yaml:
python3 scripts/meraki_rename.py plan.json --dry-runplan.json is optional — if omitted, the script runs terraform plan automatically
and saves plan.json to the working directory. If you already have a plan JSON from
a pipeline artifact, pass it directly to skip the terraform step.
Review renames.yaml and remove any entries that are not genuine renames before
proceeding.
Step 2 — generate moved.tf:
python3 scripts/meraki_rename.py --renames renames.yamlRun terraform plan to confirm 0 to destroy, 0 to add for renamed resources
before applying.
The renames.yaml Format
Section titled “The renames.yaml Format”The dry-run step auto-generates renames.yaml. You can also write or edit it manually:
renames: - name: "module.meraki.meraki_network.organizations_networks" from: "EU/My Org/Branch Office London" to: "EU/My Org/London Branch" - name: "module.meraki.meraki_organization_admin.organizations_admins" from: "EU/My Org/old.admin@cisco.com" to: "EU/My Org/new.admin@cisco.com" - name: "module.meraki.meraki_network_group_policy.networks_group_policies" from: "EU/My Org/Branch Office London/IOT" to: "EU/My Org/London Branch/IOT_Devices"name— full Terraform resource base address (module + type + resource name)from— full index key of the resource being deletedto— full index key of the resource being created
For meraki_network and meraki_device entries, you do not need individual entries
in renames.yaml for VLANs, ports, SSIDs, etc. — the script reads them from the plan
and generates the individual moved blocks in moved.tf automatically.
All-in-one mode
Section titled “All-in-one mode”python3 scripts/meraki_rename.py plan.json --no-reviewDetects candidates and generates moved.tf in one step. renames.yaml is still
written for reference. Recommended only for controlled environments where false
positives are unlikely.
Generating plan.json
Section titled “Generating plan.json”The script takes a plan JSON file as input. To produce one locally:
terraform plan -out=plan.tfplanterraform show -json plan.tfplan > plan.jsonIn a CI/CD pipeline, plan.json should be archived as a build artifact so operators
can download it without needing Terraform installed locally.
Things to Keep in Mind
Section titled “Things to Keep in Mind”- Review
renames.yamlbefore generatingmoved.tf— The auto-detection heuristic is conservative but a resource deletion paired with an unrelated new resource in the same apply can appear as a rename. Always verify before proceeding. moved.tfmust be deleted after apply — It is only valid for the apply that carries the rename. Leaving it in place may cause errors on subsequent plans.- One apply at a time — If multiple renames are batched with other changes, verify the plan carefully before applying.
- State backend must be accessible — Terraform applies the
movedblocks duringterraform apply. The script only reads the plan and does not modify state directly.