Skip to content

Commit

Permalink
Add check command to verify that modules parse and compile
Browse files Browse the repository at this point in the history
  • Loading branch information
mmussomele authored and tsandall committed Jun 29, 2017
1 parent 3261995 commit ee50506
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 9 deletions.
75 changes: 75 additions & 0 deletions cmd/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2017 The OPA Authors. All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package cmd

import (
"fmt"
"os"
"path/filepath"

"github.com/open-policy-agent/opa/ast"
"github.com/open-policy-agent/opa/runtime"

"github.com/spf13/cobra"
)

var checkCommand = &cobra.Command{
Use: "check",
Short: "Check policies for errors",
Long: `Check that policy source files can be parsed and compiled.
If the 'check' command succeeds in parsing and compiling the source file(s), no output
is produced. If the parsing or compiling fails, 'check' will output the errors
and exit with a non-zero exit code.`,
Run: func(cmd *cobra.Command, args []string) {
os.Exit(checkModules(args))
},
}

func checkModules(args []string) int {
var errors []string
modules := map[string]*ast.Module{}
checkModule := func(filename string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}

if filepath.Ext(filename) != ".rego" {
return nil
}

loaded, err := runtime.RegoLoad(filename)
if err != nil {
errors = append(errors, err.Error())
return nil
}

modules[filename] = loaded.Parsed
return nil
}

for _, filename := range args {
if err := filepath.Walk(filename, checkModule); err != nil {
fmt.Fprintln(os.Stderr, err.Error())
return 2
}
}

if len(errors) == 0 {
c := ast.NewCompiler()
if c.Compile(modules); c.Failed() {
errors = append(errors, c.Errors.Error())
}
}

for _, err := range errors {
fmt.Fprintln(os.Stderr, err)
}
return len(errors)
}

func init() {
RootCommand.AddCommand(checkCommand)
}
18 changes: 10 additions & 8 deletions runtime/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,20 @@ func (e *loaderErrors) Add(err error) {

type loaded struct {
Documents map[string]interface{}
Modules map[string]*loadedModule
Modules map[string]*LoadedModule
path []string
}

type loadedModule struct {
// LoadedModule represents a module that has been successfully loaded.
type LoadedModule struct {
Parsed *ast.Module
Raw []byte
}

func newLoaded() *loaded {
return &loaded{
Documents: map[string]interface{}{},
Modules: map[string]*loadedModule{},
Modules: map[string]*LoadedModule{},
}
}

Expand Down Expand Up @@ -96,7 +97,7 @@ func (e emptyModuleError) Error() string {

func (l *loaded) Merge(path string, result interface{}) error {
switch result := result.(type) {
case *loadedModule:
case *LoadedModule:
l.Modules[normalizeModuleID(path)] = result
default:
obj, ok := makeDir(l.path, result)
Expand Down Expand Up @@ -191,15 +192,15 @@ func loadFileForKnownTypes(path string) (interface{}, error) {
case ".json":
return jsonLoad(path)
case ".rego":
return regoLoad(path)
return RegoLoad(path)
case ".yaml", ".yml":
return yamlLoad(path)
}
return nil, unrecognizedFile(path)
}

func loadFileForAnyType(path string) (interface{}, error) {
module, err := regoLoad(path)
module, err := RegoLoad(path)
if err == nil {
return module, nil
}
Expand Down Expand Up @@ -239,7 +240,8 @@ func jsonLoad(path string) (interface{}, error) {
return x, nil
}

func regoLoad(path string) (interface{}, error) {
// RegoLoad loads and parses a rego source file.
func RegoLoad(path string) (*LoadedModule, error) {
bs, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
Expand All @@ -251,7 +253,7 @@ func regoLoad(path string) (interface{}, error) {
if module == nil {
return nil, emptyModuleError(path)
}
result := &loadedModule{
result := &LoadedModule{
Parsed: module,
Raw: bs,
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func (rt *Runtime) getBanner() string {
return buf.String()
}

func compileAndStoreInputs(ctx context.Context, store storage.Store, txn storage.Transaction, modules map[string]*loadedModule) error {
func compileAndStoreInputs(ctx context.Context, store storage.Store, txn storage.Transaction, modules map[string]*LoadedModule) error {

policies := make(map[string]*ast.Module, len(modules))

Expand Down

0 comments on commit ee50506

Please sign in to comment.