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

v1 build-tag and import for side effects #7179

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

johanfylling
Copy link
Contributor

@johanfylling johanfylling commented Nov 19, 2024

This is an alternative to the API/SDK changes in #7161.

This PR makes the following changes:

  • Updates the default rego-version to v1
  • Makes it possible to globally opt-in to v0 through
    • opa_rego_v0 build tag
    • _ "github.com/open-policy-agent/opa/features/rego_default_v0" import for side effects

Pros compared to alternative:

  • OPA 1.0 is natively v1
  • No effort to upgrade to v1
  • Single toggle to switch v0/v1
  • Cohesive API not fractured between v0 and v1 SDK:s.
    • easier to maintain

Cons compared to alternative:

  • Library-makers that introduce transitive dependency to OPA need to either:
    • set rego-version globally
      • vulnerable to library-user re-setting global rego-version default
    • update OPA SDK usage to explicitly set rego-version
      • mostly by setting the appropriate rego-version option in factory/construction calls

For toggling which rego-version is default.
This is groundwork that can be replaced/augmented with a `rego_v0` build tag in OPA v1.0.

NOTE: This is a PoC proposal, not to be merged unless no other alternatives can be devised.
Signed-off-by: Johan Fylling <[email protected]>
* Making `ast.DefaultRefoVersion` a func
* conditioning `ast.defaultRegoVersion` on `opa_rego_v1` built tag

Signed-off-by: Johan Fylling <[email protected]>
To be imported for side effects.

Signed-off-by: Johan Fylling <[email protected]>
…rsion`

Note: can't use ast.RegoVersion values directly because of circular dependencies.
`DefaultRegoVersion` could alternatively be set to int-representation (manifest representation), but the required call to `ast.RegoVersionFromInt()` from `ast.DefaultRegoVersion()` is likely somewhat more costly.

Signed-off-by: Johan Fylling <[email protected]>
Copy link
Contributor Author

@johanfylling johanfylling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some notes.

@@ -45,6 +45,10 @@ const (
RegoV1
)

func DefaultRegoVersion() RegoVersion {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaking change.
Very unlikely anyone is using this, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since DefaultRegoVersion was added so recently I think we can make this change confidently.

@@ -112,7 +112,7 @@ install: generate
$(GO) install $(GO_TAGS) -ldflags $(LDFLAGS)

.PHONY: test
test: go-test wasm-test
test: go-test go-test-v0 go-test-v0-import wasm-test
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go-tests are basically run twice, once for v0 and once for v1. This has impact on PR GHA execution time. Instead, we could narrow the scope of tests run for v0. The benefit of keeping it like this is we get great test-coverage, and will know if we break the v0 opt-in.

package rego_default

// DefaultRegoVersion is the default Rego version (v1).
var DefaultRegoVersion = 3 // enum value for ast.RegoV1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of circular import issues, we can't assign ast.RegoV1 directly.

Alternatively, we could set this to the manifest int representation (0 for v0, 1 for v1), but that would impose a slight conversion overhead on the read side.

to avoid underscores.

Signed-off-by: Johan Fylling <[email protected]>
Signed-off-by: Johan Fylling <[email protected]>
Copy link
Contributor

@charlieegan3 charlieegan3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I think the benefits of this approach outweigh the downsides by a considerable margin. I think the OPA SDK is super powerful and I'd hope we can make V1 the default experience for it with this route.

Copy link
Contributor

@srenatus srenatus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️ code looks good, thank you for trying thisa

Comment on lines +1744 to +1754
switch mod.regoVersion {
case RegoUndefined:
switch DefaultRegoVersion() {
case RegoV1, RegoV0CompatV1:
return true
default:
return false
}
}

return mod.regoV1Compatible()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] the single-case switch could be an if:

Suggested change
switch mod.regoVersion {
case RegoUndefined:
switch DefaultRegoVersion() {
case RegoV1, RegoV0CompatV1:
return true
default:
return false
}
}
return mod.regoV1Compatible()
if mod.regoVersion == RegoUndefined {
switch DefaultRegoVersion() {
case RegoV1, RegoV0CompatV1:
return true
}
return false
}
return mod.regoV1Compatible()

...but this is code golf and doesn't matter 🙃

@@ -17,6 +17,7 @@ import (
"strings"
"unicode/utf8"

"github.com/open-policy-agent/opa/internal/rego/version"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] let's cluster this one with the other opa imports below

//
// Usage (import side effects only):
//
// import _ "github.com/open-policy-agent/opa/features/rego/v0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// import _ "github.com/open-policy-agent/opa/features/rego/v0
// import _ "github.com/open-policy-agent/opa/features/rego/v0 // default to rego v0

I think it's good practice to give a reason for underscore imports; let's give a good example.

package version

// DefaultRegoVersion is the default Rego version (v0).
var DefaultRegoVersion = 1 // enum value for ast.RegoV0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot import ast because of circularity?

// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

//go:build !opa_rego_v0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] the other file has the old-style // +build comment, too. I think we only need //go:build these days, don't we? 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants