MCPcopy
hub / github.com/opentofu/opentofu / ApplyMoves

Function ApplyMoves

internal/refactoring/move_execute.go:33–193  ·  view source on GitHub ↗

ApplyMoves modifies in-place the given state object so that any existing objects that are matched by a "from" argument of one of the move statements will be moved to instead appear at the "to" argument of that statement. The result is a map from the unique key of each absolute address that was eith

(stmts []MoveStatement, state *states.State)

Source from the content-addressed store, hash-verified

31// ApplyMoves expects exclusive access to the given state while it's running.
32// Don't read or write any part of the state structure until ApplyMoves returns.
33func ApplyMoves(stmts []MoveStatement, state *states.State) MoveResults {
34 ret := makeMoveResults()
35
36 if len(stmts) == 0 {
37 return ret
38 }
39
40 // The methodology here is to construct a small graph of all of the move
41 // statements where the edges represent where a particular statement
42 // is either chained from or nested inside the effect of another statement.
43 // That then means we can traverse the graph in topological sort order
44 // to gradually move objects through potentially multiple moves each.
45
46 g := buildMoveStatementGraph(stmts)
47
48 // If the graph is not valid the we will not take any action at all. The
49 // separate validation step should detect this and return an error.
50 if diags := validateMoveStatementGraph(g); diags.HasErrors() {
51 log.Printf("[ERROR] ApplyMoves: %s", diags.ErrWithWarnings())
52 return ret
53 }
54
55 // The graph must be reduced in order for ReverseDepthFirstWalk to work
56 // correctly, since it is built from following edges and can skip over
57 // dependencies if there is a direct edge to a transitive dependency.
58 g.TransitiveReduction()
59
60 // The starting nodes are the ones that don't depend on any other nodes.
61 startNodes := make(dag.Set, len(stmts))
62 for _, v := range g.Vertices() {
63 if len(g.DownEdges(v)) == 0 {
64 startNodes.Add(v)
65 }
66 }
67
68 if startNodes.Len() == 0 {
69 log.Println("[TRACE] refactoring.ApplyMoves: No 'moved' statements to consider in this configuration")
70 return ret
71 }
72
73 log.Printf("[TRACE] refactoring.ApplyMoves: Processing 'moved' statements in the configuration\n%s", logging.Indent(g.String()))
74
75 recordOldAddr := func(oldAddr, newAddr addrs.AbsResourceInstance) {
76 if prevMove, exists := ret.Changes.GetOk(oldAddr); exists {
77 // If the old address was _already_ the result of a move then
78 // we'll replace that entry so that our results summarize a chain
79 // of moves into a single entry.
80 ret.Changes.Remove(oldAddr)
81 oldAddr = prevMove.From
82 }
83 ret.Changes.Put(newAddr, MoveSuccess{
84 From: oldAddr,
85 To: newAddr,
86 })
87 }
88 recordBlockage := func(newAddr, wantedAddr addrs.AbsMoveable) {
89 ret.Blocked.Put(newAddr, MoveBlocked{
90 Wanted: wantedAddr,

Callers 2

TestApplyMovesFunction · 0.85

Calls 15

IndentFunction · 0.92
makeMoveResultsFunction · 0.85
buildMoveStatementGraphFunction · 0.85
HasErrorsMethod · 0.80
PrintfMethod · 0.80
ErrWithWarningsMethod · 0.80
TransitiveReductionMethod · 0.80
VerticesMethod · 0.80
DownEdgesMethod · 0.80
PrintlnMethod · 0.80

Tested by 1

TestApplyMovesFunction · 0.68