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  }