Commit Graph

96 Commits

Author SHA1 Message Date
Torin Sandall c7c8e83083 Update query compiler to deep copy parsed query
The query compiler was not deep copying queries like the compiler does
for modules. As a result, the parsed query in the REPL was being
recompiled and the rewritten var mapping was not correct. E.g.,
rewritten vars were not be displayed properly.
2018-02-25 15:44:45 -08:00
Torin Sandall b6e1c8eeb4 Fix root document assignment in REPL
The initial assignment support in the REPL was using the expr operand
instead of the rule name for the unset operation. As a result,
assignments to input/data would panic because the expr operand was a ref
and not a var.
2018-02-24 10:16:27 -08:00
Torin Sandall b647eb7e71 Refactor REPL to use rego package
With these changes, the REPL can now print expression values more
reliably. E.g., simple expressions like 3+5 just do the right thing.

Previously the REPL called topdown directly and reimplemented some of
the logic to format result sets. This was a source of issues because it
was possible for the rego package and the REPL to return different
answers. With these changes, the REPL and rego package results are
equivalent.

A few changes were required. Specifically:

* Query Compiler. Updated to accept user supplied stages. This way users
can perform their own rewriting. This is used by the rego package to
provide the query+functional semantics we want. In the future, this API
could be used to register custom optimization passes to the compiler.

* Compiler. Expose GetArity helper. This allows users to quickly lookup
the arity of a function referred to by a ref. The rego package needs
this to decide whether to capture call outputs.

* Rego package. Expose new args to set parse package, imports, etc. This
is used by the REPL which maintains state to control the currently
active module.
2018-02-17 08:21:04 -08:00
Torin Sandall f9bb248c2f Fix REPL assignment support
Assignment was not special cased in the REPL before. As a result,
assigned vars would not be available in subsequent expressions.

Fixes #615
2018-02-14 09:21:43 -08:00
Torin Sandall 02e16170ac Fix safety check for nested function calls
Refactor how output vars are computed for call expressions. Previously
the number of rule args were not used to determine which args were
considered outputs. Instead, it was assumed the last arg in the call was
an output. This meant that if an arg in the output position was omitted,
an input arg would be incorrectly marked safe.

With these changes, the compiler looks up the number of args (arity) of
the rule when checking whether an arg is an output.
2018-02-14 08:36:31 -08:00
Torin Sandall 744316dbaa Add basic query performance instrumentation
Previously OPA only tracked query performance a high level (e.g., parse,
compile, eval latencies.) In some cases, it's necessary to instrument
lower level evaluation operations to understand performance. These
changes update the eval implementation to support instrumentation:

* Eval has been instrumented to record time taken for various core
operations like term plugging, reading from the store, rule lookup,
cache hits, etc.

* Rego package has been updated to support a simple rego.Instrument
operation that enables query instrumentation.

* REPL and server have been updated to expose simple interfaces to turn
on instrumentation.

* Diagnostic policy config "all" will enable instrumentation.

Instrumentation can be expensive (because it requires timing frequently
executed operations) so it should be treated as a debugging tool and not
enabled all of the time.
2018-02-09 09:30:27 -08:00
Torin Sandall b5d6e9fb09 Update REPL to show trace after partial eval 2018-01-30 15:48:37 -08:00
Torin Sandall 3f8edb627e Fix metrics reporting in REPL 2018-01-24 07:19:37 -08:00
Torin Sandall ceed94d472 Add initial implementation of partial evaluation
These changes introduce a new evaluation mode in topdown that allows
callers to mark input, data, or variables as unknown. The result of
partial evaluation is a new set of queries that can be executed when the
inputs become known. When topdown partially evaluates a query, it saves
expressions that it cannot evaluate so that they can be returned to the
caller.

As part of these changes, the binding list has been updated so that
variables can be mangled when a plug operation is performed. This allows
variables to be correctly namespaced when they're inlined into parent
queries as part of partial evaluation.
2018-01-18 07:10:31 -08:00
Stephan Renatus bffbb3fb6e fix #435: deduplicate paths in completion
I have not added a specific test case, but altered the existing one
slightly -- hope that's fine.

Signed-off-by: Stephan Renatus <srenatus@chef.io>
2018-01-15 08:13:54 -08:00
Torin Sandall 23351268a2 Fix REPL printing of generated vars
The REPL output was broken by the recent rewriting changes. In some
cases, generated vars were being displayed and in other cases ref values
were not being displayed, only true/false was being printed based on
whether the ref was defined or not.

These changes refactor the REPL to evaluate queries and output their
results with less duplication.
2017-11-22 14:46:21 -08:00
Torin Sandall 3ebbeede6c Refactor topdown evaluation/unification
These changes modify topdown evaluation to use a binding list that
namespaces variables. This allows topdown to propagate partially ground
ref operands into child query evaluation.

These changes also prepare topdown evaluation to support a partial
evaluation mode.

With these changes, evaluation is no longer performed in two steps
(i.e., first pass of evaluating individual terms, second pass of
evaluating built-in expressions.) Instead, evaluation assumes queries
have been rewritten to eagerly evaluate refs and comprehension. This
way, ref and comprehension bindings do not have to be maintained
separately: they are handled by the normal variable binding list.

This commit contains some breaking changes to the topdown APIs,
namely...

1. Truth explanation has been removed. This feature was not used and the
tracing changes broke it. We can revisit in future if necessary.

2. Data indexing has been removed. Data indexing can be re-added in
future if necessary however it should be handled outside of topdown to
avoid potential memory leaks.

3. Built-in functions produce at-most-one output now. Functions that
used to produce multiple outputs (e.g., io.jwt.decode) can produce a
composite value if they need to.

Fixes #131
2017-11-09 09:07:48 -08:00
Torin Sandall 7ca542adb5 Refactor functions implementation
Previously, functions were implemented with a separate set of types that
had their own code paths in the compiler, eval, etc. These changes
refactor the function implementation so that functions are implemented
as rules with one or more arguments.

By representing functions as rules, we can avoid special casing required
to support functions, e.g., during parse and compile there are a number
of steps that required special casing for functions:

- Parser needed separate grammar definitions for functions (which
  prevented them from being chained or using else)

- Compiler needed separate resolver and type checker implementations
  which was a source of bugs.

In some cases, special casing is unavoidable for now (e.g., during eval)
however this could be improved in the future.

Fixes #471
Fixes #467
Fixes #463
2017-10-10 08:57:58 -07:00
Torin Sandall ea2ea9b12b Modify AST to represent function names as refs
These changes update the AST to represent function names as refs.
Previously, function names were represented as strings. Representing the
names as strings was fine, however, once functions and rules are
merged, it will be desirable to refer to functions using references.
This is a bit of preemptive refactoring to make that change easier.
Instead of having functions referred to with both strings and
references, all functions will be referred to with references.
2017-10-10 08:57:58 -07:00
Torin Sandall 2401f782f3 Fix incorrect REPL interpretation of some exprs
These changes refactor the parser extensions that convert bodies into
rules if they can interpreted as such. The cases that can be converted
are clearer now and the test coverage is improved.

Fixes #433
2017-08-29 15:44:17 -07:00
Torin Sandall 4a4af6b178 Remove dead code associated with input doc errors
In b23cb4e the compiler was changed to allow queries to refer to the
input document without the input document being defined. Those changes
did not remove all of the code associated with input errors.

These changes remove the remaining (dead) code associated with input
errors and also update the server to allow Data API POST requests that
do not specify an input document.
2017-08-29 10:49:23 -07:00
Torin Sandall 588cc82f11 Add support for partial doc shorthand
These changes allow partial docs to be defined without a body in Rego
source files. Before, the rules would have to include a `{true}` body
for the parser to allow them. Now, the body can be omitted.

Rules defined this way (inside modules) cannot be copy/pasted as-is into
the REPL. This could be addressed by creating a "paste mode" in the REPL
similar to ipython and other interactive shells.

These changes build on https://github.com/open-policy-agent/opa/pull/412
with a few differences:

- Dynamic values are allowed in the head.
- Partial sets are allowed.

Both of these changes are based on personal experience writing policy.
Dynamic values are fine to allow as the compiler will catch unsafe vars
and rewrite the head to handle refs and comprehensions.
2017-08-24 11:29:14 -07:00
Matthew Mussomele df89110955 Implement metrics in the REPL 2017-08-10 08:06:22 -07:00
Torin Sandall 6c26635c4d Limit length of pretty printed values 2017-08-08 16:19:29 -07:00
Matthew Mussomele ca783539f8 Add support to cancel compilation after some number of errors
Sometimes compiling large policies with many errors causes more output
errors than is easily sorted through. The compiler has been updated to
cancel after a configurable number of errors (default no limit), and the
server, repl and check command support options for setting that limit.
2017-07-21 07:59:51 -07:00
Torin Sandall bafa5645d1 Format REPL modules before printing them 2017-07-17 11:10:38 -07:00
Matthew Mussomele 8685c588b7 Update repl to support user functions 2017-07-05 13:45:55 -07:00
Matthew Mussomele 743a7b0812 Add Comments to the AST
Comments weren't useful before, but will be needed when formatting
rego code in a future patch.
2017-06-29 13:10:36 -04:00
Torin Sandall c786fc9d33 Add support for concurrent r/w txns
These changes update the storage layer to support
multi-reader/single-writer txns:

- Writers can read their own writes
- Writers can rollback changes
- Readers only see writes after a successful commit
- Readers can progress during a write txn and only block during a commit

These changes also refactor the trigger interface to better support
transactions.
2017-06-23 13:18:15 -07:00
Torin Sandall 10f22906b5 Refactor storage layer interfaces
This is a large change set that contains a few backwards incompatible
changes. Summary of breaking changes:

- Remove storage.Storage in favour of storage.Store interface.
- Remove mount support.
- Remove storage of compiled policies.
- Modify storage.Store to support rollback.
- Modify storage.Store to support raw policy storage.
- Modify storage.Store to support indexing.
2017-06-23 13:18:15 -07:00
Torin Sandall b20f632eb6 Fix REPL to support else keyword
Otherwise, else rules would not have their module set and so their path
could not be gotten.
2017-05-26 11:55:49 -07:00
Torin Sandall eb73e2fdd9 Refactor built-in name type to use String
Previously we modelled built-in names as Vars which worked fine,
however, now that built-ins can be namespaced using "." they no longer
conform to the Var syntax.

Also, this lets us get rid of the visitor param that excluded built-in
names when walking ASTs.
2017-05-15 17:20:19 -07:00
Torin Sandall b23cb4e30f Remove input checks in query compiler
Previously the query compiler checked whether input was defined to catch
two cases:

1) Input was required by query or transitive dependencies of query.
Input was required if the input document was referenced at all.
Motivation for this was to produce "correct" results when negation is
used. In practice, this never proved to be very helpful.

2) Input document was specified multiple times, causing a conflict.
Again, in practice, this never proved to be very helpful.

In both cases, if the policy decision is *incorrect* someone has to look
at (i) the input (ii) the data and (iii) the policy to understand why.

Ultimately we expect users to push schema information into OPA so that
we can validate inputs and data conform to those schema. In that case,
if an input was not specified (or conflicting); the type checking should
catch it.
2017-05-09 17:26:51 -07:00
Torin Sandall 3690fe8f05 Initial type checking implementation 2017-04-26 15:04:48 -07:00
Torin Sandall 3a2314f5f5 Add module pointer to rules
Given a parsed rule, it should be easy to determine the path of the
document produced by that rule without having access to the entire that
the rule is contained in.
2017-04-26 15:04:48 -07:00
Torin Sandall a898de13c9 Refactor ValueToInterface into ast package 2017-04-25 20:17:02 -07:00
Torin Sandall b1fc681590 Remove persist/--policy-dir option
This is the first in series of Spring cleaning around the storage layer.
In the near future we will add local disk-based persistence support to
OPA. That support will handle storage of source files.

The --policy-dir option is almost entirely unused today. Removing it
will make it easier to get rid of the policyStore entirely.

The next thing to do will be to remove the specialized *Policy methods
from the storage layer. This way the storage layer can just accept
policies as normal data.

If policies need to be persisted until then, users can treat the
policies as config files and manage them outside of OPA.
2017-03-12 13:23:22 -07:00
Torin Sandall 039c7bdd02 Update error codes and messages throughout
- Refactor error codes to use strings instead of ints.

- Simplify error messages throughout.

- Ensure location set on all expressions. There were a couple locations
  in the parser/compiler where locations were not being set.

- Fallback to rule location in topdown in case location not set. This
  ensures that users get useful locations for API requests with paths
  that refer to virtual docs exactly.

Also add Find function to ast.Value. Useful for extracting values
dynamically. Eventually can support JSON pointers.

Fixes #237
2017-02-16 10:29:57 -08:00
Torin Sandall e04b4e5038 Fix unset of input/data in REPL
Fixes #259
2017-02-13 14:28:33 -08:00
Torin Sandall 49a963f16a Fix test cases to work with new syntax 2017-02-10 10:37:43 -08:00
Torin Sandall 95bdd4c824 Fix Rule and Expr String() functions
- Handle infix operators
- Don't add body to default rules
- Register infix operator names
2017-02-10 10:37:43 -08:00
Torin Sandall b2f5e70fcd Allow sets to be treated like objects/arrays
In the past, topdown would bind set[x] to true. This resulted in
confusion when people attempted to write joins with set elements.

With this change, topdown treats sets like objects/arrays, except that
set[x] is bound to x. This allows users to write queries that
dereference sets just like objects and arrays.

Also, fix handling of self-joins where previously a recursive binding
could be added. The "self-join" test case was added to cover this.

Fixes #243
2017-02-07 15:45:17 -08:00
Torin Sandall 04c603a059 Refactor to use ast.Head throughout OPA
Instead of storing all head attributes on the rule directly, use the
ast.Head structure that was introduced a little while ago.
2017-02-03 09:02:22 -08:00
Torin Sandall 4cb1d67bbd Update REPL to support with modifier
Also, reword error message for missing/undefined input document.
2017-02-03 08:39:35 -08:00
Torin Sandall 545332f45e Fix input document definition in REPL
Fixes #231
2017-01-26 08:54:29 -08:00
Torin Sandall d65ccff7de Fix handling of missing input document
These changes update OPA to analyze queries to determine if an input
document is required. In the future, more sophisticated checks could be
performed (e.g., JSON schema validation).

If an input document is required but not provided, OPA will return HTTP
400 (per the documentation). This was broken in #197.

Fixes #227
2017-01-25 10:10:35 -08:00
Torin Sandall a012773a10 Refactor topdown.Topdown to hide locals
The locals structure does not have be exposed to callers and should be
hidden so that changes to the structure can be made in the future. All
callers need is the ability to obtain the bindings for variables.
2017-01-20 13:58:13 -08:00
Torin Sandall ebc753cfd8 Rename the request document
Naming is hard. The "request" document is now the "input" document.
2017-01-18 16:37:32 -08:00
Torin Sandall 699e45db20 Improve module parsing errors
Fixes #213
2017-01-18 12:22:37 -08:00
Torin Sandall 0e156883a1 Update repl with request changes 2016-12-19 09:59:03 -08:00
Torin Sandall f64d75aee2 Update parser support for <var> = <term> rules
Fixes #192
2016-12-13 18:44:16 -08:00
Torin Sandall 7c176dbbb8 Improve exit handling in REPL
REPL now behaves slightly differently:

1) ctrl+c will just reset the line
2) ctrl+d will prompt user for input

Fixes #175
2016-12-13 18:44:15 -08:00
Torin Sandall 5739de9295 Add help topics to REPL
Fixes #172
2016-12-13 18:44:15 -08:00
Torin Sandall c3d1542754 Update storage to support context.Context
This includes all of the changes to plumb the context through from the HTTP
server and the REPL.

Also, this removes the Travis CI build for Go 1.6 as the context package is
not part of the standard library before Go 1.7. Once Go 1.8 is released we can
go back to supporting the previous Go release.

Fixes #155
2016-12-07 14:18:15 -08:00
Torin Sandall b4d551bcdf Rename topdown.Context to topdown.Topdown 2016-12-05 16:08:48 -08:00