Add --version flag to 'pulumi stack export' (#3906)
* Add --version flag to 'pulumi stack export' * Update CHANGELOG * Update/rebase with latest * Fix lint warning
This commit is contained in:
parent
54d344f7c1
commit
ba046b063b
|
@ -17,6 +17,9 @@ CHANGELOG
|
|||
- Move .NET SDK attributes to the root namespace.
|
||||
[#3902](https://github.com/pulumi/pulumi/pull/3902)
|
||||
|
||||
- Support exporting older stack versions.
|
||||
[#3906](https://github.com/pulumi/pulumi/pull/3906)
|
||||
|
||||
## 1.10.1 (2020-02-06)
|
||||
- Support stack references in the Go SDK.
|
||||
[#3829](https://github.com/pulumi/pulumi/pull/3829)
|
||||
|
|
|
@ -21,6 +21,8 @@ import (
|
|||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/pulumi/pulumi/pkg/apitype"
|
||||
"github.com/pulumi/pulumi/pkg/backend"
|
||||
"github.com/pulumi/pulumi/pkg/backend/display"
|
||||
"github.com/pulumi/pulumi/pkg/util/cmdutil"
|
||||
)
|
||||
|
@ -28,6 +30,7 @@ import (
|
|||
func newStackExportCmd() *cobra.Command {
|
||||
var file string
|
||||
var stackName string
|
||||
var version string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "export",
|
||||
|
@ -40,6 +43,7 @@ func newStackExportCmd() *cobra.Command {
|
|||
"in a stack's state due to failed deployments, manual changes to cloud\n" +
|
||||
"resources, etc.",
|
||||
Run: cmdutil.RunFunc(func(cmd *cobra.Command, args []string) error {
|
||||
ctx := commandContext()
|
||||
opts := display.Options{
|
||||
Color: cmdutil.GetGlobalColorization(),
|
||||
}
|
||||
|
@ -50,9 +54,28 @@ func newStackExportCmd() *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
deployment, err := s.ExportDeployment(commandContext())
|
||||
if err != nil {
|
||||
return err
|
||||
var deployment *apitype.UntypedDeployment
|
||||
// Export the latest version of the checkpoint by default. Otherwise, we require that
|
||||
// the backend/stack implements the ability the export previous checkpoints.
|
||||
if version == "" {
|
||||
deployment, err = s.ExportDeployment(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Check that the stack and its backend supports the ability to do this.
|
||||
be := s.Backend()
|
||||
specificExpBE, ok := be.(backend.SpecificDeploymentExporter)
|
||||
if !ok {
|
||||
return errors.Errorf(
|
||||
"the current backend (%s) does not provide the ability to export previous deployments",
|
||||
be.Name())
|
||||
}
|
||||
|
||||
deployment, err = specificExpBE.ExportDeploymentForVersion(ctx, s, version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Read from stdin or a specified file.
|
||||
|
@ -77,5 +100,7 @@ func newStackExportCmd() *cobra.Command {
|
|||
&stackName, "stack", "s", "", "The name of the stack to operate on. Defaults to the current stack")
|
||||
cmd.PersistentFlags().StringVarP(
|
||||
&file, "file", "", "", "A filename to write stack output to")
|
||||
cmd.PersistentFlags().StringVarP(
|
||||
&version, "version", "", "", "Previous stack version to export. (If unset, will export the latest.)")
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -189,6 +189,17 @@ type Backend interface {
|
|||
CurrentUser() (string, error)
|
||||
}
|
||||
|
||||
// SpecificDeploymentExporter is an interface defining an additional capability of a Backend, specifically the
|
||||
// ability to export a specific versions of a stack's deployment. This isn't a requirement for all backends and
|
||||
// should be checked for dynamically.
|
||||
type SpecificDeploymentExporter interface {
|
||||
// ExportDeploymentForVersion exports a specific deployment from the history of a stack. The meaning of
|
||||
// version is backend-specific. For the Pulumi Console, it is the numeric version. (The first update
|
||||
// being version "1", the second "2", and so on.) Though this might change in the future to use some
|
||||
// other type of identifier or commitish .
|
||||
ExportDeploymentForVersion(ctx context.Context, stack Stack, version string) (*apitype.UntypedDeployment, error)
|
||||
}
|
||||
|
||||
// UpdateOperation is a complete stack update operation (preview, update, refresh, or destroy).
|
||||
type UpdateOperation struct {
|
||||
Proj *workspace.Project
|
||||
|
|
|
@ -125,6 +125,9 @@ type cloudBackend struct {
|
|||
currentProject *workspace.Project
|
||||
}
|
||||
|
||||
// Assert we implement the backend.Backend and backend.SpecificDeploymentExporter interfaces.
|
||||
var _ backend.SpecificDeploymentExporter = &cloudBackend{}
|
||||
|
||||
// New creates a new Pulumi backend for the given cloud API URL and token.
|
||||
func New(d diag.Sink, cloudURL string) (Backend, error) {
|
||||
cloudURL = ValueOrDefaultURL(cloudURL)
|
||||
|
@ -1160,17 +1163,32 @@ func (b *cloudBackend) GetLogs(ctx context.Context, stack backend.Stack, cfg bac
|
|||
|
||||
func (b *cloudBackend) ExportDeployment(ctx context.Context,
|
||||
stack backend.Stack) (*apitype.UntypedDeployment, error) {
|
||||
return b.exportDeployment(ctx, stack.Ref())
|
||||
return b.exportDeployment(ctx, stack.Ref(), nil /* latest */)
|
||||
}
|
||||
|
||||
func (b *cloudBackend) exportDeployment(ctx context.Context,
|
||||
stackRef backend.StackReference) (*apitype.UntypedDeployment, error) {
|
||||
func (b *cloudBackend) ExportDeploymentForVersion(
|
||||
ctx context.Context, stack backend.Stack, version string) (*apitype.UntypedDeployment, error) {
|
||||
// The Pulumi Console defines versions as a positive integer. Parse the provided version string and
|
||||
// ensure it is valid.
|
||||
//
|
||||
// The first stack update version is 1, and monotonically increasing from there.
|
||||
versionNumber, err := strconv.Atoi(version)
|
||||
if err != nil || versionNumber <= 0 {
|
||||
return nil, errors.Errorf("%q is not a valid stack version. It should be a positive integer.", version)
|
||||
}
|
||||
|
||||
return b.exportDeployment(ctx, stack.Ref(), &versionNumber)
|
||||
}
|
||||
|
||||
// exportDeployment exports the checkpoint file for a stack, optionally getting a previous version.
|
||||
func (b *cloudBackend) exportDeployment(
|
||||
ctx context.Context, stackRef backend.StackReference, version *int) (*apitype.UntypedDeployment, error) {
|
||||
stack, err := b.getCloudStackIdentifier(stackRef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
deployment, err := b.client.ExportStackDeployment(ctx, stack)
|
||||
deployment, err := b.client.ExportStackDeployment(ctx, stack, version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -376,11 +376,19 @@ func (pc *Client) GetStackUpdates(ctx context.Context, stack StackIdentifier) ([
|
|||
}
|
||||
|
||||
// ExportStackDeployment exports the indicated stack's deployment as a raw JSON message.
|
||||
func (pc *Client) ExportStackDeployment(ctx context.Context,
|
||||
stack StackIdentifier) (apitype.UntypedDeployment, error) {
|
||||
// If version is nil, will export the latest version of the stack.
|
||||
func (pc *Client) ExportStackDeployment(
|
||||
ctx context.Context, stack StackIdentifier, version *int) (apitype.UntypedDeployment, error) {
|
||||
|
||||
path := getStackPath(stack, "export")
|
||||
|
||||
// Tack on a specific version as desired.
|
||||
if version != nil {
|
||||
path += fmt.Sprintf("/%d", *version)
|
||||
}
|
||||
|
||||
var resp apitype.ExportStackResponse
|
||||
if err := pc.restCall(ctx, "GET", getStackPath(stack, "export"), nil, nil, &resp); err != nil {
|
||||
if err := pc.restCall(ctx, "GET", path, nil, nil, &resp); err != nil {
|
||||
return apitype.UntypedDeployment{}, err
|
||||
}
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ func (b *cloudBackend) newUpdate(ctx context.Context, stackRef backend.StackRefe
|
|||
}
|
||||
|
||||
func (b *cloudBackend) getSnapshot(ctx context.Context, stackRef backend.StackReference) (*deploy.Snapshot, error) {
|
||||
untypedDeployment, err := b.exportDeployment(ctx, stackRef)
|
||||
untypedDeployment, err := b.exportDeployment(ctx, stackRef, nil /* get latest */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue