Share target checking code. (#3252)

This commit is contained in:
CyrusNajmabadi 2019-09-20 17:50:44 -07:00 committed by GitHub
parent c1ff9c37f8
commit ef7b7d0bd1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 63 deletions

View file

@ -59,24 +59,15 @@ func GetDuplicateResourceAliasError(urn resource.URN) *Diag {
)
}
func GetResourceToRefreshCouldNotBeFoundError() *Diag {
return newError("", 2010, "Resource to refresh '%v' could not be found in the stack.")
func GetTargetCouldNotBeFoundError() *Diag {
return newError("", 2010, "Target '%v' could not be found in the stack.")
}
func GetResourceToRefreshCouldNotBeFoundDidYouForgetError() *Diag {
return newError("", 2011, "Resource to refresh '%v' could not be found in the stack. "+
"Did you forget to escape $ in your shell?")
}
func GetResourceToDeleteCouldNotBeFoundError() *Diag {
return newError("", 2012, "Resource to delete '%v' could not be found in the stack.")
}
func GetResourceToDeleteCouldNotBeFoundDidYouForgetError() *Diag {
return newError("", 2013, "Resource to delete '%v' could not be found in the stack. "+
func GetTargetCouldNotBeFoundDidYouForgetError() *Diag {
return newError("", 2011, "Target '%v' could not be found in the stack. "+
"Did you forget to escape $ in your shell?")
}
func GetCannotDeleteParentResourceWithoutAlsoDeletingChildError() *Diag {
return newError("", 2014, "Cannot delete parent resource '%v' without also deleting child '%v'.")
return newError("", 2012, "Cannot delete parent resource '%v' without also deleting child '%v'.")
}

View file

@ -17,6 +17,7 @@ package deploy
import (
"context"
"math"
"strings"
"github.com/blang/semver"
"github.com/pkg/errors"
@ -29,6 +30,7 @@ import (
"github.com/pulumi/pulumi/pkg/resource/plugin"
"github.com/pulumi/pulumi/pkg/tokens"
"github.com/pulumi/pulumi/pkg/util/contract"
"github.com/pulumi/pulumi/pkg/util/logging"
"github.com/pulumi/pulumi/pkg/util/result"
)
@ -331,3 +333,37 @@ func (p *Plan) Execute(ctx context.Context, opts Options, preview bool) result.R
planExec := &planExecutor{plan: p}
return planExec.Execute(ctx, opts, preview)
}
// CheckTargets validates that all the targets passed in refer to existing resources. Diagnostics
// are generated for any target that cannot be found.
//
// A map is returned of all the target URNs to facilitate later callers. The map can be 'nil'
// indicating no targets, or will be non-nil and non-empty if there are targets.
func (p *Plan) CheckTargets(targets []resource.URN) (map[resource.URN]bool, result.Result) {
if len(targets) == 0 {
return nil, nil
}
targetMap := make(map[resource.URN]bool)
// Do an initial pass first to ensure that all the targets mentioned are ones we know about.
hasUnknownTarget := false
for _, target := range targets {
if _, has := p.olds[target]; !has {
hasUnknownTarget = true
logging.V(7).Infof("Resource to delete (%v) could not be found in the stack.", target)
if strings.Contains(string(target), "$") {
p.Diag().Errorf(diag.GetTargetCouldNotBeFoundError(), target)
} else {
p.Diag().Errorf(diag.GetTargetCouldNotBeFoundDidYouForgetError(), target)
}
}
targetMap[target] = true
}
if hasUnknownTarget {
return nil, result.Bail()
}
return targetMap, nil
}

View file

@ -16,7 +16,6 @@ package deploy
import (
"context"
"strings"
"github.com/pkg/errors"
"github.com/pulumi/pulumi/pkg/diag"
@ -322,17 +321,10 @@ func (pe *planExecutor) refresh(callerCtx context.Context, opts Options, preview
return nil
}
if len(opts.RefreshTargets) > 0 {
for _, target := range opts.RefreshTargets {
if _, has := pe.plan.olds[target]; !has {
if strings.Contains(string(target), "$") {
pe.plan.Diag().Errorf(diag.GetResourceToRefreshCouldNotBeFoundError(), target)
} else {
pe.plan.Diag().Errorf(diag.GetResourceToRefreshCouldNotBeFoundDidYouForgetError(), target)
}
return result.Bail()
}
}
// Make sure if there were any targets specified, that they all refer to existing resources.
targetMapOpt, res := pe.plan.CheckTargets(opts.RefreshTargets)
if res != nil {
return res
}
// If the user did not provide any --target's, create a refresh step for each resource in the
@ -341,7 +333,7 @@ func (pe *planExecutor) refresh(callerCtx context.Context, opts Options, preview
steps := []Step{}
resourceToStep := map[*resource.State]Step{}
for _, res := range prev.Resources {
if shouldRefresh(opts, res) {
if targetMapOpt == nil || targetMapOpt[res.URN] {
step := NewRefreshStep(pe.plan, res, nil)
steps = append(steps, step)
resourceToStep[res] = step
@ -449,18 +441,3 @@ func (pe *planExecutor) rebuildBaseState(resourceToStep map[*resource.State]Step
pe.plan.prev.Resources = resources
pe.plan.olds, pe.plan.depGraph = olds, graph.NewDependencyGraph(resources)
}
func shouldRefresh(opts Options, res *resource.State) bool {
if len(opts.RefreshTargets) == 0 {
return true
}
//var found = false
for _, urn := range opts.RefreshTargets {
if urn == res.URN {
return true
}
}
return false
}

View file

@ -97,7 +97,7 @@ func (sg *stepGenerator) GenerateReadSteps(event ReadResourceEvent) ([]Step, res
// we do not need to delete the resource - we know exactly what resource we are going
// to get from the read.
//
// This operation is tenatively called "relinquish" - it semantically represents the
// This operation is tentatively called "relinquish" - it semantically represents the
// release of a resource from the management of Pulumi.
if hasOld && !old.External && old.ID != event.ID() {
logging.V(7).Infof(
@ -556,31 +556,19 @@ func (sg *stepGenerator) GenerateDeletes(targets []resource.URN) ([]Step, result
}
}
if len(targets) > 0 {
// Make sure if there were any targets specified, that they all refer to existing resources.
targetMapOpt, res := sg.plan.CheckTargets(targets)
if res != nil {
return nil, res
}
if targetMapOpt != nil {
logging.V(7).Infof("Planner was asked to only delete '%v'", targets)
resourcesToDelete := make(map[resource.URN]bool)
// Do an initial pass first to ensure that all the targets mentioned are ones we know about.
hasUnknownTarget := false
for _, target := range targets {
if _, has := sg.plan.olds[target]; !has {
hasUnknownTarget = true
logging.V(7).Infof("Resource to delete (%v) could not be found in the stack.", target)
if strings.Contains(string(target), "$") {
sg.plan.Diag().Errorf(diag.GetResourceToDeleteCouldNotBeFoundError(), target)
} else {
sg.plan.Diag().Errorf(diag.GetResourceToDeleteCouldNotBeFoundDidYouForgetError(), target)
}
}
}
if hasUnknownTarget {
return nil, result.Bail()
}
// Now actually use all the requested targets to figure out the exact set to delete.
for _, target := range targets {
for target := range targetMapOpt {
current := sg.plan.olds[target]
resourcesToDelete[target] = true