From d857c75e336fab660d12084dbb8938dbb23e513b Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Fri, 14 Jul 2023 16:13:49 -0700 Subject: [PATCH] stackplan: Initial models for a "meta-plan" over an entire stack --- internal/stacks/stackplan/component.go | 27 +++++++++++++++++++++ internal/stacks/stackplan/doc.go | 11 +++++++++ internal/stacks/stackplan/plan.go | 33 ++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 internal/stacks/stackplan/component.go create mode 100644 internal/stacks/stackplan/doc.go create mode 100644 internal/stacks/stackplan/plan.go diff --git a/internal/stacks/stackplan/component.go b/internal/stacks/stackplan/component.go new file mode 100644 index 0000000000..f219bf8cde --- /dev/null +++ b/internal/stacks/stackplan/component.go @@ -0,0 +1,27 @@ +package stackplan + +import ( + "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/collections" + "github.com/hashicorp/terraform/internal/plans" +) + +// Component is a container for a set of changes that all belong to the same +// component instance as declared in a stack configuration. +// +// Each instance of component essentially maps to one call into the main +// Terraform language runtime to apply all of the described changes together as +// a single operation. +type Component struct { + // ResourceInstanceChangedOutside describes changes that Terraform has + // detected were made outside of Terraform since the last run. + ResourceInstanceChangedOutside collections.Map[addrs.AbsResourceInstance, *plans.ResourceInstanceChange] + + // ResourceInstancePlanned describes the changes that Terraform is proposing + // to make to try to converge the real system state with the desired state + // as described by the configuration. + ResourceInstancePlanned collections.Map[addrs.AbsResourceInstance, *plans.ResourceInstanceChange] + + // TODO: Something for deferred resource instance changes, once we have + // such a concept. +} diff --git a/internal/stacks/stackplan/doc.go b/internal/stacks/stackplan/doc.go new file mode 100644 index 0000000000..148cde1b50 --- /dev/null +++ b/internal/stacks/stackplan/doc.go @@ -0,0 +1,11 @@ +// Package stackplan contains the models and some business logic for stack-wide +// "meta-plans", which in practice are equivalent to multiple of what we +// traditionally think of as a "plan" in the non-stacks Terraform workflow, +// typically represented as a [plans.Plan] object. +// +// The stack plan model is intentionally slightly different from the original +// plan model because in the stack runtime we need to be able to split a +// traditional plan into smaller parts that we stream out to the caller as +// events, but the model here should be isomorphic so that we can translate +// to and from the models expected by the main Terraform language runtime. +package stackplan diff --git a/internal/stacks/stackplan/plan.go b/internal/stacks/stackplan/plan.go new file mode 100644 index 0000000000..b3b53c60bd --- /dev/null +++ b/internal/stacks/stackplan/plan.go @@ -0,0 +1,33 @@ +package stackplan + +import ( + "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/collections" + "github.com/hashicorp/terraform/internal/plans" + "github.com/hashicorp/terraform/internal/stacks/stackaddrs" +) + +// Plan is the main type in this package, representing an entire stack plan. +// +// However, the process of _creating_ a plan doesn't actually produce a single +// object of this type, and instead produces fragments of it gradually as the +// planning process proceeds. The caller of the stack runtime must retain +// all of the raw parts in the order they were emitted and provide them back +// during the apply phase, and then we will finally construct a single instance +// of Plan covering the entire set of changes before we begin applying it. +type Plan struct { + // Applyable is true for a plan that was successfully created in full and + // is sufficient to be applied, or false if the plan is incomplete for + // some reason, such as if an error occurred during planning and so + // the planning process did not entirely run. + Applyable bool + + // Components contains the separate plans for each of the compoonent + // instances defined in the overall stack configuration, including any + // nested component instances from embedded stacks. + Components collections.Map[stackaddrs.AbsComponentInstance, *Component] + + // OutputValues describes the planned changes to the output values of + // the topmost stack configuration. + OutputValues map[addrs.OutputValue]*plans.OutputChange +}