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

Charles/eopa engine #1000

Merged
merged 39 commits into from
Aug 29, 2024
Merged

Charles/eopa engine #1000

merged 39 commits into from
Aug 29, 2024

Conversation

charlesdaniels
Copy link
Member

@charlesdaniels charlesdaniels commented Aug 20, 2024

This PR adds initial support for an EOPA engine. It depends on the upstream PR #92, and should not be merged before that one is.

It includes 3 main components:

  1. The config package has been changed so that if the eopa engine is used, the new helpers in the upstream PR are used to look up the capabilities that are attached to the config.Config type. The engine and version are saved in the config for later use.
  2. The internal/lsp package has been modified to inspect the engine and version from the configuration, and to look up capabilities for use in the internal/lsp/rego package.
  3. A new capabilities package has been added to provide a general-purpose way for Regal to access OPA capabilities. It unifies access to local, remote, and embedded capabilities using URLs. Both config and internal/lsp have been refactored to use this new system.

In summary, capabilities.Lookup() supports loading OPA capabilities in the following ways:

  • file:// URLs are loaded as JSON from disk, just like specifying from.file.
  • `http{s}:// URLs are loaded as JSON from a web request, which was not previously supported but has been discussed.
  • regal:///capabilities/default loads the capabilities using ast.CapabilitiesForThisVersion()
  • regal:///capabilities/{engine} loads the latest (according to SemVer) capabilities version for the engine
  • regal:///capabilities/{engine}/{version} loads the specified capabilities version for the engine

Semantic versioning support is implemented using github.com/coreos/go-semver/semver, which is the same library OPA uses for its semver builtins.

The existing from.engine, from.file, and from.version will continue to work, but internally they are translated to URLs so that access to capabilities is consistent everywhere in Regal. from.url has been added as well.

These changes do appear to work, and enable Enterprise OPA specific builtins to appear in the VSCode plugin with only a config change.

Remaining work:

  • implement additional LSP tests to ensure capabilities loading works as expected
  • implement additional LSP tests to ensure capabilities hot-reload works as expected
  • document new capabilities.Lookup functionality
  • switch to fetching EOPA capabilities JSON during build
  • refactor LSP to avoid global lock for the rego package

Copy link
Member

@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.

Looks good so far 👍

pkg/capabilities/capabilities.go Outdated Show resolved Hide resolved
internal/lsp/rego/builtins.go Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
build/do.rq Outdated
# similar setups locally. Setting GIT_CONFIG=/dev/null in this case
# prevents this.

fetch_cmd := rq.template("sh -c 'GIT_CONFIG=/dev/null git archive --remote={{.remote | quote}} {{.ref}} {{.srcdir | quote}} | tar -x -C {{.destdir | quote}}'", templ)
Copy link
Member

Choose a reason for hiding this comment

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

No idea what's preferable, but if you'd consider it less of a hassle, you could grab the zip:
https://github.com/StyraInc/enterprise-opa/archive/refs/heads/main.zip

Copy link
Member Author

Choose a reason for hiding this comment

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

I was trying to find a good way to only have to download the subset of the repo that is needed, rather than the entire thing. If all else fails, I'll just do that, and/or clone the whole repo into /tmp or something.

I don't know why the git archive thing doesn't work. StackOverflow says it should. The man page leads me to believe it should. But run() is complaining about a mismatched ', and on top of that when I run it manually, git complains about trying to clone a git:// URL with the ssh:// protocol, which is just bizarre.

Copy link
Member

@anderseknert anderseknert left a comment

Choose a reason for hiding this comment

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

Looking good! Just some minor remarks. There were other changes in the past though that I'm curious to know more about. Were they not needed?

build/do.rq Outdated

{ rq.error(sprintf("\nstdout: %s\nstderr: %s\n", [eopa_tags_result.stdout, eopa_tags_result.stderr])) | eopa_tags_result.exitcode != 0 }

eopa_tags := {r[2] | r := eopa_tags_result.stdout[_]}
Copy link
Member

Choose a reason for hiding this comment

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

Can we use some ... in iteration instead? Here and on line 257. This file isn't lintable at this point in time, as we'd need something similar for rq as this PR provides for eopa. But that doesn't mean should ignore the best practices and idioms Regal recommends.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not actually sure how to use some ... in, can that handle additional clauses? I ended up having to filter the tag list down with further clauses.

Copy link
Member Author

Choose a reason for hiding this comment

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

hmm, yeah after 646a37d I'm not sure some ... in can work, based on reading the docs

Copy link
Member

Choose a reason for hiding this comment

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

It works anywhere:

eopa_tags := {t | some r in eopa_tags_result.stdout; t := r[2] ; not known_bad_tags[t]}

Copy link
Member Author

Choose a reason for hiding this comment

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

Ahh I see, I didn't realize you could use it in that way. I'll switch it over.

pkg/capabilities/embedded/eopa/v0.100.5.json Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
@charlesdaniels charlesdaniels marked this pull request as ready for review August 27, 2024 22:04
@charlesdaniels charlesdaniels force-pushed the charles/eopa-engine branch 2 times, most recently from e1d4aed to ec8c3a6 Compare August 28, 2024 19:54
Copy link
Member

@anderseknert anderseknert left a comment

Choose a reason for hiding this comment

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

Great work on this!

I left a couple of comments. You can ignore the style-related ones if you wish, as Regal itself will tend to most of them once we can lint .rq files :)

The rest should be considered however.

Very nice contribution!

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
build/do.rq Outdated Show resolved Hide resolved
internal/capabilities/capabilities_test.go Outdated Show resolved Hide resolved
@charlesdaniels
Copy link
Member Author

charlesdaniels commented Aug 29, 2024

I'm not sure why the tests are suddenly failing in CI? They pass on my machine, and none of the code the failing tests exercise was changed since the last commit where they passed.

I think server_test.go:405: timed out waiting for file diagnostics to be sent is also kinda interesting - 405 is a blank line, so I'm not sure how the test could be failing there.

@charlesdaniels
Copy link
Member Author

Interestingly, I do see a similar test failure when I run in an Alpine docker container (ARM64). This smells like some concurrency problem to me.

Copy link
Member

@anderseknert anderseknert left a comment

Choose a reason for hiding this comment

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

Thanks a lot for this Charles! I'll merge this as it is, and will have a look at the build issues reported when merged.

@anderseknert anderseknert merged commit 9cd3b05 into main Aug 29, 2024
0 of 3 checks passed
@anderseknert anderseknert deleted the charles/eopa-engine branch August 29, 2024 16:52
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