Terraform Advanced Patcher, aka.TAP,is a tool to patchTerraformfile.
This tool is maintained bySeal.
In some cases, consuming nativeTerraform Override can complete some additional expansion, like overriding a nested block or changing a predefined attribute, but the capabilities are limited. For example, it needs accurate block header to patch, and it's impossible to conditionally make changes to nested blocks or attributes.
TAPis designed to satisfy the above features.
As we all know, the HCL used byTerraform supports JSON syntax.Therefore,TAPcan be implemented using JSON patching.
The patching mode ofTerraform Overridelooks likeJSON Merge Patch, RFC 7386,butTAPis working asJSON Patch, RFC 6902.
For a comparison of JSON patch and JSON merge patch, seeJSON Patch and JSON Merge Patch.
AlthoughTAPandTerraform Overridepath in different ways, they have one thing in same, that is, top-level blocks cannot be deleted. The core reason is that top-level blocks can configureMeta-Argumentor participate in the configuration ofMeta-Argument.Directly deleting a top-level block will cause many problems.
TAPis not a complete JSON patch
forTerraform JSON Configuration SyntaxThe original
JSON path needs its operation to have exactly one "path" member, which values with
aJSON Pointer,butTAPimplements limited
operations:add
,remove
,andreplace
,and also introduces a new operation:set
.
#tap.hcl
tap{
path_syntax="json_pointer"
}
resource"kubernetes_deployment"{
type_alias=["kubernetes_deployment_v1"]
add{
path="/metadata/0/labels/new-label"
value="new-label-value"
}
remove{
path="/metadata/0/labels/old-label"
}
replace{
path="/spec/0/template/0/spec/0/replicas"
value="2"
}
set{
path="/spec/0/selector/0"
value {
match_labels=local.selectors
}
}
}
TAPrecognizes the path syntax according to the
path_syntax
attribute in thetap
block, in which the default value isjson_pointer
.We are going to support more path syntax in the future.
TAP,at present, only supports patchingresource
anddata
blocks, and filters out the target blocks
bytype_alias
orname_match
attributes.
#tap.hcl
tap{
path_syntax="json_pointer"
}
resource"kubernetes_deployment"{
type_alias=["kubernetes_deployment_v1"]
name_match=["nginx"]
#... operations
}
data"kubernetes_config_map"{
type_alias=["kubernetes_config_map_v1"]
name_match=["nginx"]
#... operations
}
TAPalso allows ignoring error if patching fails, and it can be configured by thecontinue_on_error
attribute in
thetap
block.
#tap.hcl
tap{
continue_on_error=true#global
path_syntax="json_pointer"
}
resource"kubernetes_deployment"{
continue_on_error=false#local
type_alias=["kubernetes_deployment_v1"]
#... operations
}
TAPis a wrapper toTerraformorOpenTofu,you can simplify
aliasTAPastf
,and use it as a drop-in replacement for Terraform or OpenTofu.
TAPis not a fork of Terraform or OpenTofu, so you still need to install the CLI ofTerraform orOpenTofu at first.
$ go install github.com/seal-io/tap/cmd/tap@latest
$ mv"${GOPATH}"/bin/tap"${GOPATH}"/bin/tf
$ tf --version
Put thetap.hcl
file in the same directory as themain.tf
file, and then executetf plan
ortf apply
to see the
effect.