224 lines
9.8 KiB
Go
224 lines
9.8 KiB
Go
// Copyright 2016-2018, Pulumi Corporation.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package backend encapsulates all extensibility points required to fully implement a new cloud provider.
|
|
package backend
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/pulumi/pulumi/pkg/apitype"
|
|
"github.com/pulumi/pulumi/pkg/backend/display"
|
|
"github.com/pulumi/pulumi/pkg/engine"
|
|
"github.com/pulumi/pulumi/pkg/operations"
|
|
"github.com/pulumi/pulumi/pkg/resource"
|
|
"github.com/pulumi/pulumi/pkg/resource/config"
|
|
"github.com/pulumi/pulumi/pkg/resource/deploy"
|
|
"github.com/pulumi/pulumi/pkg/resource/stack"
|
|
"github.com/pulumi/pulumi/pkg/tokens"
|
|
"github.com/pulumi/pulumi/pkg/util/cancel"
|
|
"github.com/pulumi/pulumi/pkg/workspace"
|
|
)
|
|
|
|
var (
|
|
// ErrNoPreviousDeployment is returned when there isn't a previous deployment.
|
|
ErrNoPreviousDeployment = errors.New("no previous deployment")
|
|
)
|
|
|
|
// StackAlreadyExistsError is returned from CreateStack when the stack already exists in the backend.
|
|
type StackAlreadyExistsError struct {
|
|
StackName string
|
|
}
|
|
|
|
func (e StackAlreadyExistsError) Error() string {
|
|
return fmt.Sprintf("stack '%v' already exists", e.StackName)
|
|
}
|
|
|
|
// StackReference is an opaque type that refers to a stack managed by a backend. The CLI uses the ParseStackReference
|
|
// method to turn a string like "my-great-stack" or "pulumi/my-great-stack" into a stack reference that can be used to
|
|
// interact with the stack via the backend. Stack references are specific to a given backend and different back ends
|
|
// may interpret the string passed to ParseStackReference differently
|
|
type StackReference interface {
|
|
// fmt.Stringer's String() method returns a string of the stack identity, suitable for display in the CLI
|
|
fmt.Stringer
|
|
// Name is the name that will be passed to the Pulumi engine when preforming operations on this stack. This
|
|
// name may not uniquely identify the stack (e.g. the cloud backend embeds owner information in the StackReference
|
|
// but that informaion is not part of the StackName() we pass to the engine.
|
|
Name() tokens.QName
|
|
}
|
|
|
|
// StackSummary provides a basic description of a stack, without the ability to inspect its resources or make changes.
|
|
type StackSummary interface {
|
|
Name() StackReference
|
|
|
|
// LastUpdate returns when the stack was last updated, as applicable.
|
|
LastUpdate() *time.Time
|
|
// ResourceCount returns the stack's resource count, as applicable.
|
|
ResourceCount() *int
|
|
}
|
|
|
|
// Backend is an interface that represents actions the engine will interact with to manage stacks of cloud resources.
|
|
// It can be implemented any number of ways to provide pluggable backend implementations of the Pulumi Cloud.
|
|
type Backend interface {
|
|
// Name returns a friendly name for this backend.
|
|
Name() string
|
|
// URL returns a URL at which information about this backend may be seen.
|
|
URL() string
|
|
|
|
// ParseStackReference takes a string representation and parses it to a reference which may be used for other
|
|
// methods in this backend.
|
|
ParseStackReference(s string) (StackReference, error)
|
|
|
|
// GetStack returns a stack object tied to this backend with the given name, or nil if it cannot be found.
|
|
GetStack(ctx context.Context, stackRef StackReference) (Stack, error)
|
|
// CreateStack creates a new stack with the given name and options that are specific to the backend provider.
|
|
CreateStack(ctx context.Context, stackRef StackReference, opts interface{}) (Stack, error)
|
|
// RemoveStack removes a stack with the given name. If force is true, the stack will be removed even if it
|
|
// still contains resources. Otherwise, if the stack contains resources, a non-nil error is returned, and the
|
|
// first boolean return value will be set to true.
|
|
RemoveStack(ctx context.Context, stackRef StackReference, force bool) (bool, error)
|
|
// ListStacks returns a list of stack summaries for all known stacks in the target backend.
|
|
ListStacks(ctx context.Context, projectFilter *tokens.PackageName) ([]StackSummary, error)
|
|
|
|
// GetStackCrypter returns an encrypter/decrypter for the given stack's secret config values.
|
|
GetStackCrypter(stackRef StackReference) (config.Crypter, error)
|
|
|
|
// Preview shows what would be updated given the current workspace's contents.
|
|
Preview(ctx context.Context, stackRef StackReference, op UpdateOperation) (engine.ResourceChanges, error)
|
|
// Update updates the target stack with the current workspace's contents (config and code).
|
|
Update(ctx context.Context, stackRef StackReference, op UpdateOperation) (engine.ResourceChanges, error)
|
|
// Refresh refreshes the stack's state from the cloud provider.
|
|
Refresh(ctx context.Context, stackRef StackReference, op UpdateOperation) (engine.ResourceChanges, error)
|
|
// Destroy destroys all of this stack's resources.
|
|
Destroy(ctx context.Context, stackRef StackReference, op UpdateOperation) (engine.ResourceChanges, error)
|
|
|
|
// GetHistory returns all updates for the stack. The returned UpdateInfo slice will be in
|
|
// descending order (newest first).
|
|
GetHistory(ctx context.Context, stackRef StackReference) ([]UpdateInfo, error)
|
|
// GetLogs fetches a list of log entries for the given stack, with optional filtering/querying.
|
|
GetLogs(ctx context.Context, stackRef StackReference, query operations.LogQuery) ([]operations.LogEntry, error)
|
|
// Get the configuration from the most recent deployment of the stack.
|
|
GetLatestConfiguration(ctx context.Context, stackRef StackReference) (config.Map, error)
|
|
|
|
// GetStackTags fetches the stack's existing tags.
|
|
GetStackTags(ctx context.Context, stackRef StackReference) (map[apitype.StackTagName]string, error)
|
|
// UpdateStackTags updates the stacks's tags, replacing all existing tags.
|
|
UpdateStackTags(ctx context.Context, stackRef StackReference, tags map[apitype.StackTagName]string) error
|
|
|
|
// ExportDeployment exports the deployment for the given stack as an opaque JSON message.
|
|
ExportDeployment(ctx context.Context, stackRef StackReference) (*apitype.UntypedDeployment, error)
|
|
// ImportDeployment imports the given deployment into the indicated stack.
|
|
ImportDeployment(ctx context.Context, stackRef StackReference, deployment *apitype.UntypedDeployment) error
|
|
// Logout logs you out of the backend and removes any stored credentials.
|
|
Logout() error
|
|
// Returns the identity of the current user for the backend.
|
|
CurrentUser() (string, error)
|
|
}
|
|
|
|
// UpdateOperation is a complete stack update operation (preview, update, refresh, or destroy).
|
|
type UpdateOperation struct {
|
|
Proj *workspace.Project
|
|
Root string
|
|
M *UpdateMetadata
|
|
Opts UpdateOptions
|
|
Scopes CancellationScopeSource
|
|
}
|
|
|
|
// UpdateOptions is the full set of update options, including backend and engine options.
|
|
type UpdateOptions struct {
|
|
// Engine contains all of the engine-specific options.
|
|
Engine engine.UpdateOptions
|
|
// Display contains all of the backend display options.
|
|
Display display.Options
|
|
|
|
// AutoApprove, when true, will automatically approve previews.
|
|
AutoApprove bool
|
|
// SkipPreview, when true, causes the preview step to be skipped.
|
|
SkipPreview bool
|
|
}
|
|
|
|
// CancellationScope provides a scoped source of cancellation and termination requests.
|
|
type CancellationScope interface {
|
|
// Context returns the cancellation context used to observe cancellation and termination requests for this scope.
|
|
Context() *cancel.Context
|
|
// Close closes the cancellation scope.
|
|
Close()
|
|
}
|
|
|
|
// CancellationScopeSource provides a source for cancellation scopes.
|
|
type CancellationScopeSource interface {
|
|
// NewScope creates a new cancellation scope.
|
|
NewScope(events chan<- engine.Event, isPreview bool) CancellationScope
|
|
}
|
|
|
|
// tracingOptionsKey is the value used as the context key for TracingOptions.
|
|
var tracingOptionsKey struct{}
|
|
|
|
// TracingOptions describes the set of options available for configuring tracing on a per-request basis.
|
|
type TracingOptions struct {
|
|
// PropagateSpans indicates that spans should be propagated from the client to the Pulumi service when making API
|
|
// calls.
|
|
PropagateSpans bool
|
|
// IncludeTracingHeader indicates that API calls should include the indicated tracing header contents.
|
|
TracingHeader string
|
|
}
|
|
|
|
// ContextWithTracingOptions returns a new context.Context with the indicated tracing options.
|
|
func ContextWithTracingOptions(ctx context.Context, opts TracingOptions) context.Context {
|
|
return context.WithValue(ctx, tracingOptionsKey, opts)
|
|
}
|
|
|
|
// TracingOptionsFromContext retrieves any tracing options present in the given context. If no options are present,
|
|
// this function returns the zero value.
|
|
func TracingOptionsFromContext(ctx context.Context) TracingOptions {
|
|
opts, _ := ctx.Value(tracingOptionsKey).(TracingOptions)
|
|
return opts
|
|
}
|
|
|
|
// NewBackendClient returns a deploy.BackendClient that wraps the given Backend.
|
|
func NewBackendClient(backend Backend) deploy.BackendClient {
|
|
return &backendClient{backend: backend}
|
|
}
|
|
|
|
type backendClient struct {
|
|
backend Backend
|
|
}
|
|
|
|
// GetStackOutputs returns the outputs of the stack with the given name.
|
|
func (c *backendClient) GetStackOutputs(ctx context.Context, name string) (resource.PropertyMap, error) {
|
|
ref, err := c.backend.ParseStackReference(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s, err := c.backend.GetStack(ctx, ref)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if s == nil {
|
|
return nil, errors.Errorf("unknown stack \"%s\"", name)
|
|
}
|
|
snap, err := s.Snapshot(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res, _ := stack.GetRootStackResource(snap)
|
|
if res == nil {
|
|
return resource.PropertyMap{}, nil
|
|
}
|
|
return res.Outputs, nil
|
|
}
|