PageSourceSearch

https://opentofu.org/assets/js/300884bc.bc0ca40d.js

js opentofu.org collected 2026-10-02 02:27:37 UTC 25,210 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkwebsite=globalThis.webpackChunkwebsite||[]).push([[5851],{5988(e,n,o){o.r(n),o.d(n,{assets:()=>t,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>s,toc:()=>l});let s=JSON.parse('{"id":"language/modules/develop/refactoring","title":"Refactoring","description":"How to make backward-compatible changes to modules already in use.","source":"@site/versioned_docs/version-v1.6/language/modules/develop/refactoring.mdx","sourceDirName":"language/modules/develop","slug":"/language/modules/develop/refactoring","permalink":"/docs/v1.6/language/modules/develop/refactoring","draft":false,"unlisted":false,"editUrl":"https://github.com/opentofu/opentofu/edit/v1.6/website/docs/language/modules/develop/refactoring.mdx","tags":[],"version":"v1.6","frontMatter":{"description":"How to make backward-compatible changes to modules already in use."},"sidebar":"docs","previous":{"title":"Publishing Modules","permalink":"/docs/v1.6/language/modules/develop/publish"},"next":{"title":"Standard Module Structure","permalink":"/docs/v1.6/language/modules/develop/structure"}}');var a=o(74848),c=o(28453);let i={description:"How to make backward-compatible changes to modules already in use."},r="Refactoring",t={},l=[{value:"<code>moved</code> Block Syntax",id:"moved-block-syntax",level:2},{value:"Renaming a Resource",id:"renaming-a-resource",level:2},{value:"Enabling <code>count</code> or <code>for_each</code> For a Resource",id:"enabling-count-or-for_each-for-a-resource",level:2},{value:"Renaming a Module Call",id:"renaming-a-module-call",level:2},{value:"Enabling <code>count</code> or <code>for_each</code> For a Module Call",id:"enabling-count-or-for_each-for-a-module-call",level:2},{value:"Removing <code>moved</code> Blocks",id:"removing-moved-blocks",level:2}];function d(e){let n={a:"a",admonition:"admonition",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,c.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"refactoring",children:"Refactoring"})}),"\n",(0,a.jsx)(n.p,{children:"In shared modules and long-lived configurations, you may eventually outgrow\nyour initial module structure and resource names. For example, you might decide\nthat what was previously one child module makes more sense as two separate\nmodules and move a subset of the existing resources to the new one."}),"\n",(0,a.jsxs)(n.p,{children:["OpenTofu compares previous state with new configuration, correlating by\neach module or resource's unique address. Therefore ",(0,a.jsx)(n.em,{children:"by default"})," OpenTofu\nunderstands moving or renaming an object as an intent to destroy the object\nat the old address and to create a new object at the new address."]}),"\n",(0,a.jsxs)(n.p,{children:["When you add ",(0,a.jsx)(n.code,{children:"moved"})," blocks in your configuration to record where you've\nhistorically moved or renamed an object, OpenTofu treats an existing object at\nthe old address as if it now belongs to the new address."]}),"\n",(0,a.jsxs)(n.h2,{id:"moved-block-syntax",children:[(0,a.jsx)(n.code,{children:"moved"})," Block Syntax"]}),"\n",(0,a.jsxs)(n.p,{children:["A ",(0,a.jsx)(n.code,{children:"moved"})," block expects no labels and contains only ",(0,a.jsx)(n.code,{children:"from"})," and ",(0,a.jsx)(n.code,{children:"to"})," arguments:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:"moved {\n  from = aws_instance.a\n  to   = aws_instance.b\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["The example above records that the resource currently known as ",(0,a.jsx)(n.code,{children:"aws_instance.b"}),"\nwas known as ",(0,a.jsx)(n.code,{children:"aws_instance.a"})," in a previous version of this module."]}),"\n",(0,a.jsxs)(n.p,{children:["Before creating a new plan for ",(0,a.jsx)(n.code,{children:"aws_instance.b"}),", OpenTofu first checks\nwhether there is an existing object for ",(0,a.jsx)(n.code,{children:"aws_instance.a"})," recorded in the state.\nIf there is an existing object, OpenTofu renames that object to\n",(0,a.jsx)(n.code,{children:"aws_instance.b"})," and then proceeds with creating a plan. The resulting plan is\nas if the object had originally been created at ",(0,a.jsx)(n.code,{children:"aws_instance.b"}),", avoiding any\nneed to destroy it during apply."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"from"})," and ",(0,a.jsx)(n.code,{children:"to"})," addresses both use a special addressing syntax that allows\nselecting modules, resources, and resources inside child modules. Below, we\ndescribe several refactoring use-cases and the appropriate addressing syntax\nfor each situation."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#renaming-a-resource",children:"Renaming a Resource"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsxs)(n.a,{href:"#enabling-count-or-for_each-for-a-resource",children:["Enabling ",(0,a.jsx)(n.code,{children:"count"})," or ",(0,a.jsx)(n.code,{children:"for_each"})," For a Resource"]})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#renaming-a-module-call",children:"Renaming a Module Call"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsxs)(n.a,{href:"#enabling-count-or-for_each-for-a-module-call",children:["Enabling ",(0,a.jsx)(n.code,{children:"count"})," or ",(0,a.jsx)(n.code,{children:"for_each"})," For a Module Call"]})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsx)(n.a,{href:"#splitting-one-module-into-multiple",children:"Splitting One Module into Multiple"})}),"\n",(0,a.jsx)(n.li,{children:(0,a.jsxs)(n.a,{href:"#removing-moved-blocks",children:["Removing ",(0,a.jsx)(n.code,{children:"moved"})," blocks"]})}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"renaming-a-resource",children:"Renaming a Resource"}),"\n",(0,a.jsx)(n.p,{children:"Consider this example module with a resource configuration:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'resource "aws_instance" "a" {\n  count = 2\n\n  # (resource-type-specific configuration)\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Applying this configuration for the first time would cause OpenTofu to\ncreate ",(0,a.jsx)(n.code,{children:"aws_instance.a[0]"})," and ",(0,a.jsx)(n.code,{children:"aws_instance.a[1]"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["If you later choose a different name for this resource, then you can change the\nname label in the ",(0,a.jsx)(n.code,{children:"resource"})," block and record the old name inside a ",(0,a.jsx)(n.code,{children:"moved"})," block:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'resource "aws_instance" "b" {\n  
1count = 2\n\n  # (resource-type-specific configuration)\n}\n\nmoved {\n  from = aws_instance.a\n  to   = aws_instance.b\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["When creating the next plan for each configuration using this module, OpenTofu\ntreats any existing objects belonging to ",(0,a.jsx)(n.code,{children:"aws_instance.a"})," as if they had\nbeen created for ",(0,a.jsx)(n.code,{children:"aws_instance.b"}),": ",(0,a.jsx)(n.code,{children:"aws_instance.a[0]"})," will be treated as\n",(0,a.jsx)(n.code,{children:"aws_instance.b[0]"}),", and ",(0,a.jsx)(n.code,{children:"aws_instance.a[1]"})," as ",(0,a.jsx)(n.code,{children:"aws_instance.b[1]"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["New instances of the module, which ",(0,a.jsx)(n.em,{children:"never"})," had an\n",(0,a.jsx)(n.code,{children:"aws_instance.a"}),", will ignore the ",(0,a.jsx)(n.code,{children:"moved"})," block and propose to create\n",(0,a.jsx)(n.code,{children:"aws_instance.b[0]"})," and ",(0,a.jsx)(n.code,{children:"aws_instance.b[1]"})," as normal."]}),"\n",(0,a.jsxs)(n.p,{children:["Both of the addresses in this example referred to a resource as a whole, and\nso OpenTofu recognizes the move for all instances of the resource. That is,\nit covers both ",(0,a.jsx)(n.code,{children:"aws_instance.a[0]"})," and ",(0,a.jsx)(n.code,{children:"aws_instance.a[1]"})," without the need\nto identify each one separately."]}),"\n",(0,a.jsxs)(n.p,{children:["Each resource type has a separate schema and so objects of different types\nare not compatible. Therefore, although you can use ",(0,a.jsx)(n.code,{children:"moved"})," to change the name\nof a resource, you ",(0,a.jsx)(n.em,{children:"cannot"})," use ",(0,a.jsx)(n.code,{children:"moved"})," to change to a different resource type\nor to change a managed resource (a ",(0,a.jsx)(n.code,{children:"resource"})," block) into a data resource\n(a ",(0,a.jsx)(n.code,{children:"data"})," block)."]}),"\n",(0,a.jsxs)(n.h2,{id:"enabling-count-or-for_each-for-a-resource",children:["Enabling ",(0,a.jsx)(n.code,{children:"count"})," or ",(0,a.jsx)(n.code,{children:"for_each"})," For a Resource"]}),"\n",(0,a.jsx)(n.p,{children:"Consider this example module containing a single-instance resource:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'resource "aws_instance" "a" {\n  # (resource-type-specific configuration)\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Applying this configuration would lead to OpenTofu creating an object\nbound to the address ",(0,a.jsx)(n.code,{children:"aws_instance.a"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Later, you use ",(0,a.jsx)(n.a,{href:"/docs/v1.6/language/meta-arguments/for_each",children:(0,a.jsx)(n.code,{children:"for_each"})})," with this\nresource to systematically declare multiple instances. To preserve an object\nthat was previously associated with ",(0,a.jsx)(n.code,{children:"aws_instance.a"})," alone, you must add a\n",(0,a.jsx)(n.code,{children:"moved"})," block to specify which instance key the object will take in the new\nconfiguration:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'locals {\n  instances = tomap({\n    big = {\n      instance_type = "m3.large"\n    }\n    small = {\n      instance_type = "t2.medium"\n    }\n  })\n}\n\nresource "aws_instance" "a" {\n  for_each = local.instances\n\n  instance_type = each.value.instance_type\n  # (other resource-type-specific configuration)\n}\n\nmoved {\n  from = aws_instance.a\n  to   = aws_instance.a["small"]\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The above will keep OpenTofu from planning to destroy any existing object at\n",(0,a.jsx)(n.code,{children:"aws_instance.a"}),", treating that object instead as if it were originally\ncreated as ",(0,a.jsx)(n.code,{children:'aws_instance.a["small"]'}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["When at least one of the two addresses includes an instance key, like\n",(0,a.jsx)(n.code,{children:'["small"]'})," in the above example, OpenTofu understands both addresses as\nreferring to specific ",(0,a.jsx)(n.em,{children:"instances"})," of a resource rather than the resource as a\nwhole. That means you can use ",(0,a.jsx)(n.code,{children:"moved"})," to switch between keys and to add and\nremove keys as you switch between ",(0,a.jsx)(n.code,{children:"count"}),", ",(0,a.jsx)(n.code,{children:"for_each"}),", or neither."]}),"\n",(0,a.jsxs)(n.p,{children:["The following are some other examples of valid ",(0,a.jsx)(n.code,{children:"moved"})," blocks that record\nchanges to resource instance keys in a similar way:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'# Both old and new configuration used "for_each", but the\n# "small" element was renamed to "tiny".\nmoved {\n  from = aws_instance.b["small"]\n  to   = aws_instance.b["tiny"]\n}\n\n# The old configuration used "count" and the new configuration\n# uses "for_each", with the following mappings from\n# index to key:\nmoved {\n  from = aws_instance.c[0]\n  to   = aws_instance.c["small"]\n}\nmoved {\n  from = aws_instance.c[1]\n  to   = aws_instance.c["tiny"]\n}\n\n# The old configuration used "count", and the new configuration\n# uses neither "count" nor "for_each", and you want to keep\n# only the object at index 2.\nmoved {\n  from = aws_instance.d[2]\n  to   = aws_instance.d\n}\n'})}),"\n",(0,a.jsx)(n.admonition,{type:"note",children:(0,a.jsxs)(n.p,{children:["When you add ",(0,a.jsx)(n.code,{children:"count"})," to an existing resource that didn't use it,\nOpenTofu automatically proposes to move the original object to instance zero,\nunless you write an ",(0,a.jsx)(n.code,{children:"moved"})," block explicitly mentioning that resource.\nHowever, we recommend still writing out the corresponding ",(0,a.jsx)(n.code,{children:"moved"})," block\nexplicitly, to make the change clearer to future readers of the module."]})}),"\n",(0,a.jsx)(n.h2,{id:"renaming-a-module-call",children:"Renaming a Module Call"}),"\n",(0,a.jsx)(n.p,{children:"You can rename a call to a module in a similar way as renaming a resource.\nConsider the following original module version:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'module "a" {\n  source = "../modules/example"\n\n  # (module arguments)\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["When applying this configuration, OpenTofu would prefix the addresses for\nany resources declared in this module with the module path ",(0,a.jsx)(n.code,{children:"module.a"}),".\nFor example, a resource ",(0,a.jsx)(n.code,{children:"aws_instance.example"})," would have the full address\n",(0,a.jsx)(n.code,{children:"module.a.aws_instance.example"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["If you later choose a better name for this module call, then you can change the\nname label in the ",(0,a.jsx)(n.code,{children:"module"})," block and record the old name inside a ",(0,a.jsx)(n.code,{children:"moved"})," block:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'module "b" {\n  source = "../modules/example"\n\n  # (module arguments)\n}\n\nmoved {\n  from = module.a\n  to   = module.b\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["When creating the next plan for each configuration using this module, OpenTofu\nwill treat any existing object addresses beginning with ",(0,a.jsx)(n.code,{children:"module.a"})," as if\nthey had instead been created in ",(0,a.jsx)(n.code,{children:"module.b"}),". ",(0,a.jsx)(n.code,{children:"module.a.aws_instance.example"}),"\nwould be treated as ",(0,a.jsx)(n.code,{children:"module.b.aws_instance.example"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Both of the addresses in this example referred to a module call as a whole, and\nso OpenTofu recognizes the move for all instances of the call. If this\nmodule call used ",(0,a.jsx)(n.code,{children:"count"})," or ",(0,a.jsx)(n.code,{children:"for_each"})," then it would apply to all of the\ninstances, without the need to specify each one separately."]}),"\n",(0,a.jsxs)(n.h2,{id:"enabling-count-or-for_each-for-a-module-call",children:["Enabling ",(0,a.jsx)(n.code,{children:"count"})," or ",(0,a.jsx)(n.code,{children:"for_each"})," For a Module Call"]}),"\n",(0,a.jsx)(n.p,{children:"Consider this example of a single-instance module:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'module "a" {\n  source = "../modules/example"\n\n  # (module arguments)\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Applying this configuration would cause OpenTofu to create objects whose\naddresses begin with ",(0,a.jsx)(n.code,{children:"module.a"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["In later module versions, you may 
1need to use\n",(0,a.jsx)(n.a,{href:"/docs/v1.6/language/meta-arguments/count",children:(0,a.jsx)(n.code,{children:"count"})})," with this resource to systematically\ndeclare multiple instances. To preserve an object that was previously associated\nwith ",(0,a.jsx)(n.code,{children:"aws_instance.a"})," alone, you can add a ",(0,a.jsx)(n.code,{children:"moved"})," block to specify which\ninstance key that object will take in the new configuration:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'module "a" {\n  source = "../modules/example"\n  count  = 3\n\n  # (module arguments)\n}\n\nmoved {\n  from = module.a\n  to   = module.a[2]\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The configuration above directs OpenTofu to treat all objects in ",(0,a.jsx)(n.code,{children:"module.a"})," as\nif they were originally created in ",(0,a.jsx)(n.code,{children:"module.a[2]"}),". As a result, OpenTofu plans\nto create new objects only for ",(0,a.jsx)(n.code,{children:"module.a[0]"})," and ",(0,a.jsx)(n.code,{children:"module.a[1]"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["When at least one of the two addresses includes an instance key, like\n",(0,a.jsx)(n.code,{children:"[2]"})," in the above example, OpenTofu will understand both addresses as\nreferring to specific ",(0,a.jsx)(n.em,{children:"instances"})," of a module call rather than the module\ncall as a whole. That means you can use ",(0,a.jsx)(n.code,{children:"moved"})," to switch between keys and to\nadd and remove keys as you switch between ",(0,a.jsx)(n.code,{children:"count"}),", ",(0,a.jsx)(n.code,{children:"for_each"}),", or neither."]}),"\n",(0,a.jsxs)(n.p,{children:["For more examples of recording moves associated with instances, refer to\nthe similar section\n",(0,a.jsxs)(n.a,{href:"#enabling-count-or-for_each-for-a-resource",children:["Enabling ",(0,a.jsx)(n.code,{children:"count"})," and ",(0,a.jsx)(n.code,{children:"for_each"})," For a Resource"]}),"."]}),"\n",(0,a.jsx)(n.h1,{id:"splitting-one-module-into-multiple",children:"Splitting One Module into Multiple"}),"\n",(0,a.jsx)(n.p,{children:"As a module grows to support new requirements, it might eventually grow big\nenough to warrant splitting into two separate modules."}),"\n",(0,a.jsx)(n.p,{children:"Consider this example module:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'resource "aws_instance" "a" {\n  # (other resource-type-specific configuration)\n}\n\nresource "aws_instance" "b" {\n  # (other resource-type-specific configuration)\n}\n\nresource "aws_instance" "c" {\n  # (other resource-type-specific configuration)\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can split this into two modules as follows:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"aws_instance.a"}),' now belongs to module "x".']}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"aws_instance.b"}),' also belongs to module "x".']}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"aws_instance.c"}),' belongs module "y".']}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"To achieve this refactoring without replacing existing objects bound to the\nold resource addresses, you must:"}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:'Write module "x", copying over the two resources it should contain.'}),"\n",(0,a.jsx)(n.li,{children:'Write module "y", copying over the one resource it should contain.'}),"\n",(0,a.jsx)(n.li,{children:"Edit the original module to no longer include any of these resources, and\ninstead to contain only shim configuration to migrate existing users."}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:['The new modules "x" and "y" should contain only ',(0,a.jsx)(n.code,{children:"resource"})," blocks:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'# module "x"\n\nresource "aws_instance" "a" {\n  # (other resource-type-specific configuration)\n}\n\nresource "aws_instance" "b" {\n  # (other resource-type-specific configuration)\n}\n'})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'# module "y"\n\nresource "aws_instance" "c" {\n  # (other resource-type-specific configuration)\n}\n'})}),"\n",(0,a.jsx)(n.p,{children:"The original module, now only a shim for backward-compatibility, calls the\ntwo new modules and indicates that the resources moved into them:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:'module "x" {\n  source = "../modules/x"\n\n  # ...\n}
1\n\nmodule "y" {\n  source = "../modules/y"\n\n  # ...\n}\n\nmoved {\n  from = aws_instance.a\n  to   = module.x.aws_instance.a\n}\n\nmoved {\n  from = aws_instance.b\n  to   = module.x.aws_instance.b\n}\n\nmoved {\n  from = aws_instance.c\n  to   = module.y.aws_instance.c\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:['When an existing user of the original module upgrades to the new "shim"\nversion, OpenTofu notices these three ',(0,a.jsx)(n.code,{children:"moved"})," blocks and behaves\nas if the objects associated with the three old resource addresses were\noriginally created inside the two new modules."]}),"\n",(0,a.jsxs)(n.p,{children:["New users of this family of modules may use either the combined shim module\n",(0,a.jsx)(n.em,{children:"or"})," the two new modules separately. You may wish to communicate to your\nexisting users that the old module is now deprecated and so they should use\nthe two separate modules for any new needs."]}),"\n",(0,a.jsxs)(n.p,{children:['The multi-module refactoring situation is unusual in that it violates the\ntypical rule that a parent module sees its child module as a "closed box",\nunaware of exactly which resources are declared inside it. This compromise\nassumes that all three of these modules are maintained by the same people\nand distributed together in a single\n',(0,a.jsx)(n.a,{href:"/docs/v1.6/language/modules/sources#modules-in-package-sub-directories",children:"module package"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["OpenTofu resolves module references in ",(0,a.jsx)(n.code,{children:"moved"})," blocks relative to the module\ninstance they are defined in. For example, if the original module above were\nalready a child module named ",(0,a.jsx)(n.code,{children:"module.original"}),", the reference to\n",(0,a.jsx)(n.code,{children:"module.x.aws_instance.a"})," would resolve as\n",(0,a.jsx)(n.code,{children:"module.original.module.x.aws_instance.a"}),". A module may only make ",(0,a.jsx)(n.code,{children:"moved"}),"\nstatements about its own objects and objects of its child modules."]}),"\n",(0,a.jsxs)(n.p,{children:["If you need to refer to resources within a module that was called using\n",(0,a.jsx)(n.code,{children:"count"})," or ",(0,a.jsx)(n.code,{children:"for_each"})," meta-arguments, you must specify a specific instance\nkey to use in order to match with the new location of the resource\nconfiguration:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:"moved {\n  from = aws_instance.example\n  to   = module.new[2].aws_instance.example\n}\n"})}),"\n",(0,a.jsxs)(n.h2,{id:"removing-moved-blocks",children:["Removing ",(0,a.jsx)(n.code,{children:"moved"})," Blocks"]}),"\n",(0,a.jsxs)(n.p,{children:["Over time, a long-lasting module may accumulate many ",(0,a.jsx)(n.code,{children:"moved"})," blocks."]}),"\n",(0,a.jsxs)(n.p,{children:["Removing a ",(0,a.jsx)(n.code,{children:"moved"})," block is a generally breaking change because any configurations that refer to the old address will plan to delete that existing object instead of move it. We strongly recommend that you retain all historical ",(0,a.jsx)(n.code,{children:"moved"})," blocks from earlier versions of your modules to preserve the upgrade path for users of any previous version."]}),"\n",(0,a.jsxs)(n.p,{children:["If you do decide to remove ",(0,a.jsx)(n.code,{children:"moved"})," blocks, proceed with caution. It can be safe to remove ",(0,a.jsx)(n.code,{children:"moved"})," blocks when you are maintaining private modules within an organization and you are certain that all users have successfully run ",(0,a.jsx)(n.code,{children:"tofu apply"})," with your new module version."]}),"\n",(0,a.jsxs)(n.p,{children:["If you need to rename or move the same object twice, we recommend documenting the full history\nusing ",(0,a.jsx)(n.em,{children:"chained"})," ",(0,a.jsx)(n.code,{children:"moved"})," blocks, where the new block refers to the existing block:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-hcl",children:"moved {\n  from = aws_instance.a\n  to   = aws_instance.b\n}\n\nmoved {\n  from = aws_instance.b\n  to   = aws_instance.c\n}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Recording a sequence of moves in this way allows for successful upgrades for\nboth configurations with objects at ",(0,a.jsx)(n.code,{children:"aws_instance.a"})," ",(0,a.jsx)(n.em,{children:"and"})," configurations with\nobjects at ",(0,a.jsx)(n.code,{children:"aws_instance.b"}),". In both cases, OpenTofu treats the existing\nobject as if it had been originally created as ",(0,a.jsx)(n.code,{children:"aws_instance.c"}),"."]})]})}function h(e={}){let{wrapper:n}={...(0,c.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},28453(e,n,o){o.d(n,{R:()=>i,x:()=>r});var s=o(96540);let a={},c=s.createContext(a);function i(e){let n=s.useContext(c);return s.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(c.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.