mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-19 17:59:05 -05:00
Try some weird hacks
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -68,6 +69,14 @@ func main() {
|
||||
func realMain() int {
|
||||
defer logging.PanicHandler()
|
||||
|
||||
f, err := os.Create("./profile")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
|
||||
ctx, err := tracing.OpenTelemetryInit(context.Background())
|
||||
if err != nil {
|
||||
// openTelemetryInit can only fail if OpenTofu was run with an
|
||||
|
||||
@@ -102,18 +102,21 @@ func (g *AcyclicGraph) TransitiveReduction() {
|
||||
// v such that the edge (u,v) exists (v is a direct descendant of u).
|
||||
//
|
||||
// For each v-prime reachable from v, remove the edge (u, v-prime).
|
||||
removed := 0
|
||||
for _, u := range g.Vertices() {
|
||||
uTargets := g.downEdgesNoCopy(u)
|
||||
|
||||
g.DepthFirstWalk(g.downEdgesNoCopy(u), func(v Vertex, d int) error {
|
||||
shared := uTargets.Intersection(g.downEdgesNoCopy(v))
|
||||
for _, vPrime := range shared {
|
||||
removed += 1
|
||||
g.RemoveEdge(BasicEdge(u, vPrime))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
println(removed)
|
||||
}
|
||||
|
||||
// Validate validates the DAG. A DAG is valid if it has a single root
|
||||
|
||||
@@ -327,7 +327,7 @@ func (s *Scope) evalContext(parent *hcl.EvalContext, refs []*addrs.Reference, se
|
||||
// Calling NewChild() on a nil parent will
|
||||
// produce an EvalContext with no parent.
|
||||
ctx := parent.NewChild()
|
||||
ctx.Functions = make(map[string]function.Function)
|
||||
ctx.Functions = make(map[string]function.Function, len(s.Functions()))
|
||||
ctx.Variables = make(map[string]cty.Value)
|
||||
|
||||
for name, fn := range s.Functions() {
|
||||
|
||||
@@ -245,7 +245,7 @@ func performSetValueChecks(expr hcl.Expression, hclCtx *hcl.EvalContext, forEach
|
||||
|
||||
// markSafeLengthInt allows calling LengthInt on marked values safely
|
||||
func markSafeLengthInt(val cty.Value) int {
|
||||
v, _ := val.UnmarkDeep()
|
||||
v, _ := val.Unmark()
|
||||
return v.LengthInt()
|
||||
}
|
||||
|
||||
|
||||
@@ -28,11 +28,19 @@ var impureFunctions = []string{
|
||||
// This should probably be replaced with addrs.Function everywhere
|
||||
const CoreNamespace = addrs.FunctionNamespaceCore + "::"
|
||||
|
||||
var hack map[string]function.Function
|
||||
|
||||
// Functions returns the set of functions that should be used to when evaluating
|
||||
// expressions in the receiving scope.
|
||||
func (s *Scope) Functions() map[string]function.Function {
|
||||
s.funcsLock.Lock()
|
||||
defer s.funcsLock.Unlock()
|
||||
if s.funcs == nil {
|
||||
if hack != nil {
|
||||
s.funcs = hack
|
||||
return hack
|
||||
}
|
||||
|
||||
s.funcs = makeBaseFunctionTable(s.BaseDir)
|
||||
if s.ConsoleMode {
|
||||
// The type function is only available in OpenTofu console.
|
||||
@@ -64,8 +72,8 @@ func (s *Scope) Functions() map[string]function.Function {
|
||||
for _, name := range coreNames {
|
||||
s.funcs[CoreNamespace+name] = s.funcs[name]
|
||||
}
|
||||
hack = s.funcs
|
||||
}
|
||||
s.funcsLock.Unlock()
|
||||
|
||||
return s.funcs
|
||||
}
|
||||
|
||||
@@ -175,6 +175,21 @@ func ExtractDeprecatedDiagnosticsWithExpr(val cty.Value, expr hcl.Expression) (c
|
||||
}
|
||||
|
||||
func unmarkDeepWithPathsDeprecated(val cty.Value) (cty.Value, []cty.PathValueMarks) {
|
||||
// quick check for marks
|
||||
containsMark := false
|
||||
_ = cty.Walk(val, func(p cty.Path, v cty.Value) (bool, error) {
|
||||
for m := range v.Marks() {
|
||||
if _, ok := m.(deprecationMark); ok {
|
||||
containsMark = true
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
})
|
||||
|
||||
if !containsMark {
|
||||
return val, nil
|
||||
}
|
||||
unmarked, pathMarks := val.UnmarkDeepWithPaths()
|
||||
|
||||
var deprecationMarks []cty.PathValueMarks
|
||||
|
||||
@@ -925,9 +925,12 @@ func (n *NodeAbstractResourceInstance) plan(
|
||||
}
|
||||
|
||||
// Evaluate the configuration
|
||||
forEach, _ := evaluateForEachExpression(n.Config.ForEach, ctx, n.Addr)
|
||||
/*forEach, _ := evaluateForEachExpression(n.Config.ForEach, ctx, n.Addr)
|
||||
|
||||
keyData = EvalDataForInstanceKey(n.ResourceInstanceAddr().Resource.Key, forEach)
|
||||
keyData = EvalDataForInstanceKey(n.ResourceInstanceAddr().Resource.Key, forEach)*/
|
||||
if n.Addr.Resource.Key != nil {
|
||||
keyData = ctx.InstanceExpander().GetResourceInstanceRepetitionData(n.Addr)
|
||||
}
|
||||
|
||||
checkDiags := evalCheckRules(
|
||||
addrs.ResourcePrecondition,
|
||||
|
||||
32
internal/tofu/node_resource_hack.go
Normal file
32
internal/tofu/node_resource_hack.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package tofu
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/opentofu/opentofu/internal/addrs"
|
||||
"github.com/opentofu/opentofu/internal/tfdiags"
|
||||
)
|
||||
|
||||
type NodeResourceHack struct {
|
||||
NodeAbstractResource
|
||||
}
|
||||
|
||||
var (
|
||||
_ GraphNodeExecutable = (*NodeResourceHack)(nil)
|
||||
_ GraphNodeReferenceable = (*NodeResourceHack)(nil)
|
||||
)
|
||||
|
||||
func (n *NodeResourceHack) Name() string {
|
||||
return n.Addr.String() + " (HACK)"
|
||||
}
|
||||
|
||||
func (n *NodeResourceHack) ReferenceableAddrs() []addrs.Referenceable {
|
||||
return []addrs.Referenceable{
|
||||
n.Addr.Resource,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NodeResourceHack) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
|
||||
println("HACK THE PLANET")
|
||||
return nil
|
||||
}
|
||||
@@ -84,6 +84,8 @@ func (t *DiffTransformer) Transform(_ context.Context, g *Graph) error {
|
||||
resourceNodes[addr] = append(resourceNodes[addr], rn)
|
||||
}
|
||||
|
||||
resourceRoots := map[string]dag.Vertex{}
|
||||
|
||||
for _, rc := range changes.Resources {
|
||||
addr := rc.Addr
|
||||
dk := rc.DeposedKey
|
||||
@@ -208,6 +210,15 @@ func (t *DiffTransformer) Transform(_ context.Context, g *Graph) error {
|
||||
for _, rsrcNode := range resourceNodes[rsrcAddr] {
|
||||
g.Connect(dag.BasicEdge(node, rsrcNode))
|
||||
}
|
||||
|
||||
root, ok := resourceRoots[rsrcAddr]
|
||||
if !ok {
|
||||
root = &NodeResourceHack{abstract.NodeAbstractResource}
|
||||
g.Add(root)
|
||||
resourceRoots[rsrcAddr] = root
|
||||
}
|
||||
g.Connect(dag.BasicEdge(root, node))
|
||||
|
||||
}
|
||||
|
||||
if delete {
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/opentofu/opentofu/internal/configs/configschema"
|
||||
"github.com/opentofu/opentofu/internal/dag"
|
||||
"github.com/opentofu/opentofu/internal/lang"
|
||||
"github.com/opentofu/opentofu/internal/logging"
|
||||
)
|
||||
|
||||
// GraphNodeReferenceable must be implemented by any node that represents
|
||||
@@ -120,7 +121,7 @@ type ReferenceTransformer struct{}
|
||||
func (t *ReferenceTransformer) Transform(_ context.Context, g *Graph) error {
|
||||
// Build a reference map so we can efficiently look up the references
|
||||
vs := g.Vertices()
|
||||
m := NewReferenceMap(vs)
|
||||
m := NewReferenceMap(g)
|
||||
|
||||
// Find the things that reference things and connect them
|
||||
for _, v := range vs {
|
||||
@@ -131,13 +132,15 @@ func (t *ReferenceTransformer) Transform(_ context.Context, g *Graph) error {
|
||||
}
|
||||
|
||||
parents := m.References(v)
|
||||
parentsDbg := make([]string, len(parents))
|
||||
for i, v := range parents {
|
||||
parentsDbg[i] = dag.VertexName(v)
|
||||
if logging.IsDebugOrHigher() {
|
||||
parentsDbg := make([]string, len(parents))
|
||||
for i, v := range parents {
|
||||
parentsDbg[i] = dag.VertexName(v)
|
||||
}
|
||||
log.Printf(
|
||||
"[DEBUG] ReferenceTransformer: %q references: %v",
|
||||
dag.VertexName(v), parentsDbg)
|
||||
}
|
||||
log.Printf(
|
||||
"[DEBUG] ReferenceTransformer: %q references: %v",
|
||||
dag.VertexName(v), parentsDbg)
|
||||
|
||||
for _, parent := range parents {
|
||||
// A destroy plan relies solely on the state, so we only need to
|
||||
@@ -191,7 +194,7 @@ func (t attachDataResourceDependsOnTransformer) Transform(_ context.Context, g *
|
||||
// This is very similar to what's done in ReferenceTransformer, but we keep
|
||||
// implementation separate as they may need to change independently.
|
||||
vertices := g.Vertices()
|
||||
refMap := NewReferenceMap(vertices)
|
||||
refMap := NewReferenceMap(g)
|
||||
|
||||
for _, v := range vertices {
|
||||
depender, ok := v.(graphNodeAttachDataResourceDependsOn)
|
||||
@@ -312,6 +315,9 @@ func (m ReferenceMap) References(v dag.Vertex) []dag.Vertex {
|
||||
}
|
||||
}
|
||||
|
||||
//var resources []dag.Vertex
|
||||
//var resourceInstances []dag.Vertex
|
||||
|
||||
for _, ref := range rn.References() {
|
||||
matches = append(matches, m.addReference(vertexReferencePath(v), v, ref)...)
|
||||
}
|
||||
@@ -357,6 +363,7 @@ func (m ReferenceMap) addReference(path addrs.Module, current dag.Vertex, ref *a
|
||||
}
|
||||
matches = append(matches, rv)
|
||||
}
|
||||
|
||||
return matches
|
||||
}
|
||||
|
||||
@@ -558,7 +565,9 @@ func (m *ReferenceMap) referenceMapKey(referrer dag.Vertex, addr addrs.Reference
|
||||
|
||||
// NewReferenceMap is used to create a new reference map for the
|
||||
// given set of vertices.
|
||||
func NewReferenceMap(vs []dag.Vertex) ReferenceMap {
|
||||
func NewReferenceMap(g *Graph) ReferenceMap {
|
||||
vs := g.Vertices()
|
||||
|
||||
// Build the lookup table
|
||||
m := make(ReferenceMap)
|
||||
for _, v := range vs {
|
||||
@@ -577,6 +586,32 @@ func NewReferenceMap(vs []dag.Vertex) ReferenceMap {
|
||||
}
|
||||
}
|
||||
|
||||
for key, val := range m {
|
||||
if len(val) == 1 {
|
||||
continue
|
||||
}
|
||||
println(key)
|
||||
// Locate root
|
||||
var potentialRoots []dag.Vertex
|
||||
|
||||
for _, vr := range val {
|
||||
if _, ok := vr.(*NodeResourceHack); ok {
|
||||
potentialRoots = append(potentialRoots, vr)
|
||||
}
|
||||
}
|
||||
println(len(potentialRoots))
|
||||
if len(potentialRoots) == 1 {
|
||||
println("OVERRIDE")
|
||||
m[key] = potentialRoots
|
||||
/*parent := potentialRoots[0]
|
||||
for _, v := range val {
|
||||
if v != parent {
|
||||
g.Connect(dag.BasicEdge(v, parent))
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user