pulumi/pkg/engine/destroy.go
joeduffy 6ad785d5c4 Revise the way previews are controlled
I found the flag --force to be a strange name for skipping a preview,
since that name is usually reserved for operations that might be harmful
and yet you're coercing a tool to do it anyway, knowing there's a chance
you're going to shoot yourself in the foot.

I also found that what I almost always want in the situation where
--force was being used is to actually just run a preview and have the
confirmation auto-accepted.  Going straight to --force isn't the right
thing in a CI scenario, where you actually want to run a preview first,
just to ensure there aren't any issues, before doing the update.

In a sense, there are four options here:

1. Run a preview, ask for confirmation, then do an update (the default).
2. Run a preview, auto-accept, and then do an update (the CI scenario).
3. Just run a preview with neither a confirmation nor an update (dry run).
4. Just do an update, without performing a preview beforehand (rare).

This change enables all four workflows in our CLI.

Rather than have an explosion of flags, we have a single flag,
--preview, which can specify the mode that we're operating in.  The
following are the values which correlate to the above four modes:

1. "": default (no --preview specified)
2. "auto": auto-accept preview confirmation
3. "only": only run a preview, don't confirm or update
4. "skip": skip the preview altogether

As part of this change, I redid a bit of how the preview modes
were specified.  Rather than booleans, which had some illegal
combinations, this change introduces a new enum type.  Furthermore,
because the engine is wholly ignorant of these flags -- and only the
backend understands them -- it was confusing to me that
engine.UpdateOptions stored this flag, especially given that all
interesting engine options _also_ accepted a dryRun boolean.  As of
this change, the backend.PreviewBehavior controls the preview options.
2018-05-06 13:55:04 -07:00

48 lines
1.4 KiB
Go

// Copyright 2018, Pulumi Corporation. All rights reserved.
package engine
import (
"github.com/pulumi/pulumi/pkg/resource/deploy"
"github.com/pulumi/pulumi/pkg/resource/plugin"
"github.com/pulumi/pulumi/pkg/util/contract"
"github.com/pulumi/pulumi/pkg/workspace"
)
func Destroy(u UpdateInfo, ctx *Context, opts UpdateOptions, dryRun bool) (ResourceChanges, error) {
contract.Require(u != nil, "u")
contract.Require(ctx != nil, "ctx")
defer func() { ctx.Events <- cancelEvent() }()
info, err := newPlanContext(u, "destroy", ctx.ParentSpan)
if err != nil {
return nil, err
}
defer info.Close()
emitter := makeEventEmitter(ctx.Events, u)
return update(ctx, info, planOptions{
UpdateOptions: opts,
SourceFunc: newDestroySource,
Events: emitter,
Diag: newEventSink(emitter),
}, dryRun)
}
func newDestroySource(
opts planOptions, proj *workspace.Project, pwd, main string,
target *deploy.Target, plugctx *plugin.Context, dryRun bool) (deploy.Source, error) {
// For destroy, we consult the manifest for the plugin versions/ required to destroy it.
if target != nil && target.Snapshot != nil {
if err := plugctx.Host.EnsurePlugins(target.Snapshot.Manifest.Plugins); err != nil {
return nil, err
}
}
// Create a nil source. This simply returns "nothing" as the new state, which will cause the
// engine to destroy the entire existing state.
return deploy.NullSource, nil
}