Adds/Deletes/Updates

This commit is contained in:
Fraser Waters 2021-11-16 16:26:51 +00:00
parent 40400b664b
commit 3b9cf5b648
4 changed files with 69 additions and 13 deletions

View file

@ -41,6 +41,32 @@ type GoalPlan struct {
CustomTimeouts resource.CustomTimeouts // an optional config object for resource options
}
func NewGoalPlan(oldOutputs resource.PropertyMap, goal *resource.Goal) *GoalPlan {
if goal == nil {
return nil
}
return &GoalPlan{
Type: goal.Type,
Name: goal.Name,
Custom: goal.Custom,
Adds: nil,
Deletes: nil,
Updates: nil,
Parent: goal.Parent,
Protect: goal.Protect,
Dependencies: goal.Dependencies,
Provider: goal.Provider,
PropertyDependencies: goal.PropertyDependencies,
DeleteBeforeReplace: goal.DeleteBeforeReplace,
IgnoreChanges: goal.IgnoreChanges,
AdditionalSecretOutputs: goal.AdditionalSecretOutputs,
Aliases: goal.Aliases,
ID: goal.ID,
CustomTimeouts: goal.CustomTimeouts,
}
}
// A ResourcePlan represents the planned goal state and resource operations for a single resource. The operations are
// ordered.
type ResourcePlan struct {
@ -119,7 +145,11 @@ func (rp *ResourcePlan) diffPropertyDependencies(a, b map[resource.PropertyKey][
return nil
}
func (rp *ResourcePlan) checkGoal(oldOutputs resource.PropertyMap, newInputs resource.PropertyMap, programGoal *resource.Goal) error {
func (rp *ResourcePlan) checkGoal(
oldOutputs resource.PropertyMap,
newInputs resource.PropertyMap,
programGoal *resource.Goal) error {
contract.Assert(programGoal != nil)
contract.Assert(newInputs != nil)
// rp.Goal may be nil, but if it isn't Type and Name should match

View file

@ -155,7 +155,7 @@ func (sg *stepGenerator) GenerateSteps(event RegisterResourceEvent) ([]Step, res
return nil, res
}
// Check each proposed step against the relevant resource plan, if any, and generate any output resource plans.
// Check each proposed step against the relevant resource plan, if any
for _, s := range steps {
if sg.deployment.plan != nil {
if resourcePlan, ok := sg.deployment.plan[s.URN()]; ok {
@ -175,10 +175,7 @@ func (sg *stepGenerator) GenerateSteps(event RegisterResourceEvent) ([]Step, res
resourcePlan, ok := sg.deployment.newPlans.get(s.URN())
if !ok {
// TODO(pdg-plan): using the program inputs means that non-determinism could sneak in as part of default
// application. However, it is necessary in the face of computed inputs.
resourcePlan = &ResourcePlan{Goal: event.Goal()}
sg.deployment.newPlans.set(s.URN(), resourcePlan)
return nil, result.Errorf("Expected a new resource plan for %v", s.URN())
}
resourcePlan.Ops = append(resourcePlan.Ops, s.Op())
}
@ -276,6 +273,12 @@ func (sg *stepGenerator) generateSteps(event RegisterResourceEvent) ([]Step, res
inputs = processedInputs
}
// Generate the output goal plan
// TODO(pdg-plan): using the program inputs means that non-determinism could sneak in as part of default
// application. However, it is necessary in the face of computed inputs.
newResourcePlan := &ResourcePlan{Goal: NewGoalPlan(oldOutputs, goal)}
sg.deployment.newPlans.set(urn, newResourcePlan)
// If there is a plan for this resource, validate that the program goal conforms to the plan.
if sg.deployment.plan != nil {
resourcePlan, ok := sg.deployment.plan[urn]

View file

@ -12,11 +12,21 @@ func SerializeResourcePlan(
enc config.Encrypter,
showSecrets bool) (apitype.ResourcePlanV1, error) {
properties, err := SerializeProperties(plan.Goal.Properties, enc, showSecrets)
adds, err := SerializeProperties(plan.Goal.Adds, enc, showSecrets)
if err != nil {
return apitype.ResourcePlanV1{}, err
}
updates, err := SerializeProperties(plan.Goal.Adds, enc, showSecrets)
if err != nil {
return apitype.ResourcePlanV1{}, err
}
deletes := make([]string, len(plan.Goal.Deletes))
for i := range deletes {
deletes[i] = string(plan.Goal.Deletes[i])
}
var outputs map[string]interface{}
if plan.Outputs != nil {
outs, err := SerializeProperties(plan.Outputs, enc, showSecrets)
@ -30,7 +40,9 @@ func SerializeResourcePlan(
Type: plan.Goal.Type,
Name: plan.Goal.Name,
Custom: plan.Goal.Custom,
Properties: properties,
Adds: adds,
Deletes: deletes,
Updates: updates,
Parent: plan.Goal.Parent,
Protect: plan.Goal.Protect,
Dependencies: plan.Goal.Dependencies,
@ -73,7 +85,12 @@ func DeserializeResourcePlan(
dec config.Decrypter,
enc config.Encrypter) (*deploy.ResourcePlan, error) {
properties, err := DeserializeProperties(plan.Goal.Properties, dec, enc)
adds, err := DeserializeProperties(plan.Goal.Adds, dec, enc)
if err != nil {
return nil, err
}
updates, err := DeserializeProperties(plan.Goal.Updates, dec, enc)
if err != nil {
return nil, err
}
@ -87,11 +104,13 @@ func DeserializeResourcePlan(
outputs = outs
}
goal := &resource.Goal{
goal := &deploy.GoalPlan{
Type: plan.Goal.Type,
Name: plan.Goal.Name,
Custom: plan.Goal.Custom,
Properties: properties,
Adds: adds,
Deletes: nil,
Updates: updates,
Parent: plan.Goal.Parent,
Protect: plan.Goal.Protect,
Dependencies: plan.Goal.Dependencies,

View file

@ -15,8 +15,12 @@ type GoalV1 struct {
Name tokens.QName `json:"name"`
// true if this resource is custom, managed by a plugin.
Custom bool `json:"custom"`
// the resource's input properties.
Properties map[string]interface{} `json:"properties,omitempty"`
// the resource properties that will be added.
Adds map[string]interface{} `json:"adds,omitempty"`
// the resource properties that will be deleted.
Deletes []string `json:"deletes,omitempty"`
// the resource properties that will be updated.
Updates map[string]interface{} `json:"updates,omitempty"`
// an optional parent URN for this resource.
Parent resource.URN `json:"parent,omitempty"`
// true to protect this resource from deletion.