Implement a refresh command
This change implements a `pulumi refresh` command. It operates a bit
like `pulumi update`, and friends, in that it supports `--preview` and
`--diff`, along with the usual flags, and will update your checkpoint.
It works through substitution of the deploy.Source abstraction, which
generates a sequence of resource registration events. This new
deploy.RefreshSource takes in a prior checkpoint and will walk it,
refreshing the state via the associated resource providers by invoking
Read for each resource encountered, and merging the resulting state with
the prior checkpoint, to yield a new resource.Goal state. This state is
then fed through the engine in the usual ways with a few minor caveats:
namely, although the engine must generate steps for the logical
operations (permitting us to get nice summaries, progress, and diffs),
it mustn't actually carry them out because the state being imported
already reflects reality (a deleted resource has *already* been deleted,
so of course the engine need not perform the deletion). The diffing
logic also needs to know how to treat the case of refresh slightly
differently, because we are going to be diffing outputs and not inputs.
Note that support for managed stacks is not yet complete, since that
requires updates to the service to support a refresh endpoint. That
will be coming soon ...
2018-04-10 20:22:39 +02:00
|
|
|
// Copyright 2016-2018, Pulumi Corporation. All rights reserved.
|
|
|
|
|
|
|
|
package cmd
|
|
|
|
|
|
|
|
import (
|
2018-04-20 03:59:14 +02:00
|
|
|
"context"
|
Implement a refresh command
This change implements a `pulumi refresh` command. It operates a bit
like `pulumi update`, and friends, in that it supports `--preview` and
`--diff`, along with the usual flags, and will update your checkpoint.
It works through substitution of the deploy.Source abstraction, which
generates a sequence of resource registration events. This new
deploy.RefreshSource takes in a prior checkpoint and will walk it,
refreshing the state via the associated resource providers by invoking
Read for each resource encountered, and merging the resulting state with
the prior checkpoint, to yield a new resource.Goal state. This state is
then fed through the engine in the usual ways with a few minor caveats:
namely, although the engine must generate steps for the logical
operations (permitting us to get nice summaries, progress, and diffs),
it mustn't actually carry them out because the state being imported
already reflects reality (a deleted resource has *already* been deleted,
so of course the engine need not perform the deletion). The diffing
logic also needs to know how to treat the case of refresh slightly
differently, because we are going to be diffing outputs and not inputs.
Note that support for managed stacks is not yet complete, since that
requires updates to the service to support a refresh endpoint. That
will be coming soon ...
2018-04-10 20:22:39 +02:00
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
"golang.org/x/crypto/ssh/terminal"
|
|
|
|
|
|
|
|
"github.com/pulumi/pulumi/pkg/backend"
|
|
|
|
"github.com/pulumi/pulumi/pkg/engine"
|
|
|
|
"github.com/pulumi/pulumi/pkg/tokens"
|
|
|
|
"github.com/pulumi/pulumi/pkg/util/cmdutil"
|
|
|
|
)
|
|
|
|
|
|
|
|
func newRefreshCmd() *cobra.Command {
|
|
|
|
var debug bool
|
|
|
|
var message string
|
|
|
|
var stack string
|
|
|
|
|
|
|
|
// Flags for engine.UpdateOptions.
|
|
|
|
var analyzers []string
|
|
|
|
var color colorFlag
|
|
|
|
var diffDisplay bool
|
|
|
|
var force bool
|
|
|
|
var parallel int
|
|
|
|
var preview bool
|
|
|
|
var showConfig bool
|
|
|
|
var showReplacementSteps bool
|
|
|
|
var showSames bool
|
|
|
|
|
|
|
|
var cmd = &cobra.Command{
|
|
|
|
Use: "refresh",
|
|
|
|
Short: "Refresh the resources in a stack",
|
|
|
|
Long: "Refresh the resources in a stack.\n" +
|
|
|
|
"\n" +
|
|
|
|
"This command compares the current stack's resource state with the state known to exist in\n" +
|
|
|
|
"the actual cloud provider. Any such changes are adopted into the current stack. Note that if\n" +
|
|
|
|
"the program text isn't updated accordingly, subsequent updates may still appear to be out of\n" +
|
|
|
|
"synch with respect to the cloud provider's source of truth.\n" +
|
|
|
|
"\n" +
|
|
|
|
"The program to run is loaded from the project in the current directory. Use the `-C` or\n" +
|
|
|
|
"`--cwd` flag to use a different directory.",
|
|
|
|
Args: cmdutil.NoArgs,
|
|
|
|
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
|
|
|
if !force && !preview && !terminal.IsTerminal(int(os.Stdout.Fd())) {
|
2018-04-18 20:12:02 +02:00
|
|
|
return errors.New("'refresh' must be run interactively or be passed the --force or --preview flag")
|
Implement a refresh command
This change implements a `pulumi refresh` command. It operates a bit
like `pulumi update`, and friends, in that it supports `--preview` and
`--diff`, along with the usual flags, and will update your checkpoint.
It works through substitution of the deploy.Source abstraction, which
generates a sequence of resource registration events. This new
deploy.RefreshSource takes in a prior checkpoint and will walk it,
refreshing the state via the associated resource providers by invoking
Read for each resource encountered, and merging the resulting state with
the prior checkpoint, to yield a new resource.Goal state. This state is
then fed through the engine in the usual ways with a few minor caveats:
namely, although the engine must generate steps for the logical
operations (permitting us to get nice summaries, progress, and diffs),
it mustn't actually carry them out because the state being imported
already reflects reality (a deleted resource has *already* been deleted,
so of course the engine need not perform the deletion). The diffing
logic also needs to know how to treat the case of refresh slightly
differently, because we are going to be diffing outputs and not inputs.
Note that support for managed stacks is not yet complete, since that
requires updates to the service to support a refresh endpoint. That
will be coming soon ...
2018-04-10 20:22:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if force && preview {
|
|
|
|
return errors.New("--force and --preview cannot both be specified")
|
|
|
|
}
|
|
|
|
|
|
|
|
s, err := requireStack(tokens.QName(stack), true)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
proj, root, err := readProject()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
m, err := getUpdateMetadata(message, root)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "gathering environment metadata")
|
|
|
|
}
|
|
|
|
|
2018-04-20 03:59:14 +02:00
|
|
|
err = s.Refresh(proj, root, m, engine.UpdateOptions{
|
Implement a refresh command
This change implements a `pulumi refresh` command. It operates a bit
like `pulumi update`, and friends, in that it supports `--preview` and
`--diff`, along with the usual flags, and will update your checkpoint.
It works through substitution of the deploy.Source abstraction, which
generates a sequence of resource registration events. This new
deploy.RefreshSource takes in a prior checkpoint and will walk it,
refreshing the state via the associated resource providers by invoking
Read for each resource encountered, and merging the resulting state with
the prior checkpoint, to yield a new resource.Goal state. This state is
then fed through the engine in the usual ways with a few minor caveats:
namely, although the engine must generate steps for the logical
operations (permitting us to get nice summaries, progress, and diffs),
it mustn't actually carry them out because the state being imported
already reflects reality (a deleted resource has *already* been deleted,
so of course the engine need not perform the deletion). The diffing
logic also needs to know how to treat the case of refresh slightly
differently, because we are going to be diffing outputs and not inputs.
Note that support for managed stacks is not yet complete, since that
requires updates to the service to support a refresh endpoint. That
will be coming soon ...
2018-04-10 20:22:39 +02:00
|
|
|
Analyzers: analyzers,
|
|
|
|
Force: force,
|
|
|
|
Preview: preview,
|
|
|
|
Parallel: parallel,
|
|
|
|
Debug: debug,
|
|
|
|
}, backend.DisplayOptions{
|
|
|
|
Color: color.Colorization(),
|
|
|
|
ShowConfig: showConfig,
|
|
|
|
ShowReplacementSteps: showReplacementSteps,
|
|
|
|
ShowSameResources: showSames,
|
|
|
|
DiffDisplay: diffDisplay,
|
|
|
|
Debug: debug,
|
2018-04-20 03:59:14 +02:00
|
|
|
}, cancellationScopes)
|
|
|
|
if err == context.Canceled {
|
|
|
|
return errors.New("refresh cancelled")
|
|
|
|
}
|
|
|
|
return err
|
Implement a refresh command
This change implements a `pulumi refresh` command. It operates a bit
like `pulumi update`, and friends, in that it supports `--preview` and
`--diff`, along with the usual flags, and will update your checkpoint.
It works through substitution of the deploy.Source abstraction, which
generates a sequence of resource registration events. This new
deploy.RefreshSource takes in a prior checkpoint and will walk it,
refreshing the state via the associated resource providers by invoking
Read for each resource encountered, and merging the resulting state with
the prior checkpoint, to yield a new resource.Goal state. This state is
then fed through the engine in the usual ways with a few minor caveats:
namely, although the engine must generate steps for the logical
operations (permitting us to get nice summaries, progress, and diffs),
it mustn't actually carry them out because the state being imported
already reflects reality (a deleted resource has *already* been deleted,
so of course the engine need not perform the deletion). The diffing
logic also needs to know how to treat the case of refresh slightly
differently, because we are going to be diffing outputs and not inputs.
Note that support for managed stacks is not yet complete, since that
requires updates to the service to support a refresh endpoint. That
will be coming soon ...
2018-04-10 20:22:39 +02:00
|
|
|
}),
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd.PersistentFlags().BoolVarP(
|
|
|
|
&debug, "debug", "d", false,
|
|
|
|
"Print detailed debugging output during resource operations")
|
|
|
|
cmd.PersistentFlags().StringVarP(
|
|
|
|
&stack, "stack", "s", "",
|
|
|
|
"Choose a stack other than the currently selected one")
|
|
|
|
|
|
|
|
cmd.PersistentFlags().StringVarP(
|
|
|
|
&message, "message", "m", "",
|
|
|
|
"Optional message to associate with the update operation")
|
|
|
|
|
|
|
|
// Flags for engine.UpdateOptions.
|
|
|
|
cmd.PersistentFlags().StringSliceVar(
|
|
|
|
&analyzers, "analyzer", nil,
|
|
|
|
"Run one or more analyzers as part of this update")
|
|
|
|
cmd.PersistentFlags().VarP(
|
|
|
|
&color, "color", "c", "Colorize output. Choices are: always, never, raw, auto")
|
|
|
|
cmd.PersistentFlags().BoolVar(
|
|
|
|
&diffDisplay, "diff", false,
|
|
|
|
"Display operation as a rich diff showing the overall change")
|
|
|
|
cmd.PersistentFlags().BoolVarP(
|
|
|
|
&force, "force", "f", false,
|
|
|
|
"Skip confirmation prompts and preview, and proceed with the update automatically")
|
|
|
|
cmd.PersistentFlags().IntVarP(
|
|
|
|
¶llel, "parallel", "p", 0,
|
|
|
|
"Allow P resource operations to run in parallel at once (<=1 for no parallelism)")
|
|
|
|
cmd.PersistentFlags().BoolVarP(
|
|
|
|
&preview, "preview", "n", false,
|
|
|
|
"Don't create/delete resources; just preview the planned operations")
|
|
|
|
cmd.PersistentFlags().BoolVar(
|
|
|
|
&showReplacementSteps, "show-replacement-steps", false,
|
|
|
|
"Show detailed resource replacement creates and deletes instead of a single step")
|
|
|
|
cmd.PersistentFlags().BoolVar(
|
|
|
|
&showSames, "show-sames", false,
|
|
|
|
"Show resources that needn't be updated because they haven't changed, alongside those that do")
|
|
|
|
|
|
|
|
return cmd
|
|
|
|
}
|