As documented in issue #616, the inputs/defaults/outputs model we have today has fundamental problems. The crux of the issue is that our current design requires that defaults present in the old state of a resource are applied to the new inputs for that resource. Unfortunately, it is not possible for the engine to decide which defaults remain applicable and which do not; only the provider has that knowledge. These changes take a more tactical approach to resolving this issue than that originally proposed in #616 that avoids breaking compatibility with existing checkpoints. Rather than treating the Pulumi inputs as the provider input properties for a resource, these inputs are first translated by `Check`. In order to accommodate provider defaults that were chosen for the old resource but should not change for the new, `Check` now takes the old provider inputs as well as the new Pulumi inputs. Rather than the Pulumi inputs and provider defaults, the provider inputs returned by `Check` are recorded in the checkpoint file. Put simply, these changes remove defaults as a first-class concept (except inasmuch as is required to retain the ability to read old checkpoint files) and move the responsibilty for manging and merging defaults into the provider that supplies them. Fixes #616.
62 lines
3.4 KiB
Go
62 lines
3.4 KiB
Go
// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
|
|
|
|
package plugin
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/pulumi/pulumi/pkg/resource"
|
|
"github.com/pulumi/pulumi/pkg/tokens"
|
|
)
|
|
|
|
// Provider presents a simple interface for orchestrating resource create, reead, update, and delete operations. Each
|
|
// provider understands how to handle all of the resource types within a single package.
|
|
//
|
|
// This interface hides some of the messiness of the underlying machinery, since providers are behind an RPC boundary.
|
|
//
|
|
// It is important to note that provider operations are not transactional. (Some providers might decide to offer
|
|
// transactional semantics, but such a provider is a rare treat.) As a result, failures in the operations below can
|
|
// range from benign to catastrophic (possibly leaving behind a corrupt resource). It is up to the provider to make a
|
|
// best effort to ensure catastrophes do not occur. The errors returned from mutating operations indicate both the
|
|
// underlying error condition in addition to a bit indicating whether the operation was successfully rolled back.
|
|
type Provider interface {
|
|
// Closer closes any underlying OS resources associated with this provider (like processes, RPC channels, etc).
|
|
io.Closer
|
|
// Pkg fetches this provider's package.
|
|
Pkg() tokens.Package
|
|
// Configure configures the resource provider with "globals" that control its behavior.
|
|
Configure(vars map[tokens.ModuleMember]string) error
|
|
// Check validates that the given property bag is valid for a resource of the given type and returns the inputs
|
|
// that should be passed to successive calls to Diff, Create, or Update for this resource.
|
|
Check(urn resource.URN, olds, news resource.PropertyMap) (resource.PropertyMap, []CheckFailure, error)
|
|
// Diff checks what impacts a hypothetical update will have on the resource's properties.
|
|
Diff(urn resource.URN, id resource.ID, olds resource.PropertyMap, news resource.PropertyMap) (DiffResult, error)
|
|
// Create allocates a new instance of the provided resource and returns its unique resource.ID.
|
|
Create(urn resource.URN, news resource.PropertyMap) (resource.ID, resource.PropertyMap, resource.Status, error)
|
|
// Update updates an existing resource with new values.
|
|
Update(urn resource.URN, id resource.ID,
|
|
olds resource.PropertyMap, news resource.PropertyMap) (resource.PropertyMap, resource.Status, error)
|
|
// Delete tears down an existing resource.
|
|
Delete(urn resource.URN, id resource.ID, props resource.PropertyMap) (resource.Status, error)
|
|
// Invoke dynamically executes a built-in function in the provider.
|
|
Invoke(tok tokens.ModuleMember, args resource.PropertyMap) (resource.PropertyMap, []CheckFailure, error)
|
|
// GetPluginInfo returns this plugin's information.
|
|
GetPluginInfo() (Info, error)
|
|
}
|
|
|
|
// CheckFailure indicates that a call to check failed; it contains the property and reason for the failure.
|
|
type CheckFailure struct {
|
|
Property resource.PropertyKey // the property that failed checking.
|
|
Reason string // the reason the property failed to check.
|
|
}
|
|
|
|
// DiffResult indicates whether an operation should replace or update an existing resource.
|
|
type DiffResult struct {
|
|
ReplaceKeys []resource.PropertyKey // an optional list of replacement keys.
|
|
StableKeys []resource.PropertyKey // an optional list of property keys that are stable.
|
|
}
|
|
|
|
// Replace returns true if this diff represents a replacement.
|
|
func (r DiffResult) Replace() bool {
|
|
return len(r.ReplaceKeys) > 0
|
|
}
|