build(deps): bump github.com/open-policy-agent/opa from 0.59.0 to 0.60.0
Bumps [github.com/open-policy-agent/opa](https://github.com/open-policy-agent/opa) from 0.59.0 to 0.60.0. - [Release notes](https://github.com/open-policy-agent/opa/releases) - [Changelog](https://github.com/open-policy-agent/opa/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-policy-agent/opa/compare/v0.59.0...v0.60.0) --- updated-dependencies: - dependency-name: github.com/open-policy-agent/opa dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
Ralf Haferkamp
parent
b62ba69bba
commit
f989854f0a
+17
-8
@@ -24,14 +24,15 @@ type exprChecker func(*TypeEnv, *Expr) *Error
|
||||
// accumulated on the typeChecker so that a single run can report multiple
|
||||
// issues.
|
||||
type typeChecker struct {
|
||||
builtins map[string]*Builtin
|
||||
required *Capabilities
|
||||
errs Errors
|
||||
exprCheckers map[string]exprChecker
|
||||
varRewriter varRewriter
|
||||
ss *SchemaSet
|
||||
allowNet []string
|
||||
input types.Type
|
||||
builtins map[string]*Builtin
|
||||
required *Capabilities
|
||||
errs Errors
|
||||
exprCheckers map[string]exprChecker
|
||||
varRewriter varRewriter
|
||||
ss *SchemaSet
|
||||
allowNet []string
|
||||
input types.Type
|
||||
allowUndefinedFuncs bool
|
||||
}
|
||||
|
||||
// newTypeChecker returns a new typeChecker object that has no errors.
|
||||
@@ -92,6 +93,11 @@ func (tc *typeChecker) WithInputType(tpe types.Type) *typeChecker {
|
||||
return tc
|
||||
}
|
||||
|
||||
func (tc *typeChecker) WithAllowUndefinedFunctionCalls(allow bool) *typeChecker {
|
||||
tc.allowUndefinedFuncs = allow
|
||||
return tc
|
||||
}
|
||||
|
||||
// Env returns a type environment for the specified built-ins with any other
|
||||
// global types configured on the checker. In practice, this is the default
|
||||
// environment that other statements will be checked against.
|
||||
@@ -347,6 +353,9 @@ func (tc *typeChecker) checkExprBuiltin(env *TypeEnv, expr *Expr) *Error {
|
||||
tpe := env.Get(name)
|
||||
|
||||
if tpe == nil {
|
||||
if tc.allowUndefinedFuncs {
|
||||
return nil
|
||||
}
|
||||
return NewError(TypeErr, expr.Location, "undefined function %v", name)
|
||||
}
|
||||
|
||||
|
||||
+16
-4
@@ -146,6 +146,7 @@ type Compiler struct {
|
||||
keepModules bool // whether to keep the unprocessed, parse modules (below)
|
||||
parsedModules map[string]*Module // parsed, but otherwise unprocessed modules, kept track of when keepModules is true
|
||||
useTypeCheckAnnotations bool // whether to provide annotated information (schemas) to the type checker
|
||||
allowUndefinedFuncCalls bool // don't error on calls to unknown functions.
|
||||
evalMode CompilerEvalMode
|
||||
}
|
||||
|
||||
@@ -457,6 +458,11 @@ func (c *Compiler) WithUseTypeCheckAnnotations(enabled bool) *Compiler {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Compiler) WithAllowUndefinedFunctionCalls(allow bool) *Compiler {
|
||||
c.allowUndefinedFuncCalls = allow
|
||||
return c
|
||||
}
|
||||
|
||||
// WithEvalMode allows setting the CompilerEvalMode of the compiler
|
||||
func (c *Compiler) WithEvalMode(e CompilerEvalMode) *Compiler {
|
||||
c.evalMode = e
|
||||
@@ -1513,7 +1519,8 @@ func (c *Compiler) checkTypes() {
|
||||
WithInputType(c.inputType).
|
||||
WithBuiltins(c.builtins).
|
||||
WithRequiredCapabilities(c.Required).
|
||||
WithVarRewriter(rewriteVarsInRef(c.RewrittenVars))
|
||||
WithVarRewriter(rewriteVarsInRef(c.RewrittenVars)).
|
||||
WithAllowUndefinedFunctionCalls(c.allowUndefinedFuncCalls)
|
||||
var as *AnnotationSet
|
||||
if c.useTypeCheckAnnotations {
|
||||
as = c.annotationSet
|
||||
@@ -1537,7 +1544,7 @@ func (c *Compiler) checkUnsafeBuiltins() {
|
||||
func (c *Compiler) checkDeprecatedBuiltins() {
|
||||
for _, name := range c.sorted {
|
||||
mod := c.Modules[name]
|
||||
if c.strict || mod.regoV1Compatible {
|
||||
if c.strict || mod.regoV1Compatible() {
|
||||
errs := checkDeprecatedBuiltins(c.deprecatedBuiltinsMap, mod)
|
||||
for _, err := range errs {
|
||||
c.err(err)
|
||||
@@ -1577,6 +1584,11 @@ func (c *Compiler) compile() {
|
||||
continue // skip these stages
|
||||
}
|
||||
}
|
||||
|
||||
if c.allowUndefinedFuncCalls && s.name == "CheckUndefinedFuncs" {
|
||||
continue
|
||||
}
|
||||
|
||||
c.runStage(s.metricName, s.f)
|
||||
if c.Failed() {
|
||||
return
|
||||
@@ -1683,7 +1695,7 @@ func (c *Compiler) checkDuplicateImports() {
|
||||
|
||||
for _, name := range c.sorted {
|
||||
mod := c.Modules[name]
|
||||
if c.strict || mod.regoV1Compatible {
|
||||
if c.strict || mod.regoV1Compatible() {
|
||||
modules = append(modules, mod)
|
||||
}
|
||||
}
|
||||
@@ -1697,7 +1709,7 @@ func (c *Compiler) checkDuplicateImports() {
|
||||
func (c *Compiler) checkKeywordOverrides() {
|
||||
for _, name := range c.sorted {
|
||||
mod := c.Modules[name]
|
||||
if c.strict || mod.regoV1Compatible {
|
||||
if c.strict || mod.regoV1Compatible() {
|
||||
errs := checkRootDocumentOverrides(mod)
|
||||
for _, err := range errs {
|
||||
c.err(err)
|
||||
|
||||
+70
-18
@@ -27,6 +27,22 @@ import (
|
||||
|
||||
var RegoV1CompatibleRef = Ref{VarTerm("rego"), StringTerm("v1")}
|
||||
|
||||
// RegoVersion defines the Rego syntax requirements for a module.
|
||||
type RegoVersion int
|
||||
|
||||
const (
|
||||
// RegoV0 is the default, original Rego syntax.
|
||||
RegoV0 RegoVersion = iota
|
||||
// RegoV0CompatV1 requires modules to comply with both the RegoV0 and RegoV1 syntax (as when 'rego.v1' is imported in a module).
|
||||
// Shortly, RegoV1 compatibility is required, but 'rego.v1' or 'future.keywords' must also be imported.
|
||||
RegoV0CompatV1
|
||||
// RegoV1 is the Rego syntax enforced by OPA 1.0; e.g.:
|
||||
// future.keywords part of default keyword set, and don't require imports;
|
||||
// 'if' and 'contains' required in rule heads;
|
||||
// (some) strict checks on by default.
|
||||
RegoV1
|
||||
)
|
||||
|
||||
// Note: This state is kept isolated from the parser so that we
|
||||
// can do efficient shallow copies of these values when doing a
|
||||
// save() and restore().
|
||||
@@ -99,14 +115,27 @@ func (e *parsedTermCacheItem) String() string {
|
||||
|
||||
// ParserOptions defines the options for parsing Rego statements.
|
||||
type ParserOptions struct {
|
||||
Capabilities *Capabilities
|
||||
ProcessAnnotation bool
|
||||
AllFutureKeywords bool
|
||||
FutureKeywords []string
|
||||
SkipRules bool
|
||||
JSONOptions *astJSON.Options
|
||||
unreleasedKeywords bool // TODO(sr): cleanup
|
||||
Capabilities *Capabilities
|
||||
ProcessAnnotation bool
|
||||
AllFutureKeywords bool
|
||||
FutureKeywords []string
|
||||
SkipRules bool
|
||||
JSONOptions *astJSON.Options
|
||||
// RegoVersion is the version of Rego to parse for.
|
||||
// RegoV1Compatible additionally affects the Rego version. Use EffectiveRegoVersion to get the effective Rego version.
|
||||
RegoVersion RegoVersion
|
||||
// RegoV1Compatible is equivalent to setting RegoVersion to RegoV0CompatV1.
|
||||
// RegoV1Compatible takes precedence, and if set to true, RegoVersion is ignored.
|
||||
// Deprecated: use RegoVersion instead. Will be removed in a future version of OPA.
|
||||
RegoV1Compatible bool
|
||||
unreleasedKeywords bool // TODO(sr): cleanup
|
||||
}
|
||||
|
||||
func (po *ParserOptions) EffectiveRegoVersion() RegoVersion {
|
||||
if po.RegoV1Compatible {
|
||||
return RegoV0CompatV1
|
||||
}
|
||||
return po.RegoVersion
|
||||
}
|
||||
|
||||
// NewParser creates and initializes a Parser.
|
||||
@@ -189,6 +218,11 @@ func (p *Parser) WithJSONOptions(jsonOptions *astJSON.Options) *Parser {
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Parser) WithRegoVersion(version RegoVersion) *Parser {
|
||||
p.po.RegoVersion = version
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Parser) parsedTermCacheLookup() (*Term, *state) {
|
||||
l := p.s.loc.Offset
|
||||
// stop comparing once the cached offsets are lower than l
|
||||
@@ -257,16 +291,23 @@ func (p *Parser) Parse() ([]Statement, []*Comment, Errors) {
|
||||
|
||||
allowedFutureKeywords := map[string]tokens.Token{}
|
||||
|
||||
for _, kw := range p.po.Capabilities.FutureKeywords {
|
||||
var ok bool
|
||||
allowedFutureKeywords[kw], ok = futureKeywords[kw]
|
||||
if !ok {
|
||||
return nil, nil, Errors{
|
||||
&Error{
|
||||
Code: ParseErr,
|
||||
Message: fmt.Sprintf("illegal capabilities: unknown keyword: %v", kw),
|
||||
Location: nil,
|
||||
},
|
||||
if p.po.EffectiveRegoVersion() == RegoV1 {
|
||||
// RegoV1 includes all future keywords in the default language definition
|
||||
for k, v := range futureKeywords {
|
||||
allowedFutureKeywords[k] = v
|
||||
}
|
||||
} else {
|
||||
for _, kw := range p.po.Capabilities.FutureKeywords {
|
||||
var ok bool
|
||||
allowedFutureKeywords[kw], ok = futureKeywords[kw]
|
||||
if !ok {
|
||||
return nil, nil, Errors{
|
||||
&Error{
|
||||
Code: ParseErr,
|
||||
Message: fmt.Sprintf("illegal capabilities: unknown keyword: %v", kw),
|
||||
Location: nil,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,7 +325,7 @@ func (p *Parser) Parse() ([]Statement, []*Comment, Errors) {
|
||||
}
|
||||
|
||||
selected := map[string]tokens.Token{}
|
||||
if p.po.AllFutureKeywords {
|
||||
if p.po.AllFutureKeywords || p.po.EffectiveRegoVersion() == RegoV1 {
|
||||
for kw, tok := range allowedFutureKeywords {
|
||||
selected[kw] = tok
|
||||
}
|
||||
@@ -305,6 +346,12 @@ func (p *Parser) Parse() ([]Statement, []*Comment, Errors) {
|
||||
}
|
||||
p.s.s = p.s.s.WithKeywords(selected)
|
||||
|
||||
if p.po.EffectiveRegoVersion() == RegoV1 {
|
||||
for kw, tok := range allowedFutureKeywords {
|
||||
p.s.s.AddKeyword(kw, tok)
|
||||
}
|
||||
}
|
||||
|
||||
// read the first token to initialize the parser
|
||||
p.scan()
|
||||
|
||||
@@ -2567,6 +2614,11 @@ func (p *Parser) regoV1Import(imp *Import) {
|
||||
return
|
||||
}
|
||||
|
||||
if p.po.EffectiveRegoVersion() == RegoV1 {
|
||||
// We're parsing for Rego v1, where the 'rego.v1' import is a no-op.
|
||||
return
|
||||
}
|
||||
|
||||
path := imp.Path.Value.(Ref)
|
||||
|
||||
if len(path) == 1 || !path[1].Equal(RegoV1CompatibleRef[1]) || len(path) > 2 {
|
||||
|
||||
+7
-6
@@ -477,7 +477,7 @@ func ParseModuleWithOpts(filename, input string, popts ParserOptions) (*Module,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parseModule(filename, stmts, comments, popts.RegoV1Compatible)
|
||||
return parseModule(filename, stmts, comments, popts.EffectiveRegoVersion())
|
||||
}
|
||||
|
||||
// ParseBody returns exactly one body.
|
||||
@@ -626,6 +626,7 @@ func ParseStatementsWithOpts(filename, input string, popts ParserOptions) ([]Sta
|
||||
WithCapabilities(popts.Capabilities).
|
||||
WithSkipRules(popts.SkipRules).
|
||||
WithJSONOptions(popts.JSONOptions).
|
||||
WithRegoVersion(popts.EffectiveRegoVersion()).
|
||||
withUnreleasedKeywords(popts.unreleasedKeywords)
|
||||
|
||||
stmts, comments, errs := parser.Parse()
|
||||
@@ -637,7 +638,7 @@ func ParseStatementsWithOpts(filename, input string, popts ParserOptions) ([]Sta
|
||||
return stmts, comments, nil
|
||||
}
|
||||
|
||||
func parseModule(filename string, stmts []Statement, comments []*Comment, regoV1Compatible bool) (*Module, error) {
|
||||
func parseModule(filename string, stmts []Statement, comments []*Comment, regoCompatibilityMode RegoVersion) (*Module, error) {
|
||||
|
||||
if len(stmts) == 0 {
|
||||
return nil, NewError(ParseErr, &Location{File: filename}, "empty module")
|
||||
@@ -658,14 +659,14 @@ func parseModule(filename string, stmts []Statement, comments []*Comment, regoV1
|
||||
|
||||
// The comments slice only holds comments that were not their own statements.
|
||||
mod.Comments = append(mod.Comments, comments...)
|
||||
mod.regoV1Compatible = regoV1Compatible
|
||||
mod.regoVersion = regoCompatibilityMode
|
||||
|
||||
for i, stmt := range stmts[1:] {
|
||||
switch stmt := stmt.(type) {
|
||||
case *Import:
|
||||
mod.Imports = append(mod.Imports, stmt)
|
||||
if Compare(stmt.Path.Value, RegoV1CompatibleRef) == 0 {
|
||||
mod.regoV1Compatible = true
|
||||
if mod.regoVersion == RegoV0 && Compare(stmt.Path.Value, RegoV1CompatibleRef) == 0 {
|
||||
mod.regoVersion = RegoV0CompatV1
|
||||
}
|
||||
case *Rule:
|
||||
setRuleModule(stmt, mod)
|
||||
@@ -694,7 +695,7 @@ func parseModule(filename string, stmts []Statement, comments []*Comment, regoV1
|
||||
}
|
||||
}
|
||||
|
||||
if mod.regoV1Compatible {
|
||||
if mod.regoVersion == RegoV0CompatV1 || mod.regoVersion == RegoV1 {
|
||||
for _, rule := range mod.Rules {
|
||||
for r := rule; r != nil; r = r.Else {
|
||||
var t string
|
||||
|
||||
+15
-7
@@ -145,13 +145,13 @@ type (
|
||||
// within a namespace (defined by the package) and optional
|
||||
// dependencies on external documents (defined by imports).
|
||||
Module struct {
|
||||
Package *Package `json:"package"`
|
||||
Imports []*Import `json:"imports,omitempty"`
|
||||
Annotations []*Annotations `json:"annotations,omitempty"`
|
||||
Rules []*Rule `json:"rules,omitempty"`
|
||||
Comments []*Comment `json:"comments,omitempty"`
|
||||
stmts []Statement
|
||||
regoV1Compatible bool
|
||||
Package *Package `json:"package"`
|
||||
Imports []*Import `json:"imports,omitempty"`
|
||||
Annotations []*Annotations `json:"annotations,omitempty"`
|
||||
Rules []*Rule `json:"rules,omitempty"`
|
||||
Comments []*Comment `json:"comments,omitempty"`
|
||||
stmts []Statement
|
||||
regoVersion RegoVersion
|
||||
}
|
||||
|
||||
// Comment contains the raw text from the comment in the definition.
|
||||
@@ -399,6 +399,14 @@ func (mod *Module) UnmarshalJSON(bs []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mod *Module) regoV1Compatible() bool {
|
||||
return mod.regoVersion == RegoV1 || mod.regoVersion == RegoV0CompatV1
|
||||
}
|
||||
|
||||
func (mod *Module) RegoVersion() RegoVersion {
|
||||
return mod.regoVersion
|
||||
}
|
||||
|
||||
// NewComment returns a new Comment object.
|
||||
func NewComment(text []byte) *Comment {
|
||||
return &Comment{
|
||||
|
||||
Reference in New Issue
Block a user