Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

opa build -t wasm|plan: fail on unmatched entrypoints #5086

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions ast/builtins.go
Expand Up @@ -941,8 +941,8 @@ var RegexFind = &Builtin{
// GlobsMatch takes two strings regexp-style strings and evaluates to true if their
// intersection matches a non-empty set of non-empty strings.
// Examples:
// - "a.a." and ".b.b" -> true.
// - "[a-z]*" and [0-9]+" -> not true.
// - "a.a." and ".b.b" -> true.
// - "[a-z]*" and [0-9]+" -> not true.
var GlobsMatch = &Builtin{
Name: "regex.globs_match",
Description: `Checks if the intersection of two glob-style regular expressions matches a non-empty set of non-empty strings.
Expand Down Expand Up @@ -1021,7 +1021,7 @@ var Concat = &Builtin{

var FormatInt = &Builtin{
Name: "format_int",
Description: "Returns the string representation of the number in the given base after converting it to an integer value.",
Description: "Returns the string representation of the number in the given base after rounding it down to an integer value.",
anderseknert marked this conversation as resolved.
Show resolved Hide resolved
Decl: types.NewFunction(
types.Args(
types.Named("number", types.N).Description("number to format"),
Expand Down
2 changes: 1 addition & 1 deletion builtin_metadata.json
Expand Up @@ -3718,7 +3718,7 @@
"v0.43.0",
"edge"
],
"description": "Returns the string representation of the number in the given base after converting it to an integer value.",
"description": "Returns the string representation of the number in the given base after rounding it down to an integer value.",
"introduced": "v0.17.0",
"result": {
"description": "formatted number",
Expand Down
14 changes: 12 additions & 2 deletions compile/compile.go
Expand Up @@ -418,7 +418,7 @@ func (c *Compiler) optimize(ctx context.Context) error {
return nil
}

func (c *Compiler) compilePlan(ctx context.Context) error {
func (c *Compiler) compilePlan(context.Context) error {

// Lazily compile the modules if needed. If optimizations were run, the
// AST compiler will not be set because the default target does not require it.
Expand Down Expand Up @@ -464,6 +464,7 @@ func (c *Compiler) compilePlan(ctx context.Context) error {
// Create query sets for each of the entrypoints.
resultSym := ast.NewTerm(resultVar)
queries := make([]planner.QuerySet, len(c.entrypointrefs))
var unmappedEntrypoints []string

for i := range c.entrypointrefs {

Expand All @@ -474,13 +475,22 @@ func (c *Compiler) compilePlan(ctx context.Context) error {
return err
}

if len(c.compiler.GetRules(c.entrypointrefs[i].Value.(ast.Ref))) == 0 {
unmappedEntrypoints = append(unmappedEntrypoints, c.entrypoints[i])
}

queries[i] = planner.QuerySet{
Name: c.entrypoints[i],
Queries: []ast.Body{compiled},
RewrittenVars: qc.RewrittenVars(),
}
}

if len(unmappedEntrypoints) > 0 {
return fmt.Errorf("entrypoint %q does not refer to a rule or policy decision", unmappedEntrypoints[0])

}

// Prepare modules and builtins for the planner.
modules := []*ast.Module{}
for _, module := range c.compiler.Modules {
Expand All @@ -503,7 +513,7 @@ func (c *Compiler) compilePlan(ctx context.Context) error {
return err
}

// dump policy IR (if "debug" wasn't requested, debug.Witer will discard it)
// dump policy IR (if "debug" wasn't requested, debug.Writer will discard it)
err = ir.Pretty(c.debug.Writer(), policy)
if err != nil {
return err
Expand Down
40 changes: 40 additions & 0 deletions compile/compile_test.go
Expand Up @@ -55,6 +55,11 @@ func TestCompilerInitErrors(t *testing.T) {
c: New().WithTarget("wasm"),
want: errors.New("wasm compilation requires at least one entrypoint"),
},
{
note: "plan compilation requires at least one entrypoint",
c: New().WithTarget("plan"),
want: errors.New("plan compilation requires at least one entrypoint"),
},
}

for _, tc := range tests {
Expand Down Expand Up @@ -781,6 +786,41 @@ func TestCompilerPlanTargetPruneUnused(t *testing.T) {
})
}

func TestCompilerPlanTargetUnmatchedEntrypoints(t *testing.T) {
files := map[string]string{
"test.rego": `package test

p := 7
q := p + 1`,
}

test.WithTempFS(files, func(root string) {

compiler := New().WithPaths(root).WithTarget("plan").WithEntrypoints("test/p", "test/q", "test/no")
anderseknert marked this conversation as resolved.
Show resolved Hide resolved
err := compiler.Build(context.Background())
if err == nil {
t.Error("expected error from unmatched entrypoint")
}
expectError := "entrypoint \"test/no\" does not refer to a rule or policy decision"
if err.Error() != expectError {
t.Errorf("expected error %s, got: %s", expectError, err.Error())
}
})

test.WithTempFS(files, func(root string) {

compiler := New().WithPaths(root).WithTarget("plan").WithEntrypoints("foo", "foo.bar", "test/no")
err := compiler.Build(context.Background())
if err == nil {
t.Error("expected error from unmatched entrypoints")
}
expectError := "entrypoint \"foo\" does not refer to a rule or policy decision"
if err.Error() != expectError {
t.Errorf("expected error %s, got: %s", expectError, err.Error())
}
})
}

func TestCompilerSetRevision(t *testing.T) {
files := map[string]string{
"test.rego": `package test
Expand Down