// Copyright IBM Corp. 2014, 2026 // SPDX-License-Identifier: BUSL-1.1 syntax = "proto3"; package tfplan; // For Terraform's own parsing, the proto stub types go into an internal Go // package. The public API is in github.com/hashicorp/terraform/internal/plans/planfile . option go_package = "github.com/hashicorp/terraform/internal/plans/planproto"; // Plan is the root message type for the tfplan file message Plan { // Version is incremented whenever there is a breaking change to // the serialization format. Programs reading serialized plans should // verify that version is set to the expected value and abort processing // if not. A breaking change is any change that may cause an older // consumer to interpret the structure incorrectly. This number will // not be incremented if an existing consumer can either safely ignore // changes to the format or if an existing consumer would fail to process // the file for another message- or field-specific reason. uint64 version = 1; // The mode that was active when this plan was created. // // This is saved only for UI purposes, so that Terraform can tailor its // rendering of the plan depending on the mode. This must never be used to // make decisions in Terraform Core during the applying of a plan. Mode ui_mode = 17; // Applyable is true for any plan where it makes sense to ask an operator // to approve it and then ask Terraform to apply it. // // The other fields provide more context about why a non-applyable plan // is not applyable, but this field is here so that if new situations // arise in future then old callers can at least still make the right // decision about whether to show the approval prompt, even if they don't // know yet why a particular plan isn't applyable and have to just use // a generic error message. bool applyable = 25; // Complete is true for a plan that includes a planned action for every // resource input object that was present across the desired state and // prior state, even if the planned action is "no-op". // // Conversely, if this field is false then the plan deals with only a // subset of those objects. The reason for that should always be // determinable based on other fields in this message, but this flag // is here to ensure that if new situations arise in future then old // callers can at least still show a generic message about the plan // being incomplete, even if they don't know yet how to explain the // reason to the operator. bool complete = 26; // Errored is true for any plan whose creation was interrupted by an // error. A plan with this flag set cannot be applied // (i.e. applyable = false), and the changes it proposes are likely to be // incomplete. bool errored = 20; // The variables that were set when creating the plan. Each value is // a msgpack serialization of an HCL value. map variables = 2; // Variables whose values must be provided during the apply phase. repeated string apply_time_variables = 28; // An unordered set of proposed changes to resources throughout the // configuration, including any nested modules. Use the address of // each resource to determine which module it belongs to. repeated ResourceInstanceChange resource_changes = 3; // An unordered set of detected drift: changes made to resources outside of // Terraform, computed by comparing the previous run's state to the state // after refresh. repeated ResourceInstanceChange resource_drift = 18; // An unordered set of deferred changes. These are changes that will be // applied in a subsequent plan, but were deferred in this plan for some // reason. Generally, if complete is set to false there should be entries // in this list. repeated DeferredResourceInstanceChange deferred_changes = 27; // An unordered set of deferred action invocations. These are action invocations that will be // applied in a subsequent plan, but were deferred in this plan for some // reason. Generally, if complete is set to false there should be entries // in this list. repeated DeferredActionInvocation deferred_action_invocations = 31; // An unordered set of proposed changes to outputs in the root module // of the configuration. This set also includes "no action" changes for // outputs that are not changing, as context for detecting inconsistencies // at apply time. repeated OutputChange output_changes = 4; // An unordered set of check results for the entire configuration. // // Each element represents a single static configuration object that has // checks, and each of those may have zero or more dynamic objects that // the checks were applied to nested within. repeated CheckResults check_results = 19; // An unordered set of proposed action invocations. repeated ActionInvocationInstance action_invocations = 30; // An unordered set of target addresses to include when applying. If no // target addresses are present, the plan applies to the whole // configuration. repeated string target_addrs = 5; // An unordered set of action addresses that must be invoked when applying. // If no actions are specified then only resource-triggered actions should // be executed. repeated string action_target_addrs = 32; // An unordered set of force-replace addresses to include when applying. // This must match the set of addresses that was used when creating the // plan, or else applying the plan will fail when it reaches a different // conclusion about what action a particular resource instance needs. repeated string force_replace_addrs = 16; // The version string for the Terraform binary that created this plan. string terraform_version = 14; // Backend is a description of the backend configuration and other related // settings at the time the plan was created. Backend backend = 13; // StateStore is a description of the state_store configuration and other related // settings at the time the plan was created. StateStore state_store = 29; message resource_attr { string resource = 1; Path attr= 2; }; // RelevantAttributes lists individual resource attributes from // ResourceDrift which may have contributed to the plan changes. repeated resource_attr relevant_attributes = 15; // timestamp is the record of truth for when the plan happened. string timestamp = 21; repeated FunctionCallHash function_results = 22; } // Mode describes the planning mode that created the plan. enum Mode { NORMAL = 0; DESTROY = 1; REFRESH_ONLY = 2; } // Backend is a description of backend configuration and other related settings. message Backend { string type = 1; DynamicValue config = 2; string workspace = 3; } // StateStore is a description of state_store configuration and other related settings. message StateStore { string type = 1; DynamicValue config = 2; string workspace = 3; Provider provider = 4; } message Provider { string source = 1; string version = 2; DynamicValue config = 3; } // Action describes the type of action planned for an object. // Not all action values are valid for all object types. enum Action { NOOP = 0; CREATE = 1; READ = 2; UPDATE = 3; DELETE = 5; DELETE_THEN_CREATE = 6; CREATE_THEN_DELETE = 7; FORGET = 8; CREATE_THEN_FORGET = 9; } // Change represents a change made to some object, transforming it from an old // state to a new state. message Change { // Not all action values are valid for all object types. Consult // the documentation for any message that embeds Change. Action action = 1; // msgpack-encoded HCL values involved in the change. // - For update and replace, two values are provided that give the old and new values, // respectively. // - For create, one value is provided that gives the new value to be created // - For delete, one value is provided that describes the value being deleted // - For read, two values are provided that give the prior value for this object // (or null, if no prior value exists) and the value that was or will be read, // respectively. // - For no-op, one value is provided that is left unmodified by this non-change. repeated DynamicValue values = 2; // An unordered set of paths into the old value which are marked as // sensitive. Values at these paths should be obscured in human-readable // output. This set is always empty for create. repeated Path before_sensitive_paths = 3; // An unordered set of paths into the new value which are marked as // sensitive. Values at these paths should be obscured in human-readable // output. This set is always empty for delete. repeated Path after_sensitive_paths = 4; // Importing, if true, specifies that the resource is being imported as part // of the change. Importing importing = 5; // GeneratedConfig contains any configuration that was generated as part of // the change, as an HCL string. string generated_config = 6; // The resource identity before the plan operation DynamicValue before_identity = 7; // The resource identity after the plan operation DynamicValue after_identity = 8; } // ResourceInstanceActionReason sometimes provides some additional user-facing // context for why a particular action was chosen for a resource instance. // This is for user feedback only and never used to drive behavior during the // subsequent apply step. enum ResourceInstanceActionReason { NONE = 0; REPLACE_BECAUSE_TAINTED = 1; REPLACE_BY_REQUEST = 2; REPLACE_BECAUSE_CANNOT_UPDATE = 3; DELETE_BECAUSE_NO_RESOURCE_CONFIG = 4; DELETE_BECAUSE_WRONG_REPETITION = 5; DELETE_BECAUSE_COUNT_INDEX = 6; DELETE_BECAUSE_EACH_KEY = 7; DELETE_BECAUSE_NO_MODULE = 8; REPLACE_BY_TRIGGERS = 9; READ_BECAUSE_CONFIG_UNKNOWN = 10; READ_BECAUSE_DEPENDENCY_PENDING = 11; READ_BECAUSE_CHECK_NESTED = 13; DELETE_BECAUSE_NO_MOVE_TARGET = 12; } message ResourceInstanceChange { // addr is a string representation of the resource instance address that // this change will apply to. string addr = 13; // prev_run_addr is a string representation of the address at which // this resource instance was tracked during the previous apply operation. // // This is populated only if it would be different from addr due to // Terraform having reacted to refactoring annotations in the configuration. // If empty, the previous run address is the same as the current address. string prev_run_addr = 14; // NOTE: Earlier versions of this format had fields 1 through 6 describing // various individual parts of "addr". We're now using our standard compact // string representation to capture the same information. We don't support // preserving plan files from one Terraform version to the next, so we // no longer declare nor accept those fields. // deposed_key, if set, indicates that this change applies to a deposed // object for the indicated instance with the given deposed key. If not // set, the change applies to the instance's current object. string deposed_key = 7; // provider is the address of the provider configuration that this change // was planned with, and thus the configuration that must be used to // apply it. string provider = 8; // Description of the proposed change. May use "create", "read", "update", // "replace", "delete" and "no-op" actions. Change change = 9; // raw blob value provided by the provider as additional context for the // change. Must be considered an opaque value for any consumer other than // the provider that generated it, and will be returned verbatim to the // provider during the subsequent apply operation. bytes private = 10; // An unordered set of paths that prompted the change action to be // "replace" rather than "update". Empty for any action other than // "replace". repeated Path required_replace = 11; // Optional extra user-oriented context for why change.Action was chosen. // This is for user feedback only and never used to drive behavior during // apply. ResourceInstanceActionReason action_reason = 12; } // DeferredResourceInstanceChange represents a resource instance change that // was deferred for some reason. // // It contains the original change that was deferred, along with the reason // why it was deferred. message DeferredResourceInstanceChange { // The reason why the change was deferred. Deferred deferred = 1; // The original change that was deferred. ResourceInstanceChange change = 2; } // DeferredActionInvocation represents an action invocation that // was deferred for some reason. // It contains the original action invocation that was deferred, along with the reason // why it was deferred. message DeferredActionInvocation { // The reason why the action invocation was deferred. Deferred deferred = 1; // The original action invocation that was deferred. ActionInvocationInstance action_invocation = 2; } message OutputChange { // Name of the output as defined in the root module. string name = 1; // Description of the proposed change. May use "no-op", "create", // "update" and "delete" actions. Change change = 2; // Sensitive, if true, indicates that one or more of the values given // in "change" is sensitive and should not be shown directly in any // rendered plan. bool sensitive = 3; } message CheckResults { // Status describes the status of a particular checkable object at the // completion of the plan. enum Status { UNKNOWN = 0; PASS = 1; FAIL = 2; ERROR = 3; } enum ObjectKind { UNSPECIFIED = 0; RESOURCE = 1; OUTPUT_VALUE = 2; CHECK = 3; INPUT_VARIABLE = 4; } message ObjectResult { string object_addr = 1; Status status = 2; repeated string failure_messages = 3; } ObjectKind kind = 1; // Address of the configuration object that declared the checks. string config_addr = 2; // The aggregate status of the entire configuration object, based on // the statuses of its zero or more checkable objects. Status status = 3; // The results for individual objects that were declared by the // configuration object named in config_addr. repeated ObjectResult objects = 4; } // FunctionCallHash stores a record of a hashed function call and // result. This is used internally to ensure that providers return consistent // values between plan and apply given the same arguments. message FunctionCallHash { bytes key = 1; bytes result = 2; } // DynamicValue represents a value whose type is not decided until runtime, // often based on schema information obtained from a plugin. // // At present dynamic values are always encoded as msgpack, with extension // id 0 used to represent the special "unknown" value indicating results // that won't be known until after apply. // // In future other serialization formats may be used, possibly with a // transitional period of including both as separate attributes of this type. // Consumers must ignore attributes they don't support and fail if no supported // attribute is present. The top-level format version will not be incremented // for changes to the set of dynamic serialization formats. message DynamicValue { bytes msgpack = 1; } // Path represents a set of steps to traverse into a data structure. It is // used to refer to a sub-structure within a dynamic data structure presented // separately. message Path { message Step { oneof selector { // Set "attribute_name" to represent looking up an attribute // in the current object value. string attribute_name = 1; // Set "element_key" to represent looking up an element in // an indexable collection type. DynamicValue element_key = 2; } } repeated Step steps = 1; } // Importing contains the embedded metadata about the import operation if this // change describes it. message Importing { // The original ID of the resource. string id = 1; // unknown is true if the original ID of the resource is unknown. bool unknown = 2; // Identity can be used to import instead of id DynamicValue identity = 3; } // DeferredReason describes the reason why a resource instance change was // deferred. enum DeferredReason { INVALID = 0; INSTANCE_COUNT_UNKNOWN = 1; RESOURCE_CONFIG_UNKNOWN = 2; PROVIDER_CONFIG_UNKNOWN = 3; ABSENT_PREREQ = 4; DEFERRED_PREREQ = 5; } // Deferred contains all the metadata about a the deferral of a resource // instance change. message Deferred { DeferredReason reason = 1; } // ActionInvocation describes the reason an action was triggered enum ActionTriggerEvent { INVALID_EVENT = 0; BEFORE_CERATE = 1; AFTER_CREATE = 2; BEFORE_UPDATE = 3; AFTER_UPDATE = 4; BEFORE_DESTROY = 5; AFTER_DESTROY = 6; INVOKE = 7; } // ActionInvocationInstance contains a planned action invocation and any embedded ResourceInstanceActionChanges message ActionInvocationInstance { // addr is a string representation of the action invocation instance address of this change string addr = 1; // provider is the address of the provider configuration that this change // was planned with, and thus the configuration that must be used to // apply it. string provider = 2; DynamicValue config_value = 4; // An unordered set of paths into config_value which are marked as // sensitive. Values at these paths should be obscured in human-readable // output. repeated Path sensitive_config_paths = 5; oneof action_trigger { ResourceActionTrigger resource_action_trigger = 6; InvokeActionTrigger invoke_action_trigger = 7; } } // ResourceActionTrigger contains details on the conditions that led to the // triggering of an action. message ResourceActionTrigger { string triggering_resource_addr = 1; ActionTriggerEvent trigger_event = 2; int64 action_trigger_block_index = 3; int64 actions_list_index = 4; } // InvokeActionTrigger indicates the action was triggered by the invoke command // on the CLI. message InvokeActionTrigger {} message ResourceInstanceActionChange { // addr is a string representation of the resource instance address that // this change will apply to. string addr = 1; // deposed_key, if set, indicates that this change applies to a deposed // object for the indicated instance with the given deposed key. If not // set, the change applies to the instance's current object. string deposed_key = 2; // Description of the proposed change. // May use "update", "replace", "delete" and "no-op" actions. Change change = 3; }