-
Notifications
You must be signed in to change notification settings - Fork 8
/
document.go
131 lines (120 loc) · 3.81 KB
/
document.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
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - Aaron Meihm ameihm@mozilla.com
package scribe
import (
"fmt"
)
// Document describes a scribe document; a document contains all tests and other
// infomration used to execute a policy check
type Document struct {
Variables []Variable `json:"variables,omitempty" yaml:"variables,omitempty"`
Objects []Object `json:"objects,omitempty" yaml:"objects,omitempty"`
Tests []Test `json:"tests,omitempty" yaml:"tests,omitempty"`
}
// Validate a scribe document for consistency. This identifies any errors in
// the document that are not JSON syntax related, including missing fields or
// references to tests that do not exist. Returns an error if validation fails.
func (d *Document) Validate() error {
for i := range d.Objects {
err := d.Objects[i].validate(d)
if err != nil {
return err
}
}
for i := range d.Tests {
err := d.Tests[i].validate(d)
if err != nil {
return err
}
}
return nil
}
// GetTestIdentifiers returns the test identifiers for all tests present in
// the document.
func (d *Document) GetTestIdentifiers() []string {
ret := make([]string, 0)
for _, x := range d.Tests {
ret = append(ret, x.TestID)
}
return ret
}
func (d *Document) prepareObjects() error {
// Mark any chain objects; these will be skipped during preparation
// as they are dependent on evaluation of the root object. Chain
// objects are objects that contain chain variables; that is they
// cannot be evaluated as they depend on information being passed
// from the previous object in the chain.
for i := range d.Objects {
d.Objects[i].markChain()
}
// Note that prepare() will return an error if something goes wrong
// but we don't propagate this back. Errors within object preparation
// are kept localized to the object, and are not considered fatal to
// execution of the entire document.
for i := range d.Objects {
d.Objects[i].prepare(d)
}
debugPrint("prepareObjects(): firing any import chains\n")
for i := range d.Objects {
d.Objects[i].fireChains(d)
}
return nil
}
func (d *Document) objectPrepared(obj string) (bool, error) {
var objptr *Object
for i := range d.Objects {
if d.Objects[i].Object == obj {
objptr = &d.Objects[i]
}
}
if objptr == nil {
return false, fmt.Errorf("unknown object \"%v\"", obj)
}
// If an error occurred while preparing this object, return that here
// and note preparation as false.
if objptr.err != nil {
return false, objptr.err
}
return objptr.prepared, nil
}
func (d *Document) runTests() error {
// As documented prepareObjects(), we don't propagate errors here but
// instead keep them localized to the test.
for i := range d.Tests {
d.Tests[i].runTest(d)
}
return nil
}
// Return a pointer to a test instance of the test whose identifier matches
func (d *Document) GetTest(testid string) (*Test, error) {
for i := range d.Tests {
if d.Tests[i].TestID == testid {
return &d.Tests[i], nil
}
}
return nil, fmt.Errorf("unknown test \"%v\"", testid)
}
// Given an object name, return a generic source interface for the object.
func (d *Document) getObjectInterface(obj string) (genericSource, error) {
for i := range d.Objects {
if d.Objects[i].Object == obj {
return d.Objects[i].getSourceInterface(), nil
}
}
return nil, fmt.Errorf("unknown object \"%v\"", obj)
}
// Given an object name, return a generic source interface to a copy of the
// object.
func (d *Document) getObjectInterfaceCopy(obj string) (genericSource, error) {
for i := range d.Objects {
if d.Objects[i].Object == obj {
newobj := d.Objects[i]
return newobj.getSourceInterface(), nil
}
}
return nil, fmt.Errorf("unknown object \"%v\"", obj)
}