mirror of
https://github.com/hashicorp/terraform.git
synced 2026-02-03 20:50:59 -05:00
410 lines
18 KiB
Protocol Buffer
410 lines
18 KiB
Protocol Buffer
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
syntax = "proto3";
|
|
package tfstackdata1;
|
|
|
|
import "planfile.proto"; // tfplan, from internal/plans/planproto
|
|
import "google/protobuf/any.proto";
|
|
|
|
// These definitions describe the PRIVATE raw format that we use to persist
|
|
// stack and plan information for stacks between operations.
|
|
//
|
|
// Nothing outside of this codebase should attempt to produce or consume
|
|
// these formats. They are subject to change at any time.
|
|
|
|
///////////// PLAN SEQUENCE MESSAGES
|
|
//
|
|
// A "stack plan" consists of a sequence of messages emitted gradually from
|
|
// the streaming Stacks.PlanStackChanges RPC in the Terraform Core RPC API.
|
|
//
|
|
// From the perspective of that protocol the objects in the sequence are
|
|
// opaque and to be preserved byte-for-byte without any external interpretation,
|
|
// in the same order they were emitted from Terraform Core.
|
|
//
|
|
// Internally, we decode each one based on the type field of google.protobuf.Any,
|
|
// treating each one as some kind of mutation of our in-memory plan data
|
|
// structure.
|
|
//
|
|
// These message types only cover the data that Terraform needs to apply the
|
|
// plan, and so don't cover any information that Terraform Core might emit
|
|
// only for the caller's benefit.
|
|
//////////////
|
|
|
|
// Appears early in a raw plan sequence to capture some metadata that we need
|
|
// to process subsequent messages, or to abort if we're being asked to decode
|
|
// a plan created by a different version of Terraform.
|
|
message PlanHeader {
|
|
// The canonical version string for the version of Terraform that created
|
|
// the plan sequence that this message belongs to.
|
|
//
|
|
// The raw plan sequence loader will fail if it finds a message of this
|
|
// type with a version string that disagrees with the version of Terraform
|
|
// decoding the message, because we always expect plans to be applied by
|
|
// the same version of Terraform that created them.
|
|
string terraform_version = 1;
|
|
}
|
|
|
|
// Captures one element from the raw prior state that was provided when
|
|
// creating the plan. A valid plan includes a copy of its entire prior state
|
|
// represented as zero or more messages of this type, which we then interpret
|
|
// as a map from key to raw during load.
|
|
message PlanPriorStateElem {
|
|
string key = 1;
|
|
google.protobuf.Any raw = 2;
|
|
}
|
|
|
|
// Confirms whether the overall plan whose raw plan sequence includes this
|
|
// message is complete enough and valid enough to be applied.
|
|
//
|
|
// If a the sequence of raw plan messages includes multiple messages of this
|
|
// type then the one with the latest position in the list "wins" during
|
|
// decoding of the overall sequence, although in practice there isn't yet
|
|
// any clear reason to include more than one instance of this message type in a
|
|
// plan.
|
|
message PlanApplyable {
|
|
bool applyable = 1;
|
|
}
|
|
|
|
// Records the plan timestamp to be used for all components and the stacks language.
|
|
message PlanTimestamp {
|
|
string plan_timestamp = 1;
|
|
}
|
|
|
|
// Records the value of one of the main stack's input values during planning.
|
|
//
|
|
// These values get fixed during the plan phase so that we can ensure that we
|
|
// use identical values when subsequently applying the plan.
|
|
message PlanRootInputValue {
|
|
string name = 1;
|
|
DynamicValue value = 2;
|
|
bool required_on_apply = 3;
|
|
}
|
|
|
|
// Records that a root input variable should be deleted by the apply operation.
|
|
message DeletedRootInputVariable {
|
|
string name = 1;
|
|
}
|
|
|
|
// Records that a root output should be deleted by the apply operation.
|
|
message DeletedRootOutputValue {
|
|
string name = 1;
|
|
}
|
|
|
|
// Records that a component should just be deleted from the state.
|
|
message DeletedComponent {
|
|
string component_instance_addr = 1;
|
|
}
|
|
|
|
// FunctionResults stores a record of the results of provider functions
|
|
// that were called during the planning phase. This is used to ensure that the
|
|
// same results are returned during the apply phase.
|
|
message FunctionResults {
|
|
repeated tfplan.FunctionCallHash function_results = 1;
|
|
}
|
|
|
|
// Represents the existence of a particular component instance, and so must
|
|
// always appear before any messages representing objects that belong to that
|
|
// component instance.
|
|
//
|
|
// This message type exists to avoid the ambiguity between a component instance
|
|
// existing with zero resource instances inside vs. a component instance
|
|
// not existing at all.
|
|
message PlanComponentInstance {
|
|
string component_instance_addr = 1;
|
|
|
|
// plan_timestamp records the time when the plan for this component
|
|
// instance was created, exclusively for making sure that the
|
|
// "plantimestamp" function can return the same value during the apply
|
|
// phase. It must not be used for any other purpose.
|
|
string plan_timestamp = 2;
|
|
|
|
// Captures an approximation of the input values for this component with
|
|
// as much detail as we knew during the planning phase. This might
|
|
// contain unknown values as placeholders for values that won't be
|
|
// determined until the apply phase, so this isn't usable directly as
|
|
// the input to subsequently applying the component plan but the final
|
|
// input values should be a valid concretization of what's described here.
|
|
map<string, DynamicValue> planned_input_values = 3;
|
|
|
|
// The action planned for the component as a whole.
|
|
//
|
|
// This does not directly incorporate actions planned for resource
|
|
// instances within this component instance, but does capture a sense
|
|
// of the overall action being taken for this particular component
|
|
// instance.
|
|
//
|
|
// The currently-possible values are:
|
|
// - CREATE and UPDATE both describe applying a "normal" plan, where
|
|
// CREATE additionally represents that the component instance
|
|
// did not previously exist.
|
|
// - READ describes a refresh-only plan. This is currently possible only
|
|
// if the overall stack plan is refresh-only.
|
|
// - DELETE describes applying a destroy plan, with the intent of
|
|
// deleting all remote objects currently bound to resource instances
|
|
// in this component instance.
|
|
//
|
|
// The value recorded here is used to achieve a few variations needed in
|
|
// the apply phase.
|
|
tfplan.Action planned_action = 4;
|
|
|
|
// The mode that was used to plan this component.
|
|
//
|
|
// This is used to determine the behavior of the apply phase for this
|
|
// component instance.
|
|
//
|
|
// Ideally, we wouldn't need to include this at all as the plan should
|
|
// contain everything we need without a general mode. However, this is
|
|
// not currently the case. See context_apply.go:332 for more details.
|
|
// TODO: Remove this once walkDestroy has been properly audited.
|
|
tfplan.Mode mode = 10;
|
|
|
|
// The appliability flag decided by the modules runtime for this component's
|
|
// plan. See the docs for plans.Plan.Applyable for details on what this
|
|
// represents. (It's here largely just so that we can repopulate it
|
|
// faithfully when we rebuild a plans.Plan object at apply time.)
|
|
bool plan_applyable = 7;
|
|
|
|
// The completion flag decided by the modules runtime for this component's
|
|
// plan. See the docs for plans.Plan.Complete for details on what this
|
|
// represents. (It's here largely just so that we can repopulate it
|
|
// faithfully when we rebuild a plans.Plan object at apply time.)
|
|
bool plan_complete = 8;
|
|
|
|
// A list of absolute component addresses that this component
|
|
// instance depends on according to the configuration the plan was
|
|
// created from. (These are components rather than component instances
|
|
// because the stacks language evaluation model uses components as the
|
|
// most specific granularity for dependency resolution.)
|
|
//
|
|
// Applying this component instance's plan must wait until any
|
|
// CREATE or UPDATE plans for any of the listed component instances have
|
|
// completed successfully. Additionally, if any of the component instances
|
|
// listed here have DELETE plans then this component instance must also
|
|
// have a DELETE plan and the upstream DELETE must wait until this one
|
|
// has completed.
|
|
//
|
|
// A component instance plan that is not DELETE cannot depend on another
|
|
// component instance that is not also DELETE, since that would imply that
|
|
// this component instance's configuration refers to a component that isn't
|
|
// declared, which should therefore have failed validation.
|
|
repeated string depends_on_component_addrs = 5;
|
|
|
|
// Captures an approximation of the output values for this component with
|
|
// as much detail as we knew during the planning phase.
|
|
//
|
|
// For any planned action other than DELETE this might contain unknown
|
|
// values as placeholders for values that won't be determined until the
|
|
// apply phase
|
|
//
|
|
// For a DELETE plan the values should always be known because they are
|
|
// based on the prior state for the component, before it has been destroyed.
|
|
// The apply phase should use these values to build the representation of
|
|
// the component instance as an expression, because for DELETE any
|
|
// dependent objects must also be pending DELETE and their delete must
|
|
// happen before this instance is destroyed.
|
|
map<string, DynamicValue> planned_output_values = 6;
|
|
|
|
// A list of check results for this component instance, as produced by
|
|
// the modules runtime during the planning phase. The apply expects to
|
|
// update check results which were unknown during planning to reflect
|
|
// the actual results from the apply phase.
|
|
repeated tfplan.CheckResults planned_check_results = 9;
|
|
|
|
// The set of provider function results that were produced during the
|
|
// planning phase for this component instance. These results are used
|
|
// to ensure that the same results are returned during the apply phase.
|
|
repeated tfplan.FunctionCallHash function_results = 11;
|
|
}
|
|
|
|
// Represents a planned change to a particular resource instance within a
|
|
// particular component instance.
|
|
message PlanResourceInstanceChangePlanned {
|
|
// The same string must previously have been announced with a
|
|
// PlanComponentInstance message, or the overall plan sequence is invalid.
|
|
string component_instance_addr = 1;
|
|
string resource_instance_addr = 4;
|
|
string deposed_key = 5;
|
|
|
|
// The address of the provider configuration that planned this change,
|
|
// or that produced the prior state for messages where "change" is
|
|
// unpopulated. This is a module-centric view relative to the root module
|
|
// of the component identified in component_instance_addr.
|
|
string provider_config_addr = 6;
|
|
|
|
// Description of the planned change in the standard "tfplan" (planproto)
|
|
// format.
|
|
tfplan.ResourceInstanceChange change = 2;
|
|
|
|
// A snapshot of the "prior state", which is the result of upgrading and
|
|
// refreshing the previous run's state.
|
|
//
|
|
// The very first action on applying this plan should be to update the
|
|
// raw state for the resource instance to match this value, since
|
|
// the main apply phase for each component instance assumes that the
|
|
// prior state has already been updated to match the "old" value from
|
|
// the "change" message.
|
|
StateResourceInstanceObjectV1 prior_state = 3;
|
|
}
|
|
|
|
// Represents a deferred change to a particular resource instance within a
|
|
// particular component instance.
|
|
message PlanDeferredResourceInstanceChange {
|
|
tfplan.Deferred deferred = 1;
|
|
PlanResourceInstanceChangePlanned change = 2;
|
|
}
|
|
|
|
message PlanActionInvocationPlanned {
|
|
// The same string must previously have been announced with a
|
|
// PlanComponentInstance message, or the overall plan sequence is invalid.
|
|
string component_instance_addr = 1;
|
|
string action_invocation_addr = 3;
|
|
|
|
// The address of the provider configuration that planned this change,
|
|
// or that produced the prior state for messages where "change" is
|
|
// unpopulated. This is a module-centric view relative to the root module
|
|
// of the component identified in component_instance_addr.
|
|
string provider_config_addr = 4;
|
|
|
|
tfplan.ActionInvocationInstance invocation = 2;
|
|
}
|
|
|
|
// Represents a deferred change to a particular action invocation within a
|
|
// particular component instance.
|
|
message PlanDeferredActionInvocation {
|
|
tfplan.Deferred deferred = 1;
|
|
PlanActionInvocationPlanned invocation = 2;
|
|
}
|
|
|
|
// Represents that we need to emit "delete" requests for one or more raw
|
|
// state and/or state description objects during the apply phase.
|
|
//
|
|
// This situation arises if the previous state (given as input to the apply
|
|
// phase) contains keys that are of a type unrecognized by the current
|
|
// version of Terraform and that are marked as "discard if unrecognized",
|
|
// suggesting that their content is likely to become somehow invalid if
|
|
// other parts of the state were to get updated.
|
|
message PlanDiscardStateMapKeys {
|
|
// A set of keys to delete from the "raw state".
|
|
repeated string raw_state_keys = 1;
|
|
|
|
// A set of keys to delete from the "state description".
|
|
repeated string description_keys = 2;
|
|
}
|
|
|
|
///////////// STATE MAP MESSAGES
|
|
//
|
|
// A "stack state snapshot" is a mapping from arbitrary keys to messages
|
|
// emitted gradually from the streaming Stacks.ApplyStackChanges RPC in the
|
|
// Terraform Core RPC API.
|
|
//
|
|
// From the perspective of that protocol the keys and values in the map are
|
|
// opaque and to be preserved verbatim without any external interpretation,
|
|
// overwriting any previous value that had the same key.
|
|
//
|
|
// Internally, we decode each one based on the type field of google.protobuf.Any,
|
|
// treating each one as some kind of mutation of our in-memory plan data
|
|
// structure.
|
|
//
|
|
// These message types only cover the data that Terraform needs to produce
|
|
// a future plan based on this snapshot, and don't cover any information that
|
|
// Terraform Core might emit only for the caller's benefit.
|
|
//
|
|
// Because state messages survive from one run to the next, all top-level
|
|
// messages used for state snapshots have a format version suffix that is
|
|
// currently always 1. The functions that load a state map into the in-memory
|
|
// state structure will fail if any of the messages are of an unknown type, so
|
|
// we should increment the format version only as a last resort because this
|
|
// will prevent users from downgrading to an earlier version of Terraform once
|
|
// they've got at least one state map message that is of a newer version.
|
|
//////////////
|
|
|
|
// Represents the existence of a particular component instance.
|
|
//
|
|
// This is here mainly to remove the ambiguity between a component instance that
|
|
// exists but contains no resource instances vs. a component instance that
|
|
// doesn't exist at all.
|
|
//
|
|
// Because the state map is updated on a per-element basis rather than
|
|
// atomically, it's possible that the state map might contain resource instances
|
|
// which belong to a component instance that is not tracked by a message of
|
|
// this type. In that case, the state loader will just assume an implied
|
|
// message of this type with a matching component instance address and with
|
|
// all other fields unset.
|
|
message StateComponentInstanceV1 {
|
|
// The component instance's output values as reported from the most recent
|
|
// apply action. We retain this only so that we have some values to use
|
|
// in cases where the values in the configuration are unavailable or
|
|
// insufficient, such as when we're making a destroy-mode plan and therefore
|
|
// the desired state would be for the component instance to cease existing
|
|
// but yet we still need to have _some_ output values to use when planning
|
|
// and applying other component instances that refer to this one.
|
|
map<string, DynamicValue> output_values = 1;
|
|
|
|
// The input variables for this component instance as reported from the
|
|
// most recent apply action. We retain this only for usage within removed
|
|
// blocks, where we need to know the input variables to be able to plan
|
|
// and apply the destroy action without asking the user to resupply or
|
|
// remember them.
|
|
map<string, DynamicValue> input_variables = 2;
|
|
|
|
// The absolute configuration addresses of components that this component
|
|
// instance depended on when it was created. We preserve this information
|
|
// to help with plan and apply ordering during destroy plans or for removed
|
|
// blocks.
|
|
repeated string dependency_addrs = 3;
|
|
|
|
// The absolute configuration addresses of components that depended on this
|
|
// component instance when it was created. We preserve this information
|
|
// to help with plan and apply ordering during destroy plans or for removed
|
|
// blocks.
|
|
repeated string dependent_addrs = 4;
|
|
}
|
|
|
|
// Represents the existence of a particular resource instance object in a
|
|
// particular component instance.
|
|
//
|
|
// A resource instance message object should typically be accompanied by a
|
|
// StateComponentInstanceV1 (or later version) that represents the existence
|
|
// of the component itself, but for robustness we tolerate the absense of
|
|
// such a message and just assume that all of its fields (other than the
|
|
// component instance address) are unset.
|
|
message StateResourceInstanceObjectV1 {
|
|
// value_json is a JSON representation of the object value representing
|
|
// this resource instance object.
|
|
//
|
|
// This is JSON-serialized rather than MessagePack serialized (as we do
|
|
// for everything else in this format and in the RPC API) because
|
|
// the provider protocol only supports legacy flatmap and JSON as input
|
|
// to the state upgrade process, and we won't be able to transcode from
|
|
// MessagePack to JSON once we decode this because we won't know the
|
|
// schema that the value was encoded with.
|
|
//
|
|
// This is a pragmatic exception for this particular quirk of Terraform's
|
|
// provider API design. Other parts of this format and associated protocol
|
|
// should use tfplan.DynamicValue and MessagePack encoding for consistency.
|
|
bytes value_json = 1;
|
|
repeated tfplan.Path sensitive_paths = 2;
|
|
uint64 schema_version = 3;
|
|
|
|
Status status = 4;
|
|
repeated string dependencies = 5;
|
|
bool create_before_destroy = 6;
|
|
string provider_config_addr = 7;
|
|
|
|
// provider_specific_data is arbitrary bytes produced by the provider
|
|
// in its apply response which we preserve and pass back to it in any
|
|
// subsequent plan operation.
|
|
bytes provider_specific_data = 8;
|
|
|
|
enum Status {
|
|
UNKNOWN = 0;
|
|
READY = 1;
|
|
DAMAGED = 2; // (formerly known as "tainted")
|
|
}
|
|
}
|
|
|
|
message DynamicValue {
|
|
tfplan.DynamicValue value = 1;
|
|
repeated tfplan.Path sensitive_paths = 2;
|
|
}
|