This commit is contained in:
Pat Gavlin 2020-11-30 14:19:38 -08:00
parent 2818c9888d
commit 6de090c540
20 changed files with 65 additions and 58 deletions

View file

@ -27,6 +27,7 @@ import (
"github.com/pulumi/pulumi/pkg/v3/backend/display"
"github.com/pulumi/pulumi/pkg/v3/engine"
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
"github.com/pulumi/pulumi/sdk/v3/go/common/apitype"
"github.com/pulumi/pulumi/sdk/v3/go/common/diag/colors"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
@ -45,7 +46,7 @@ type ApplierOptions struct {
// Applier applies the changes specified by this update operation against the target stack.
type Applier func(ctx context.Context, kind apitype.UpdateKind, stack Stack, op UpdateOperation,
opts ApplierOptions, events chan<- engine.Event) (engine.Plan, engine.ResourceChanges, result.Result)
opts ApplierOptions, events chan<- engine.Event) (deploy.Plan, engine.ResourceChanges, result.Result)
func ActionLabel(kind apitype.UpdateKind, dryRun bool) string {
v := updateTextMap[kind]
@ -80,7 +81,7 @@ const (
)
func PreviewThenPrompt(ctx context.Context, kind apitype.UpdateKind, stack Stack,
op UpdateOperation, apply Applier) (engine.Plan, engine.ResourceChanges, result.Result) {
op UpdateOperation, apply Applier) (deploy.Plan, engine.ResourceChanges, result.Result) {
// create a channel to hear about the update events from the engine. this will be used so that
// we can build up the diff display in case the user asks to see the details of the diff

View file

@ -162,7 +162,7 @@ type Backend interface {
RenameStack(ctx context.Context, stack Stack, newName tokens.QName) (StackReference, error)
// Preview shows what would be updated given the current workspace's contents.
Preview(ctx context.Context, stack Stack, op UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result)
Preview(ctx context.Context, stack Stack, op UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result)
// Update updates the target stack with the current workspace's contents (config and code).
Update(ctx context.Context, stack Stack, op UpdateOperation) (engine.ResourceChanges, result.Result)
// Import imports resources into a stack.

View file

@ -459,7 +459,7 @@ func (b *localBackend) PackPolicies(
}
func (b *localBackend) Preview(ctx context.Context, stack backend.Stack,
op backend.UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result) {
op backend.UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result) {
if cmdutil.IsTruthy(os.Getenv(PulumiFilestateLockingEnvVar)) {
err := b.Lock(ctx, stack.Ref())
@ -546,7 +546,7 @@ func (b *localBackend) Watch(ctx context.Context, stack backend.Stack,
func (b *localBackend) apply(
ctx context.Context, kind apitype.UpdateKind, stack backend.Stack,
op backend.UpdateOperation, opts backend.ApplierOptions,
events chan<- engine.Event) (engine.Plan, engine.ResourceChanges, result.Result) {
events chan<- engine.Event) (deploy.Plan, engine.ResourceChanges, result.Result) {
stackRef := stack.Ref()
stackName := stackRef.Name()
@ -602,7 +602,7 @@ func (b *localBackend) apply(
// Perform the update
start := time.Now().Unix()
var plan engine.Plan
var plan deploy.Plan
var changes engine.ResourceChanges
var updateRes result.Result
switch kind {

View file

@ -64,7 +64,7 @@ func (s *localStack) Rename(ctx context.Context, newName tokens.QName) (backend.
return backend.RenameStack(ctx, s, newName)
}
func (s *localStack) Preview(ctx context.Context, op backend.UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result) {
func (s *localStack) Preview(ctx context.Context, op backend.UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result) {
return backend.PreviewStack(ctx, s, op)
}

View file

@ -824,7 +824,7 @@ func (b *cloudBackend) RenameStack(ctx context.Context, stack backend.Stack,
}
func (b *cloudBackend) Preview(ctx context.Context, stack backend.Stack,
op backend.UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result) {
op backend.UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result) {
// We can skip PreviewtThenPromptThenExecute, and just go straight to Execute.
opts := backend.ApplierOptions{
DryRun: true,
@ -927,7 +927,7 @@ func (b *cloudBackend) createAndStartUpdate(
func (b *cloudBackend) apply(
ctx context.Context, kind apitype.UpdateKind, stack backend.Stack,
op backend.UpdateOperation, opts backend.ApplierOptions,
events chan<- engine.Event) (engine.Plan, engine.ResourceChanges, result.Result) {
events chan<- engine.Event) (deploy.Plan, engine.ResourceChanges, result.Result) {
actionLabel := backend.ActionLabel(kind, opts.DryRun)
@ -981,7 +981,7 @@ func (b *cloudBackend) query(ctx context.Context, op backend.QueryOperation,
func (b *cloudBackend) runEngineAction(
ctx context.Context, kind apitype.UpdateKind, stackRef backend.StackReference,
op backend.UpdateOperation, update client.UpdateIdentifier, token string,
callerEventsOpt chan<- engine.Event, dryRun bool) (engine.Plan, engine.ResourceChanges, result.Result) {
callerEventsOpt chan<- engine.Event, dryRun bool) (deploy.Plan, engine.ResourceChanges, result.Result) {
contract.Assertf(token != "", "persisted actions require a token")
u, err := b.newUpdate(ctx, stackRef, op, update, token)
@ -1035,7 +1035,7 @@ func (b *cloudBackend) runEngineAction(
engineCtx.ParentSpan = parentSpan.Context()
}
var plan engine.Plan
var plan deploy.Plan
var changes engine.ResourceChanges
var res result.Result
switch kind {

View file

@ -140,7 +140,7 @@ func (s *cloudStack) Rename(ctx context.Context, newName tokens.QName) (backend.
return backend.RenameStack(ctx, s, newName)
}
func (s *cloudStack) Preview(ctx context.Context, op backend.UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result) {
func (s *cloudStack) Preview(ctx context.Context, op backend.UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result) {
return backend.PreviewStack(ctx, s, op)
}

View file

@ -57,7 +57,7 @@ type MockBackend struct {
LogoutAllF func() error
CurrentUserF func() (string, error)
PreviewF func(context.Context, Stack,
UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result)
UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result)
UpdateF func(context.Context, Stack,
UpdateOperation) (engine.ResourceChanges, result.Result)
ImportF func(context.Context, Stack,
@ -180,7 +180,7 @@ func (be *MockBackend) GetStackCrypter(stackRef StackReference) (config.Crypter,
}
func (be *MockBackend) Preview(ctx context.Context, stack Stack,
op UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result) {
op UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result) {
if be.PreviewF != nil {
return be.PreviewF(ctx, stack, op)
@ -335,7 +335,7 @@ type MockStack struct {
ConfigF func() config.Map
SnapshotF func(ctx context.Context) (*deploy.Snapshot, error)
BackendF func() Backend
PreviewF func(ctx context.Context, op UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result)
PreviewF func(ctx context.Context, op UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result)
UpdateF func(ctx context.Context, op UpdateOperation) (engine.ResourceChanges, result.Result)
ImportF func(ctx context.Context, op UpdateOperation,
imports []deploy.Import) (engine.ResourceChanges, result.Result)
@ -381,7 +381,7 @@ func (ms *MockStack) Backend() Backend {
panic("not implemented")
}
func (ms *MockStack) Preview(ctx context.Context, op UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result) {
func (ms *MockStack) Preview(ctx context.Context, op UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result) {
if ms.PreviewF != nil {
return ms.PreviewF(ctx, op)
}

View file

@ -40,7 +40,7 @@ type Stack interface {
Backend() Backend // the backend this stack belongs to.
// Preview changes to this stack.
Preview(ctx context.Context, op UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result)
Preview(ctx context.Context, op UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result)
// Update this stack.
Update(ctx context.Context, op UpdateOperation) (engine.ResourceChanges, result.Result)
// Import resources into this stack.
@ -75,7 +75,7 @@ func RenameStack(ctx context.Context, s Stack, newName tokens.QName) (StackRefer
}
// PreviewStack previews changes to this stack.
func PreviewStack(ctx context.Context, s Stack, op UpdateOperation) (engine.Plan, engine.ResourceChanges, result.Result) {
func PreviewStack(ctx context.Context, s Stack, op UpdateOperation) (deploy.Plan, engine.ResourceChanges, result.Result) {
return s.Backend().Preview(ctx, s, op)
}

View file

@ -20,7 +20,6 @@ import (
"github.com/spf13/cobra"
"github.com/pulumi/pulumi/pkg/v2/backend/display"
"github.com/pulumi/pulumi/pkg/v2/engine"
"github.com/pulumi/pulumi/pkg/v2/resource/deploy"
"github.com/pulumi/pulumi/sdk/v2/go/common/diag/colors"
"github.com/pulumi/pulumi/sdk/v2/go/common/resource"
@ -150,7 +149,7 @@ func pruneSames(root *planNode) *planNode {
return root
}
func renderPlan(plan engine.Plan, showSames bool, color colors.Colorization) []cmdutil.TableRow {
func renderPlan(plan deploy.Plan, showSames bool, color colors.Colorization) []cmdutil.TableRow {
var root *planNode
var orphans []*planNode
nodes := map[resource.URN]*planNode{}

View file

@ -41,6 +41,7 @@ import (
"github.com/pulumi/pulumi/pkg/v3/backend/httpstate"
"github.com/pulumi/pulumi/pkg/v3/backend/state"
"github.com/pulumi/pulumi/pkg/v3/engine"
"github.com/pulumi/pulumi/pkg/v3/resource/deploy"
"github.com/pulumi/pulumi/pkg/v3/resource/stack"
"github.com/pulumi/pulumi/pkg/v3/secrets/passphrase"
"github.com/pulumi/pulumi/pkg/v3/util/cancel"
@ -864,7 +865,7 @@ func getRefreshOption(proj *workspace.Project, refresh string) (bool, error) {
return false, nil
}
func writePlan(path string, plan engine.Plan, enc config.Encrypter, showSecrets bool) error {
func writePlan(path string, plan deploy.Plan, enc config.Encrypter, showSecrets bool) error {
f, err := os.Create(path)
if err != nil {
return err
@ -878,7 +879,7 @@ func writePlan(path string, plan engine.Plan, enc config.Encrypter, showSecrets
return json.NewEncoder(f).Encode(deploymentPlan)
}
func readPlan(path string, dec config.Decrypter, enc config.Encrypter) (engine.Plan, error) {
func readPlan(path string, dec config.Decrypter, enc config.Encrypter) (deploy.Plan, error) {
f, err := os.Open(path)
if err != nil {
return nil, err

View file

@ -165,7 +165,7 @@ func newDeployment(ctx *Context, info *deploymentContext, opts deploymentOptions
var depl *deploy.Deployment
if !opts.isImport {
depl, err = deploy.NewDeployment(
plugctx, target, target.Snapshot, source, localPolicyPackPaths, dryRun, ctx.BackendClient)
plugctx, target, target.Snapshot, opts.Plan, source, localPolicyPackPaths, dryRun, ctx.BackendClient)
} else {
_, defaultProviderVersions, pluginErr := installPlugins(proj, pwd, main, target, plugctx,
false /*returnInstallErrors*/)
@ -216,12 +216,12 @@ type runActions interface {
// run executes the deployment. It is primarily responsible for handling cancellation.
func (deployment *deployment) run(cancelCtx *Context, actions runActions, policyPacks map[string]string,
preview bool) (ResourceChanges, result.Result) {
preview bool) (deploy.Plan, ResourceChanges, result.Result) {
// Change into the plugin context's working directory.
chdir, err := fsutil.Chdir(deployment.Plugctx.Pwd)
if err != nil {
return nil, result.FromError(err)
return nil, nil, result.FromError(err)
}
defer chdir()
@ -240,6 +240,7 @@ func (deployment *deployment) run(cancelCtx *Context, actions runActions, policy
start := time.Now()
done := make(chan bool)
var newPlan deploy.Plan
var walkResult result.Result
go func() {
opts := deploy.Options{
@ -257,7 +258,7 @@ func (deployment *deployment) run(cancelCtx *Context, actions runActions, policy
DisableResourceReferences: deployment.Options.DisableResourceReferences,
DisableOutputValues: deployment.Options.DisableOutputValues,
}
walkResult = deployment.Deployment.Execute(ctx, opts, preview)
newPlan, walkResult = deployment.Deployment.Execute(ctx, opts, preview)
close(done)
}()
@ -288,7 +289,7 @@ func (deployment *deployment) run(cancelCtx *Context, actions runActions, policy
// Emit a summary event.
deployment.Options.Events.summaryEvent(preview, actions.MaybeCorrupt(), duration, changes, policyPacks)
return changes, res
return newPlan, changes, res
}
func (deployment *deployment) Close() error {

View file

@ -23,7 +23,7 @@ import (
"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"
)
func Destroy(u UpdateInfo, ctx *Context, opts UpdateOptions, dryRun bool) (Plan, ResourceChanges, result.Result) {
func Destroy(u UpdateInfo, ctx *Context, opts UpdateOptions, dryRun bool) (deploy.Plan, ResourceChanges, result.Result) {
contract.Require(u != nil, "u")
contract.Require(ctx != nil, "ctx")

View file

@ -21,7 +21,7 @@ import (
)
func Import(u UpdateInfo, ctx *Context, opts UpdateOptions, imports []deploy.Import,
dryRun bool) (Plan, ResourceChanges, result.Result) {
dryRun bool) (deploy.Plan, ResourceChanges, result.Result) {
contract.Require(u != nil, "u")
contract.Require(ctx != nil, "ctx")

View file

@ -23,7 +23,7 @@ import (
"github.com/pulumi/pulumi/sdk/v3/go/common/workspace"
)
func Refresh(u UpdateInfo, ctx *Context, opts UpdateOptions, dryRun bool) (Plan, ResourceChanges, result.Result) {
func Refresh(u UpdateInfo, ctx *Context, opts UpdateOptions, dryRun bool) (deploy.Plan, ResourceChanges, result.Result) {
contract.Require(u != nil, "u")
contract.Require(ctx != nil, "ctx")

View file

@ -147,7 +147,7 @@ type UpdateOptions struct {
Host plugin.Host
// The plan to use for the update, if any.
Plan Plan
Plan deploy.Plan
}
// ResourceChanges contains the aggregate resource changes by operation type.
@ -167,10 +167,7 @@ func (changes ResourceChanges) HasChanges() bool {
return c > 0
}
// Plan records planned resource changes.
type Plan map[resource.URN]*deploy.ResourcePlan
func Update(u UpdateInfo, ctx *Context, opts UpdateOptions, dryRun bool) (Plan, ResourceChanges, result.Result) {
func Update(u UpdateInfo, ctx *Context, opts UpdateOptions, dryRun bool) (deploy.Plan, ResourceChanges, result.Result) {
contract.Require(u != nil, "update")
contract.Require(ctx != nil, "ctx")
@ -425,7 +422,7 @@ func newUpdateSource(
}
func update(ctx *Context, info *deploymentContext, opts deploymentOptions,
preview bool) (Plan, ResourceChanges, result.Result) {
preview bool) (deploy.Plan, ResourceChanges, result.Result) {
// Refresh and Import do not execute Policy Packs.
policies := map[string]string{}

View file

@ -153,7 +153,7 @@ type Deployment struct {
target *Target // the deployment target.
prev *Snapshot // the old resource snapshot for comparison.
olds map[resource.URN]*resource.State // a map of all old resources.
resourcePlans map[resource.URN]*ResourcePlan // a map of all planned resource changes, if any.
plan Plan // a map of all planned resource changes, if any.
imports []Import // resources to import, if this is an import deployment.
isImport bool // true if this is an import deployment.
schemaLoader schema.Loader // the schema cache for this deployment, if any.
@ -164,7 +164,7 @@ type Deployment struct {
providers *providers.Registry // the provider registry for this deployment.
goals *goalMap // the set of resource goals generated by the deployment.
news *resourceMap // the set of new resources generated by the deployment
newResourcePlans map[resource.URN]*ResourcePlan // the set of new resource plans.
newPlan map[resource.URN]*ResourcePlan // the set of new resource plans.
}
// addDefaultProviders adds any necessary default provider definitions and references to the given snapshot. Version
@ -301,7 +301,7 @@ func buildResourceMap(prev *Snapshot, preview bool) ([]*resource.State, map[reso
//
// Note that a deployment uses internal concurrency and parallelism in various ways, so it must be closed if for some
// reason it isn't carried out to its final conclusion. This will result in cancellation and reclamation of resources.
func NewDeployment(ctx *plugin.Context, target *Target, prev *Snapshot, plans map[resource.URN]*ResourcePlan, source Source,
func NewDeployment(ctx *plugin.Context, target *Target, prev *Snapshot, plan Plan, source Source,
localPolicyPackPaths []string, preview bool, backendClient BackendClient) (*Deployment, error) {
contract.Assert(ctx != nil)
@ -345,7 +345,7 @@ func NewDeployment(ctx *plugin.Context, target *Target, prev *Snapshot, plans ma
ctx: ctx,
target: target,
prev: prev,
resourcePlans: plans,
plan: plan,
olds: olds,
source: source,
localPolicyPackPaths: localPolicyPackPaths,
@ -354,7 +354,7 @@ func NewDeployment(ctx *plugin.Context, target *Target, prev *Snapshot, plans ma
providers: reg,
goals: newGoals,
news: newResources,
newResourcePlans: map[resource.URN]*ResourcePlan{},
newPlan: Plan{},
}, nil
}
@ -409,7 +409,7 @@ func (d *Deployment) generateEventURN(event SourceEvent) resource.URN {
}
// Execute executes a deployment to completion, using the given cancellation context and running a preview or update.
func (d *Deployment) Execute(ctx context.Context, opts Options, preview bool) (map[resource.URN]*ResourcePlan, result.Result) {
func (d *Deployment) Execute(ctx context.Context, opts Options, preview bool) (Plan, result.Result) {
deploymentExec := &deploymentExecutor{deployment: d}
return deploymentExec.Execute(ctx, opts, preview)
}

View file

@ -114,7 +114,7 @@ func (ex *deploymentExecutor) reportError(urn resource.URN, err error) {
// Execute executes a deployment to completion, using the given cancellation context and running a preview
// or update.
func (ex *deploymentExecutor) Execute(callerCtx context.Context, opts Options, preview bool) (map[resource.URN]*ResourcePlan, result.Result) {
func (ex *deploymentExecutor) Execute(callerCtx context.Context, opts Options, preview bool) (Plan, result.Result) {
// Set up a goroutine that will signal cancellation to the deployment's plugins if the caller context is cancelled.
// We do not hang this off of the context we create below because we do not want the failure of a single step to
// cause other steps to fail.
@ -295,7 +295,7 @@ func (ex *deploymentExecutor) Execute(callerCtx context.Context, opts Options, p
return nil, result.Bail()
}
return pe.plan.newResourcePlans, res
return ex.deployment.newPlan, res
}
func (ex *deploymentExecutor) performDeletes(
@ -433,7 +433,7 @@ func (ex *deploymentExecutor) retirePendingDeletes(callerCtx context.Context, op
}
// import imports a list of resources into a stack.
func (ex *deploymentExecutor) importResources(callerCtx context.Context, opts Options, preview bool) (map[resource.URN]*ResourcePlan, result.Result) {
func (ex *deploymentExecutor) importResources(callerCtx context.Context, opts Options, preview bool) (Plan, result.Result) {
if len(ex.deployment.imports) == 0 {
return nil, nil
}
@ -466,7 +466,7 @@ func (ex *deploymentExecutor) importResources(callerCtx context.Context, opts Op
ex.reportExecResult("canceled", preview)
return nil, result.Bail()
}
return pe.plan.newResourcePlans, nil
return ex.deployment.newPlan, nil
}
// refresh refreshes the state of the base checkpoint file for the current deployment in memory.

View file

@ -10,6 +10,14 @@ import (
"github.com/pulumi/pulumi/sdk/v2/go/common/util/contract"
)
// A Plan is a mapping from URNs to ResourcePlans. The plan defines an expected set of resources and the expected
// inputs and operations for each. The inputs and operations are treated as constraints, and may allow for inputs or
// operations that do not exactly match those recorded in the plan. In the case of inputs, unknown values in the plan
// accept any value (including no value) as valid. For operations, a same step is allowed in place of an update or
// a replace step, and an update is allowed in place of a replace step. All resource options are required to match
// exactly.
type Plan map[resource.URN]*ResourcePlan
// A ResourcePlan represents the planned goal state and resource operations for a single resource. The operations are
// ordered.
type ResourcePlan struct {

View file

@ -158,7 +158,7 @@ func (sg *stepGenerator) GenerateSteps(event RegisterResourceEvent) ([]Step, res
// Check each proposed step against the relevant resource plan, if any, and generate any output resource plans.
for _, s := range steps {
if resourcePlan, ok := sg.plan.resourcePlans[s.URN()]; ok {
if resourcePlan, ok := sg.deployment.plan[s.URN()]; ok {
if len(resourcePlan.Ops) == 0 {
return nil, result.Errorf("%v is not allowed by the plan: no more steps were expected for this resource", s.Op())
}
@ -170,12 +170,12 @@ func (sg *stepGenerator) GenerateSteps(event RegisterResourceEvent) ([]Step, res
resourcePlan.Ops = resourcePlan.Ops[1:]
}
resourcePlan, ok := sg.plan.newResourcePlans[s.URN()]
resourcePlan, ok := sg.deployment.newPlan[s.URN()]
if !ok {
// TODO(pdg-plan): using the program inputs means that non-determinism could sneak in as part of default
// application. However, it is necessary in the face of computed inputs.
resourcePlan = &ResourcePlan{Goal: event.Goal()}
sg.plan.newResourcePlans[s.URN()] = resourcePlan
sg.deployment.newPlan[s.URN()] = resourcePlan
}
resourcePlan.Ops = append(resourcePlan.Ops, s.Op())
}
@ -237,8 +237,8 @@ func (sg *stepGenerator) generateSteps(event RegisterResourceEvent) ([]Step, res
sg.urns[urn] = true
// If there is a plan for this resource, validate that the program goal conforms to the plan.
if len(sg.plan.resourcePlans) != 0 {
resourcePlan, ok := sg.plan.resourcePlans[urn]
if len(sg.deployment.plan) != 0 {
resourcePlan, ok := sg.deployment.plan[urn]
if !ok {
return nil, result.Errorf("resource not found in plan")
}

View file

@ -42,7 +42,7 @@ func SerializeResourcePlan(plan *deploy.ResourcePlan, enc config.Encrypter, show
}, nil
}
func SerializePlan(plan map[resource.URN]*deploy.ResourcePlan, enc config.Encrypter, showSecrets bool) (apitype.DeploymentPlanV1, error) {
func SerializePlan(plan deploy.Plan, enc config.Encrypter, showSecrets bool) (apitype.DeploymentPlanV1, error) {
resourcePlans := map[resource.URN]apitype.ResourcePlanV1{}
for urn, plan := range plan {
serializedPlan, err := SerializeResourcePlan(plan, enc, showSecrets)
@ -89,14 +89,14 @@ func DeserializeResourcePlan(plan apitype.ResourcePlanV1, dec config.Decrypter,
}, nil
}
func DeserializePlan(plan apitype.DeploymentPlanV1, dec config.Decrypter, enc config.Encrypter) (map[resource.URN]*deploy.ResourcePlan, error) {
resourcePlans := map[resource.URN]*deploy.ResourcePlan{}
for urn, plan := range plan.ResourcePlans {
deserializedPlan, err := DeserializeResourcePlan(plan, dec, enc)
func DeserializePlan(plan apitype.DeploymentPlanV1, dec config.Decrypter, enc config.Encrypter) (deploy.Plan, error) {
deserializedPlan := deploy.Plan{}
for urn, resourcePlan := range plan.ResourcePlans {
deserializedResourcePlan, err := DeserializeResourcePlan(resourcePlan, dec, enc)
if err != nil {
return nil, err
}
resourcePlans[urn] = deserializedPlan
deserializedPlan[urn] = deserializedResourcePlan
}
return resourcePlans, nil
return deserializedPlan, nil
}