-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathterrapolicy_test.go
156 lines (127 loc) · 3.87 KB
/
terrapolicy_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package terrapolicy
import (
"bytes"
"fmt"
"github.com/clearbank/terrapolicy/internals/cli"
"github.com/clearbank/terrapolicy/internals/file"
"github.com/clearbank/terrapolicy/internals/policies"
"io"
"os"
"os/exec"
"strings"
"testing"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/logutils"
"log"
. "github.com/onsi/gomega"
)
var testLoc = "integration_tests/"
var tmpDir = "__tmp"
type Logger interface {
Log(args ...any)
}
func TestTerraPolicy(t *testing.T) {
if _, skip := os.LookupEnv("SKIP_INTEGRATION_TESTS"); skip {
t.Skip("skipping integration test")
return
}
prepare()
var suites []TestSuite
paths, _ := file.GetFilePaths(testLoc + "/*")
for _, testBaseLocation := range paths {
testPolicies, _ := file.GetFilePaths(testBaseLocation + "/policy_*.yaml")
for _, policyToTest := range testPolicies {
testLocation := tmpDir + "/" + file.GetFilename(testBaseLocation) + "/" + file.GetFilename(policyToTest) + "/"
file.Copy(testBaseLocation+"/*.tf", testLocation)
file.Copy(policyToTest, testLocation+cli.TERRAPOLICY_DEFAULT_POLICY_NAME)
extraArgs, _ := file.ReadFile(testBaseLocation + "/args")
suites = append(suites, TestSuite{
location: testLocation,
pass: shouldPass(policyToTest, t),
extraArgs: string(extraArgs),
})
}
}
for _, suite := range suites {
suite := suite
t.Run(suite.location, func(t *testing.T) {
if _, parallel := os.LookupEnv("PARALLEL"); parallel {
t.Parallel() // marks each test case as capable of running in parallel with each other
}
if name, skip := os.LookupEnv("SUITE"); skip && !strings.Contains(t.Name(), name) {
t.Skip("skipping")
}
g := NewWithT(t)
itShouldRunTerraformInit(&suite, g, t)
itShouldRunTerraPolicy(&suite, g, t)
itShouldRunTerraformValidate(&suite, g, t)
})
}
}
func itShouldRunTerraformInit(suite *TestSuite, g *WithT, l Logger) {
err := run("terraform", suite.location, "init", l)
g.Expect(err).To(BeNil(), "terraform init failed")
}
func itShouldRunTerraPolicy(suite *TestSuite, g *WithT, l Logger) {
stringArgs := fmt.Sprintf("-dir %v %v", suite.location, suite.extraArgs)
cliArgs, err := cli.ParseArgs("terrapolicy", strings.Split(stringArgs, " "))
g.Expect(err).To(BeNil(), "arguments failed to parse")
l.Log(stringArgs, cliArgs)
p, err := policies.Parse(cliArgs.Config)
g.Expect(err).To(BeNil(), "policy failed to parse")
err = TerraPolicy(Args{
Policy: p,
Flags: policies.PolicyExecutionFlags{
Strict: cliArgs.Strict,
},
Dir: cliArgs.Dir,
})
g.Expect(err == nil).To(BeEquivalentTo(suite.pass), "wrong expected outcome")
}
func itShouldRunTerraformValidate(suite *TestSuite, g *WithT, l Logger) {
err := run("terraform", suite.location, "validate", l)
g.Expect(err).To(BeNil(), "terraform validate failed")
}
func run(prog string, entryDir string, cmd string, g Logger) error {
println(prog, cmd)
var stdout bytes.Buffer
var stderr bytes.Buffer
command := exec.Command(prog, cmd)
command.Dir = entryDir
command.Stdout = &stdout
command.Stderr = &stderr
if err := command.Run(); err != nil {
g.Log(stderr.String())
return err
}
println(stdout.String())
return nil
}
func prepare() {
filter := &logutils.LevelFilter{
Levels: []logutils.LogLevel{"DEBUG", "TRACE", "INFO", "WARN", "ERROR"},
MinLevel: logutils.LogLevel("INFO"),
Writer: os.Stderr,
}
log.SetOutput(filter)
hclog.DefaultOutput = io.Discard //suppress tfSchema logs
os.RemoveAll(tmpDir)
}
func shouldPass(policyName string, t *testing.T) bool {
frags := strings.Split(file.GetFilename(policyName), "_")
exp := strings.ToLower(frags[len(frags)-1])
switch string(exp) {
case "ok":
return true
case "ko":
return false
default:
t.Fatalf("policy name %v must end in ok|ko to determine the success/fail outcome of the policy", policyName)
return false
}
}
type TestSuite struct {
location string
pass bool
extraArgs string
}