pulumi/pkg/resource/deploy/state_builder.go

128 lines
3.2 KiB
Go

// Copyright 2016-2022, 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 deploy
import (
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
)
// Simplifies non-mutating edits on resource.State
type stateBuilder struct {
state resource.State
original *resource.State
edited bool
}
func newStateBuilder(state *resource.State) *stateBuilder {
return &stateBuilder{*(state.Copy()), state, false}
}
func (sb *stateBuilder) withUpdatedURN(update func(resource.URN) resource.URN) *stateBuilder {
sb.setURN(&sb.state.URN, update(sb.state.URN))
return sb
}
func (sb *stateBuilder) withUpdatedParent(update func(resource.URN) resource.URN) *stateBuilder {
if sb.state.Parent != "" {
sb.setURN(&sb.state.Parent, update(sb.state.Parent))
}
return sb
}
func (sb *stateBuilder) withUpdatedProvider(update func(string) string) *stateBuilder {
if sb.state.Provider != "" {
sb.setString(&sb.state.Provider, update(sb.state.Provider))
}
return sb
}
func (sb *stateBuilder) withUpdatedDependencies(update func(resource.URN) resource.URN) *stateBuilder {
var edited bool
edited, sb.state.Dependencies = sb.updateURNSlice(sb.state.Dependencies, update)
sb.edited = sb.edited || edited
return sb
}
func (sb *stateBuilder) withUpdatedPropertyDependencies(update func(resource.URN) resource.URN) *stateBuilder {
m := map[resource.PropertyKey][]resource.URN{}
edited := false
for k, urns := range sb.state.PropertyDependencies {
var edit bool
edit, m[k] = sb.updateURNSlice(urns, update)
edited = edited || edit
}
if edited {
sb.state.PropertyDependencies = m
}
sb.edited = sb.edited || edited
return sb
}
// Removes all "Aliases" from the state. Once URN normalisation is done we don't want to write aliases out.
func (sb *stateBuilder) withUpdatedAliases() *stateBuilder {
if len(sb.state.Aliases) > 0 {
sb.state.Aliases = nil
sb.edited = true
}
return sb
}
func (sb *stateBuilder) build() *resource.State {
if !sb.edited {
return sb.original
}
return &sb.state
}
// internal
func (sb *stateBuilder) setString(loc *string, value string) {
if *loc == value {
return
}
sb.edited = true
*loc = value
}
// internal
func (sb *stateBuilder) setURN(loc *resource.URN, value resource.URN) {
if *loc == value {
return
}
sb.edited = true
*loc = value
}
// internal
func (sb *stateBuilder) updateURNSlice(
slice []resource.URN,
update func(resource.URN) resource.URN,
) (bool, []resource.URN) {
needsUpdate := false
for _, urn := range slice {
if update(urn) != urn {
needsUpdate = true
break
}
}
if !needsUpdate {
return false, slice
}
updated := make([]resource.URN, len(slice))
for i, urn := range slice {
updated[i] = update(urn)
}
return true, updated
}