// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package stackstate import ( "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/collections" "github.com/hashicorp/terraform/internal/stacks/stackaddrs" "github.com/hashicorp/terraform/internal/states" ) // StateBuilder wraps State, and provides some write-only methods to update the // state. // // This is generally used to build up a new state from scratch during tests. type StateBuilder struct { state *State } func NewStateBuilder() *StateBuilder { return &StateBuilder{ state: NewState(), } } // Build returns the state and invalidates the StateBuilder. // // You will get nil pointer exceptions if you attempt to use the builder after // calling Build. func (s *StateBuilder) Build() *State { ret := s.state s.state = nil return ret } // AddResourceInstance adds a resource instance to the state. func (s *StateBuilder) AddResourceInstance(builder *ResourceInstanceBuilder) *StateBuilder { if builder.addr == nil || builder.src == nil || builder.providerAddr == nil { panic("ResourceInstanceBuilder is missing required fields") } s.state.addResourceInstanceObject(*builder.addr, builder.src, *builder.providerAddr) return s } // AddComponentInstance adds a component instance to the state. func (s *StateBuilder) AddComponentInstance(builder *ComponentInstanceBuilder) *StateBuilder { component := s.state.ensureComponentInstanceState(builder.addr) component.outputValues = builder.outputValues component.inputVariables = builder.inputVariables for dep := range builder.dependencies.All() { component.dependencies.Add(dep) } for dep := range builder.dependents.All() { component.dependents.Add(dep) } return s } // AddOutput adds an output to the state. func (s *StateBuilder) AddOutput(name string, value cty.Value) *StateBuilder { s.state.outputs[stackaddrs.OutputValue{Name: name}] = value return s } // AddInput adds an input variable to the state. func (s *StateBuilder) AddInput(name string, value cty.Value) *StateBuilder { s.state.inputs[stackaddrs.InputVariable{Name: name}] = value return s } type ResourceInstanceBuilder struct { addr *stackaddrs.AbsResourceInstanceObject src *states.ResourceInstanceObjectSrc providerAddr *addrs.AbsProviderConfig } func NewResourceInstanceBuilder() *ResourceInstanceBuilder { return &ResourceInstanceBuilder{} } func (b *ResourceInstanceBuilder) SetAddr(addr stackaddrs.AbsResourceInstanceObject) *ResourceInstanceBuilder { b.addr = &addr return b } func (b *ResourceInstanceBuilder) SetResourceInstanceObjectSrc(src states.ResourceInstanceObjectSrc) *ResourceInstanceBuilder { b.src = &src return b } func (b *ResourceInstanceBuilder) SetProviderAddr(addr addrs.AbsProviderConfig) *ResourceInstanceBuilder { b.providerAddr = &addr return b } type ComponentInstanceBuilder struct { addr stackaddrs.AbsComponentInstance dependencies collections.Set[stackaddrs.AbsComponent] dependents collections.Set[stackaddrs.AbsComponent] outputValues map[addrs.OutputValue]cty.Value inputVariables map[addrs.InputVariable]cty.Value } func NewComponentInstanceBuilder(instance stackaddrs.AbsComponentInstance) *ComponentInstanceBuilder { return &ComponentInstanceBuilder{ addr: instance, dependencies: collections.NewSet[stackaddrs.AbsComponent](), dependents: collections.NewSet[stackaddrs.AbsComponent](), outputValues: make(map[addrs.OutputValue]cty.Value), inputVariables: make(map[addrs.InputVariable]cty.Value), } } func (b *ComponentInstanceBuilder) AddDependency(addr stackaddrs.AbsComponent) *ComponentInstanceBuilder { b.dependencies.Add(addr) return b } func (b *ComponentInstanceBuilder) AddDependent(addr stackaddrs.AbsComponent) *ComponentInstanceBuilder { b.dependents.Add(addr) return b } func (b *ComponentInstanceBuilder) AddOutputValue(name string, value cty.Value) *ComponentInstanceBuilder { b.outputValues[addrs.OutputValue{Name: name}] = value return b } func (b *ComponentInstanceBuilder) AddInputVariable(name string, value cty.Value) *ComponentInstanceBuilder { b.inputVariables[addrs.InputVariable{Name: name}] = value return b }