This PR adds a new `pulumi history` command, which prints the update history for a stack. The local backend stores the update history in a JSON file on disk, next to the checkpoint file. The cloud backend simply provides the update metadata, and expects to receive all the data from a (NYI) `/history` REST endpoint. `pkg/backend/updates.go` defines the data that is being persisted. The way the data is wired through the system is adding a new `backend.UpdateMetadata` parameter to a Stack/Backend's `Update` and `Destroy` methods. I use `tests/integration/stack_outputs/` as the simple app for the related tests, hence the addition to the `.gitignore` and fixing the name in the `Pulumi.yaml`. Fixes #636.
103 lines
3.1 KiB
Go
103 lines
3.1 KiB
Go
// Copyright 2018, Pulumi Corporation. All rights reserved.
|
|
|
|
package backend
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/pulumi/pulumi/pkg/engine"
|
|
"github.com/pulumi/pulumi/pkg/resource/config"
|
|
)
|
|
|
|
// UpdateMetadata describes optional metadata about an update.
|
|
type UpdateMetadata struct {
|
|
// Message is an optional message associated with the update.
|
|
Message string `json:"message"`
|
|
// Environment contains optional data from the deploying environment. e.g. the current
|
|
// source code control commit information.
|
|
Environment map[string]string `json:"environment"`
|
|
}
|
|
|
|
// UpdateKind is an enum for the type of update performed.
|
|
type UpdateKind string
|
|
|
|
const (
|
|
// DeployUpdate is the prototypical Pulumi program update.
|
|
DeployUpdate UpdateKind = "update"
|
|
// PreviewUpdate is a preview of an update, without impacting resources.
|
|
PreviewUpdate = "preview"
|
|
// DestroyUpdate is an update which removes all resources.
|
|
DestroyUpdate = "destroy"
|
|
)
|
|
|
|
// UpdateResult is an enum for the result of the update.
|
|
type UpdateResult string
|
|
|
|
const (
|
|
// InProgressResult is for updates that have not yet completed.
|
|
InProgressResult = "in-progress"
|
|
// SucceededResult is for updates that completed successfully.
|
|
SucceededResult UpdateResult = "succeeded"
|
|
// FailedResult is for updates that have failed.
|
|
FailedResult = "failed"
|
|
)
|
|
|
|
// Keys we use for values put into UpdateInfo.Environment.
|
|
const (
|
|
// GitHead is the commit hash of HEAD.
|
|
GitHead = "git.head"
|
|
// GitDirty ("true", "false") indiciates if there are any unstaged or modified files in the local repo.
|
|
GitDirty = "git.dirty"
|
|
|
|
// GitHubLogin is the user/organization who owns the local repo, if the origin remote is hosted on GitHub.com.
|
|
GitHubLogin = "github.login"
|
|
// GitHubRepo is the name of the GitHub repo, if the local git repo's remote origin is hosted on GitHub.com.
|
|
GitHubRepo = "github.repo"
|
|
)
|
|
|
|
// UpdateInfo describes a previous update.
|
|
type UpdateInfo struct {
|
|
// Information known before an update is started.
|
|
|
|
Kind UpdateKind `json:"kind"`
|
|
StartTime int64 `json:"startTime"`
|
|
// Message is an optional message associated with the update.
|
|
Message string `json:"message"`
|
|
// Environment contains optional data from the deploying environment. e.g. the current
|
|
// source code control commit information.
|
|
Environment map[string]string `json:"environment"`
|
|
|
|
// Config used for the update.
|
|
Config config.Map `json:"config"`
|
|
|
|
// Information obtained from an update completing.
|
|
|
|
Result UpdateResult `json:"result"`
|
|
EndTime int64 `json:"endTime"`
|
|
|
|
ResourceChanges engine.ResourceChanges `json:"resourceChanges"`
|
|
}
|
|
|
|
// updateSorter implements the sort.Interface interface.
|
|
// Sorts by StartTime in *descending* order (more recent first).
|
|
type updateSorter struct {
|
|
u []UpdateInfo
|
|
}
|
|
|
|
func (us *updateSorter) Len() int {
|
|
return len(us.u)
|
|
}
|
|
|
|
func (us *updateSorter) Swap(i, j int) {
|
|
us.u[i], us.u[j] = us.u[j], us.u[i]
|
|
}
|
|
|
|
func (us *updateSorter) Less(i, j int) bool {
|
|
return us.u[i].StartTime > us.u[j].StartTime
|
|
}
|
|
|
|
// Sort orders the UpdateInfo slice by StartTime descending.
|
|
func Sort(updates []UpdateInfo) {
|
|
us := updateSorter{u: updates}
|
|
sort.Sort(&us)
|
|
}
|