remove unused

This commit is contained in:
James Bardin 2020-11-30 17:48:02 -05:00
parent 1b530b7d9d
commit 1e8537b8d4
10 changed files with 327 additions and 81 deletions

View File

@ -37,17 +37,6 @@ const (
InputModeStd = InputModeProvider InputModeStd = InputModeProvider
) )
var (
// contextFailOnShadowError will cause Context operations to return
// errors when shadow operations fail. This is only used for testing.
contextFailOnShadowError = false
// contextTestDeepCopyOnPlan will perform a Diff DeepCopy on every
// Plan operation, effectively testing the Diff DeepCopy whenever
// a Plan occurs. This is enabled for tests.
contextTestDeepCopyOnPlan = false
)
// ContextOpts are the user-configurable options to create a context with // ContextOpts are the user-configurable options to create a context with
// NewContext. // NewContext.
type ContextOpts struct { type ContextOpts struct {
@ -125,11 +114,9 @@ type Context struct {
parallelSem Semaphore parallelSem Semaphore
providerInputConfig map[string]map[string]cty.Value providerInputConfig map[string]map[string]cty.Value
providerSHA256s map[string][]byte providerSHA256s map[string][]byte
runLock sync.Mutex
runCond *sync.Cond runCond *sync.Cond
runContext context.Context runContext context.Context
runContextCancel context.CancelFunc runContextCancel context.CancelFunc
shadowErr error
} }
// (additional methods on Context can be found in context_*.go files.) // (additional methods on Context can be found in context_*.go files.)
@ -383,33 +370,6 @@ func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, tfdiags.
} }
} }
// ShadowError returns any errors caught during a shadow operation.
//
// A shadow operation is an operation run in parallel to a real operation
// that performs the same tasks using new logic on copied state. The results
// are compared to ensure that the new logic works the same as the old logic.
// The shadow never affects the real operation or return values.
//
// The result of the shadow operation are only available through this function
// call after a real operation is complete.
//
// For API consumers of Context, you can safely ignore this function
// completely if you have no interest in helping report experimental feature
// errors to Terraform maintainers. Otherwise, please call this function
// after every operation and report this to the user.
//
// IMPORTANT: Shadow errors are _never_ critical: they _never_ affect
// the real state or result of a real operation. They are purely informational
// to assist in future Terraform versions being more stable. Please message
// this effectively to the end user.
//
// This must be called only when no other operation is running (refresh,
// plan, etc.). The result can be used in parallel to any other operation
// running.
func (c *Context) ShadowError() error {
return c.shadowErr
}
// State returns a copy of the current state associated with this context. // State returns a copy of the current state associated with this context.
// //
// This cannot safely be called in parallel with any other Context function. // This cannot safely be called in parallel with any other Context function.
@ -748,9 +708,6 @@ func (c *Context) acquireRun(phase string) func() {
// Reset the stop hook so we're not stopped // Reset the stop hook so we're not stopped
c.sh.Reset() c.sh.Reset()
// Reset the shadow errors
c.shadowErr = nil
return c.releaseRun return c.releaseRun
} }

View File

@ -5700,7 +5700,7 @@ func TestContext2Apply_destroyModulePrefix(t *testing.T) {
t.Fatalf("plan errors: %s", diags.Err()) t.Fatalf("plan errors: %s", diags.Err())
} }
state, diags = ctx.Apply() _, diags = ctx.Apply()
if diags.HasErrors() { if diags.HasErrors() {
t.Fatalf("diags: %s", diags.Err()) t.Fatalf("diags: %s", diags.Err())
} }
@ -8049,7 +8049,7 @@ func TestContext2Apply_singleDestroy(t *testing.T) {
} }
h.Active = true h.Active = true
state, diags := ctx.Apply() _, diags := ctx.Apply()
if diags.HasErrors() { if diags.HasErrors() {
t.Fatalf("diags: %s", diags.Err()) t.Fatalf("diags: %s", diags.Err())
} }
@ -8141,7 +8141,7 @@ func TestContext2Apply_issue5254(t *testing.T) {
}, },
}) })
plan, diags := ctx.Plan() _, diags := ctx.Plan()
if diags.HasErrors() { if diags.HasErrors() {
t.Fatalf("err: %s", diags.Err()) t.Fatalf("err: %s", diags.Err())
} }
@ -8162,7 +8162,7 @@ func TestContext2Apply_issue5254(t *testing.T) {
}, },
}) })
plan, diags = ctx.Plan() plan, diags := ctx.Plan()
if diags.HasErrors() { if diags.HasErrors() {
t.Fatalf("err: %s", diags.Err()) t.Fatalf("err: %s", diags.Err())
} }

View File

@ -921,17 +921,6 @@ module.child[0].nested:
provider = provider["registry.terraform.io/hashicorp/aws"] provider = provider["registry.terraform.io/hashicorp/aws"]
` `
const testImportModuleExistingStr = `
<no state>
module.foo:
aws_instance.bar:
ID = bar
provider = provider["registry.terraform.io/hashicorp/aws"]
aws_instance.foo:
ID = foo
provider = provider["registry.terraform.io/hashicorp/aws"]
`
const testImportMultiStr = ` const testImportMultiStr = `
aws_instance.foo: aws_instance.foo:
ID = foo ID = foo

View File

@ -4389,7 +4389,6 @@ func TestContext2Plan_targetedOverTen(t *testing.T) {
state := states.NewState() state := states.NewState()
root := state.EnsureModule(addrs.RootModuleInstance) root := state.EnsureModule(addrs.RootModuleInstance)
var expectedState []string
for i := 0; i < 13; i++ { for i := 0; i < 13; i++ {
key := fmt.Sprintf("aws_instance.foo[%d]", i) key := fmt.Sprintf("aws_instance.foo[%d]", i)
id := fmt.Sprintf("i-abc%d", i) id := fmt.Sprintf("i-abc%d", i)
@ -4403,7 +4402,6 @@ func TestContext2Plan_targetedOverTen(t *testing.T) {
}, },
mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`),
) )
expectedState = append(expectedState, fmt.Sprintf("%s:\n ID = %s\n", key, id))
} }
ctx := testContext2(t, &ContextOpts{ ctx := testContext2(t, &ContextOpts{

View File

@ -1054,18 +1054,6 @@ func logDiagnostics(t *testing.T, diags tfdiags.Diagnostics) {
} }
} }
const testContextGraph = `
root: root
aws_instance.bar
aws_instance.bar -> provider.aws
aws_instance.foo
aws_instance.foo -> provider.aws
provider.aws
root
root -> aws_instance.bar
root -> aws_instance.foo
`
const testContextRefreshModuleStr = ` const testContextRefreshModuleStr = `
aws_instance.web: (tainted) aws_instance.web: (tainted)
ID = bar ID = bar

View File

@ -332,7 +332,6 @@ func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance
args := ctx.VariableValues[key] args := ctx.VariableValues[key]
if args == nil { if args == nil {
args = make(map[string]cty.Value)
ctx.VariableValues[key] = vals ctx.VariableValues[key] = vals
return return
} }

View File

@ -38,8 +38,7 @@ func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics {
ctx := walker.EvalContext() ctx := walker.EvalContext()
// Walk the graph. // Walk the graph.
var walkFn dag.WalkFunc walkFn := func(v dag.Vertex) (diags tfdiags.Diagnostics) {
walkFn = func(v dag.Vertex) (diags tfdiags.Diagnostics) {
log.Printf("[TRACE] vertex %q: starting visit (%T)", dag.VertexName(v), v) log.Printf("[TRACE] vertex %q: starting visit (%T)", dag.VertexName(v), v)
defer func() { defer func() {

9
terraform/graph_dot.go Normal file
View File

@ -0,0 +1,9 @@
package terraform
import "github.com/hashicorp/terraform/dag"
// GraphDot returns the dot formatting of a visual representation of
// the given Terraform graph.
func GraphDot(g *Graph, opts *dag.DotOpts) (string, error) {
return string(g.Dot(opts)), nil
}

313
terraform/graph_dot_test.go Normal file
View File

@ -0,0 +1,313 @@
package terraform
import (
"strings"
"testing"
"github.com/hashicorp/terraform/dag"
)
func TestGraphDot(t *testing.T) {
cases := []struct {
Name string
Graph testGraphFunc
Opts dag.DotOpts
Expect string
Error string
}{
{
Name: "empty",
Graph: func() *Graph { return &Graph{} },
Expect: `
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
}
}`,
},
{
Name: "three-level",
Graph: func() *Graph {
var g Graph
root := &testDrawableOrigin{"root"}
g.Add(root)
levelOne := []interface{}{"foo", "bar"}
for i, s := range levelOne {
levelOne[i] = &testDrawable{
VertexName: s.(string),
}
v := levelOne[i]
g.Add(v)
g.Connect(dag.BasicEdge(v, root))
}
levelTwo := []string{"baz", "qux"}
for i, s := range levelTwo {
v := &testDrawable{
VertexName: s,
}
g.Add(v)
g.Connect(dag.BasicEdge(v, levelOne[i]))
}
return &g
},
Expect: `
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] bar"
"[root] baz"
"[root] foo"
"[root] qux"
"[root] root"
"[root] bar" -> "[root] root"
"[root] baz" -> "[root] foo"
"[root] foo" -> "[root] root"
"[root] qux" -> "[root] bar"
}
}
`,
},
{
Name: "cycle",
Opts: dag.DotOpts{
DrawCycles: true,
},
Graph: func() *Graph {
var g Graph
root := &testDrawableOrigin{"root"}
g.Add(root)
vA := g.Add(&testDrawable{
VertexName: "A",
})
vB := g.Add(&testDrawable{
VertexName: "B",
})
vC := g.Add(&testDrawable{
VertexName: "C",
})
g.Connect(dag.BasicEdge(vA, root))
g.Connect(dag.BasicEdge(vA, vC))
g.Connect(dag.BasicEdge(vB, vA))
g.Connect(dag.BasicEdge(vC, vB))
return &g
},
Expect: `
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] A"
"[root] B"
"[root] C"
"[root] root"
"[root] A" -> "[root] B" [color = "red", penwidth = "2.0"]
"[root] A" -> "[root] C"
"[root] A" -> "[root] root"
"[root] B" -> "[root] A"
"[root] B" -> "[root] C" [color = "red", penwidth = "2.0"]
"[root] C" -> "[root] A" [color = "red", penwidth = "2.0"]
"[root] C" -> "[root] B"
}
}
`,
},
{
Name: "subgraphs, no depth restriction",
Opts: dag.DotOpts{
MaxDepth: -1,
},
Graph: func() *Graph {
var g Graph
root := &testDrawableOrigin{"root"}
g.Add(root)
var sub Graph
vSubRoot := sub.Add(&testDrawableOrigin{"sub_root"})
var subsub Graph
subsub.Add(&testDrawableOrigin{"subsub_root"})
vSubV := sub.Add(&testDrawableSubgraph{
VertexName: "subsub",
SubgraphMock: &subsub,
})
vSub := g.Add(&testDrawableSubgraph{
VertexName: "sub",
SubgraphMock: &sub,
})
g.Connect(dag.BasicEdge(vSub, root))
sub.Connect(dag.BasicEdge(vSubV, vSubRoot))
return &g
},
Expect: `
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] root"
"[root] sub"
"[root] sub" -> "[root] root"
}
subgraph "cluster_sub" {
label = "sub"
"[sub] sub_root"
"[sub] subsub"
"[sub] subsub" -> "[sub] sub_root"
}
subgraph "cluster_subsub" {
label = "subsub"
"[subsub] subsub_root"
}
}
`,
},
{
Name: "subgraphs, with depth restriction",
Opts: dag.DotOpts{
MaxDepth: 1,
},
Graph: func() *Graph {
var g Graph
root := &testDrawableOrigin{"root"}
g.Add(root)
var sub Graph
rootSub := sub.Add(&testDrawableOrigin{"sub_root"})
var subsub Graph
subsub.Add(&testDrawableOrigin{"subsub_root"})
subV := sub.Add(&testDrawableSubgraph{
VertexName: "subsub",
SubgraphMock: &subsub,
})
vSub := g.Add(&testDrawableSubgraph{
VertexName: "sub",
SubgraphMock: &sub,
})
g.Connect(dag.BasicEdge(vSub, root))
sub.Connect(dag.BasicEdge(subV, rootSub))
return &g
},
Expect: `
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] root"
"[root] sub"
"[root] sub" -> "[root] root"
}
subgraph "cluster_sub" {
label = "sub"
"[sub] sub_root"
"[sub] subsub"
"[sub] subsub" -> "[sub] sub_root"
}
}
`,
},
}
for _, tc := range cases {
tn := tc.Name
t.Run(tn, func(t *testing.T) {
g := tc.Graph()
var err error
//actual, err := GraphDot(g, &tc.Opts)
actual := string(g.Dot(&tc.Opts))
if err == nil && tc.Error != "" {
t.Fatalf("%s: expected err: %s, got none", tn, tc.Error)
}
if err != nil && tc.Error == "" {
t.Fatalf("%s: unexpected err: %s", tn, err)
}
if err != nil && tc.Error != "" {
if !strings.Contains(err.Error(), tc.Error) {
t.Fatalf("%s: expected err: %s\nto contain: %s", tn, err, tc.Error)
}
return
}
expected := strings.TrimSpace(tc.Expect) + "\n"
if actual != expected {
t.Fatalf("%s:\n\nexpected:\n%s\n\ngot:\n%s", tn, expected, actual)
}
})
}
}
type testGraphFunc func() *Graph
type testDrawable struct {
VertexName string
DependentOnMock []string
}
func (node *testDrawable) Name() string {
return node.VertexName
}
func (node *testDrawable) DotNode(n string, opts *dag.DotOpts) *dag.DotNode {
return &dag.DotNode{Name: n, Attrs: map[string]string{}}
}
func (node *testDrawable) DependableName() []string {
return []string{node.VertexName}
}
func (node *testDrawable) DependentOn() []string {
return node.DependentOnMock
}
type testDrawableOrigin struct {
VertexName string
}
func (node *testDrawableOrigin) Name() string {
return node.VertexName
}
func (node *testDrawableOrigin) DotNode(n string, opts *dag.DotOpts) *dag.DotNode {
return &dag.DotNode{Name: n, Attrs: map[string]string{}}
}
func (node *testDrawableOrigin) DotOrigin() bool {
return true
}
func (node *testDrawableOrigin) DependableName() []string {
return []string{node.VertexName}
}
type testDrawableSubgraph struct {
VertexName string
SubgraphMock *Graph
DependentOnMock []string
}
func (node *testDrawableSubgraph) Name() string {
return node.VertexName
}
func (node *testDrawableSubgraph) Subgraph() dag.Grapher {
return node.SubgraphMock
}
func (node *testDrawableSubgraph) DotNode(n string, opts *dag.DotOpts) *dag.DotNode {
return &dag.DotNode{Name: n, Attrs: map[string]string{}}
}
func (node *testDrawableSubgraph) DependentOn() []string {
return node.DependentOnMock
}

View File

@ -38,12 +38,6 @@ func TestMain(m *testing.M) {
experiment.Flag(flag.CommandLine) experiment.Flag(flag.CommandLine)
flag.Parse() flag.Parse()
// Make sure shadow operations fail our real tests
contextFailOnShadowError = true
// Always DeepCopy the Diff on every Plan during a test
contextTestDeepCopyOnPlan = true
// We have fmt.Stringer implementations on lots of objects that hide // We have fmt.Stringer implementations on lots of objects that hide
// details that we very often want to see in tests, so we just disable // details that we very often want to see in tests, so we just disable
// spew's use of String methods globally on the assumption that spew // spew's use of String methods globally on the assumption that spew