github.com/opentofu/opentofu@v1.7.1/internal/addrs/remove_endpoint.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package addrs 7 8 import ( 9 "github.com/hashicorp/hcl/v2" 10 "github.com/opentofu/opentofu/internal/tfdiags" 11 ) 12 13 // RemoveEndpoint is to ConfigRemovable what Target is to Targetable: 14 // a wrapping struct that captures the result of decoding an HCL 15 // traversal representing a relative path from the current module to 16 // a removable object. It is very similar to MoveEndpoint. 17 // 18 // Its purpose is to represent the "from" address in a "removed" block 19 // in the configuration. 20 // 21 // To obtain a full address from a RemoveEndpoint we need to combine it 22 // with any ancestor modules in the configuration 23 type RemoveEndpoint struct { 24 // SourceRange is the location of the physical endpoint address 25 // in configuration, if this RemoveEndpoint was decoded from a 26 // configuration expression. 27 SourceRange tfdiags.SourceRange 28 29 // the representation of our relative address as a ConfigRemovable 30 RelSubject ConfigRemovable 31 } 32 33 // ParseRemoveEndpoint attempts to interpret the given traversal as a 34 // "remove endpoint" address, which is a relative path from the module containing 35 // the traversal to a removable object in either the same module or in some 36 // child module. 37 // 38 // This deals only with the syntactic element of a remove endpoint expression 39 // in configuration. Before the result will be useful you'll need to combine 40 // it with the address of the module where it was declared in order to get 41 // an absolute address relative to the root module. 42 func ParseRemoveEndpoint(traversal hcl.Traversal) (*RemoveEndpoint, tfdiags.Diagnostics) { 43 path, remain, diags := parseModulePrefix(traversal) 44 if diags.HasErrors() { 45 return nil, diags 46 } 47 48 rng := tfdiags.SourceRangeFromHCL(traversal.SourceRange()) 49 50 if len(remain) == 0 { 51 return &RemoveEndpoint{ 52 RelSubject: path, 53 SourceRange: rng, 54 }, diags 55 } 56 57 riAddr, moreDiags := parseResourceUnderModule(path, remain) 58 diags = diags.Append(moreDiags) 59 if diags.HasErrors() { 60 return nil, diags 61 } 62 63 if riAddr.Resource.Mode == DataResourceMode { 64 diags = diags.Append(&hcl.Diagnostic{ 65 Severity: hcl.DiagError, 66 Summary: "Data source address is not allowed", 67 Detail: "Data sources cannot be destroyed, and therefore, 'removed' blocks are not allowed to target them. To remove data sources from the state, you should remove the data source block from the configuration.", 68 Subject: traversal.SourceRange().Ptr(), 69 }) 70 71 return nil, diags 72 } 73 74 return &RemoveEndpoint{ 75 RelSubject: riAddr, 76 SourceRange: rng, 77 }, diags 78 }