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

bundle: Fixing issue where --v0-compatible isn't respected for custom bundles #7338

Conversation

johanfylling
Copy link
Contributor

where the bundle has been manually constructed containing v0 Rego modules and no rego_version/file_rego_versions fields are declared in the bundle manifest.

This affects bundle deactivation in the bundle store lifecycle used when for opa run in server mode (-s).

…om bundles

where the bundle has been manually constructed containing v0 Rego modules and
no `rego_version`/`file_rego_versions` fields are declared in the bundle manifest.

This affects bundle deactivation in the bundle store lifecycle used when for
`opa run` in server mode (`-s`).

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

netlify bot commented Feb 4, 2025

Deploy Preview for openpolicyagent ready!

Name Link
🔨 Latest commit 12d0f0a
🔍 Latest deploy log https://app.netlify.com/sites/openpolicyagent/deploys/67a3304e667472000811a3fe
😎 Deploy Preview https://deploy-preview-7338--openpolicyagent.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

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 comments to aid review.

@@ -1204,10 +1206,6 @@ func (b *Bundle) SetRegoVersion(v ast.RegoVersion) {
// If there is no defined version for the given path, the default version def is returned.
// If the version does not correspond to ast.RegoV0 or ast.RegoV1, an error is returned.
func (b *Bundle) RegoVersionForFile(path string, def ast.RegoVersion) (ast.RegoVersion, error) {
if def == ast.RegoUndefined {
def = ast.DefaultRegoVersion
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a "magic", undocumented behavior that even confused our own internal usage.

Copy link
Contributor

@philipaconrad philipaconrad Feb 4, 2025

Choose a reason for hiding this comment

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

[comment]: I did wonder about this when I was looking at the sources recently. Thanks for addressing this!

@@ -827,7 +827,7 @@ func writeModuleRegoVersionToStore(ctx context.Context, store storage.Store, txn

if regoVersion == ast.RegoUndefined {
var err error
regoVersion, err = b.RegoVersionForFile(mf.Path, ast.RegoUndefined)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was the root cause of the issue. If no rego-version was declared for the module in the bundle, we'd always default to v1, and not the runtime rego-version (i.e. --v0-compatible enabled/disabled).

},
},
{
note: "custom bundle without rego-version, lazy, --v0-compatible",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test-case fails without the fix.

"modules":{
"example/example.rego":{
"rego_version":1
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

No explicit rego-version set for runtime and bundle, so both default to the same version (v1) and is therefore not recorded into the stored meta data.

Copy link
Contributor

@philipaconrad philipaconrad left a comment

Choose a reason for hiding this comment

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

Thank you for addressing this edge case for Rego v0/v1 support in bundles. 🙂

I've tested this PR branch against one of my own bundles that was failing due to a lack of the rego_version field in its manifest-- it works now!

A few comments and questions below:

Comment on lines 720 to 721
} else if regoVersion != ast.RegoUndefined {
modulePopts.RegoVersion = regoVersion
Copy link
Contributor

@philipaconrad philipaconrad Feb 4, 2025

Choose a reason for hiding this comment

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

[comment/question]: It is not obvious to me exactly when this condition could occur, even after diving into the sources for bundle.RegoVersionForFile. As best I can tell though, getting both an error and a regoVersion that isn't the default ast.RegoUndefined value should be pretty difficult.

If there's an obvious edge-case I'm missing, could we add a quick comment to explain it here? 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is merely a safeguard against the world changing around us. You're correct that ast.RegoUndefined isn't an expected value here, but I think this is buried deeply enough that a future code change that alters this expectation could cause an issue here that is hard to detect. Also, if we get a ast.RegoUndefined returned here, we know that the correct course of action is to let the configured parser-options take precedence.

I'll add a comment 👍

@@ -1204,10 +1206,6 @@ func (b *Bundle) SetRegoVersion(v ast.RegoVersion) {
// If there is no defined version for the given path, the default version def is returned.
// If the version does not correspond to ast.RegoV0 or ast.RegoV1, an error is returned.
func (b *Bundle) RegoVersionForFile(path string, def ast.RegoVersion) (ast.RegoVersion, error) {
if def == ast.RegoUndefined {
def = ast.DefaultRegoVersion
}
Copy link
Contributor

@philipaconrad philipaconrad Feb 4, 2025

Choose a reason for hiding this comment

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

[comment]: I did wonder about this when I was looking at the sources recently. Thanks for addressing this!

Comment on lines 451 to 453
if m.parserOptions.RegoVersion == ast.RegoUndefined {
m.parserOptions.RegoVersion = ast.DefaultRegoVersion
}
Copy link
Contributor

Choose a reason for hiding this comment

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

[question]: Is this where the "default to the ast.DefaultRegoVersion if none provided" logic needed to move to?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. If a plugins.Manager has ast.RegoUndefined as rego-version, then any consumer of the manager would simply do the correct thing depending on what v0/v1 package it comes from, which is why this has gone undetected. Defaulting to v1 here if no rego-version has been provided through the options is however more consistent with user expectations.

@johanfylling johanfylling merged commit bb12354 into open-policy-agent:main Feb 5, 2025
28 checks passed
@johanfylling johanfylling deleted the fix/bundle-store_custom-bundle_v0-compatible branch February 5, 2025 11:50
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