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

guest: add plugin.Set for simpler example and fixes URL parsing #69

Merged
merged 1 commit into from
Aug 5, 2023

Conversation

codefromthecrypt
Copy link
Contributor

@codefromthecrypt codefromthecrypt commented Aug 1, 2023

What type of PR is this?

/kind cleanup

What this PR does / why we need it:

This adds plugin.Set which makes it easier to write plugins. This also makes the example that uses it simpler by avoiding nottinygo. This is simpler because it reduces the amount of flags used, as well a flat package is easier to write. However, this can't be tested with tinygo anymore, and is slower.

Hence, this adds an "advanced" example with the former logic, which is more verbose and tricky, but faster.

Which issue(s) this PR fixes:

NONE

Special notes for your reviewer:

This also fixes some bugs in URL parsing due to some logic not copied over from dapr. Notably, the original logic handled relative paths and better error messages. This also simplifies the logic further as we were parsing into URL type, just to convert it back to a string! Also, we started using testify by accident where that's not used anywhere else.

cc @evacchi sorry I didn't look closely at your earlier PR or would have caught this!

Does this PR introduce a user-facing change?

NONE

What are the benchmark results of this change?

You can see below that the simple plugin runs >5x slower than the advanced. However, because it is still less than millisecond, some users may be ok with this.

goos: darwin
goarch: arm64
pkg: sigs.k8s.io/kube-scheduler-wasm-extension/internal/e2e/scheduler
                                   │  before.txt  │       now.txt        │
                                   │    sec/op    │    sec/op      vs base   │
Example_NodeNumber/New-12            75.08m ±  2%
Example_NodeNumber/Run-12            47.86µ ± 10%
Example_NodeNumber/Simple/New-12                    62.23m ±   1%
Example_NodeNumber/Simple/Run-12                    188.6µ ± 109%
Example_NodeNumber/Advanced/New-12                  73.61m ±   2%
Example_NodeNumber/Advanced/Run-12                  47.03µ ±   2%
geomean                              1.895m         2.525m         ? ¹ ²
¹ benchmark set differs from baseline; geomeans may not be comparable
² ratios must be >0 to compute geomean

@k8s-ci-robot k8s-ci-robot added kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Aug 1, 2023
protoapi "sigs.k8s.io/kube-scheduler-wasm-extension/kubernetes/proto/api"
)

func Test_NodeNumber(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

these tests still work in normal Go. In fact a lot of SDKs only test with Go and never TinyGo, probably because it is too complicated.

That said, I think the guest SDK itself and advanced example should stil work with tinygo test -target=wasi (and they do).

if score == nil { // Then, the user didn't define one.
// This is likely caused by use of plugin.Set(p), where 'p' didn't
// implement ScorePlugin: return success and score zero.
return 0
Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, if you use the simple plugin.Set(plugin) we have to return something for score. Returning zero here (both status and score). There's no way to avoid this in simple mode because the host will call the function regardless. Only other way is complicated, but exposing a bitflag of functions that could be called.

I think that's too much, so if someone needs to assign score, really they should implement it. If they must not call score, they should not use plugin.Set(p) as the docs mention.

@@ -79,22 +76,6 @@ func NewFromConfig(ctx context.Context, config PluginConfig) (framework.Plugin,
}
}

func readFromURI(ctx context.Context, u string) ([]byte, error) {
uri, err := url.ParseRequestURI(u)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the problem was eagerly parsing here (not done in dapr where some logic was copied from). This breaks relative paths like file://../../foo.wasm. I noticed this running make profile

Copy link
Contributor

Choose a reason for hiding this comment

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

ah right. This was not caught by other tests because they were eagerly converting to an absolute file:///


func Test_httpGet(t *testing.T) {
wasmBinary := wasmMagicNumber
wasmBinary = append(wasmBinary, 0x00, 0x00, 0x00, 0x00)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ps I have no idea why we are appending 4 bytes as this was copied from before.. possibly to give some more data to compress?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it was padded to make it a valid wasmBinary, but this could be misguided. I didn't think of verifying without the padding.

@k8s-ci-robot k8s-ci-robot added size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Aug 1, 2023
@codefromthecrypt
Copy link
Contributor Author

added polish, mostly README

Copy link
Member

@sanposhiho sanposhiho left a comment

Choose a reason for hiding this comment

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

Thanks, left small nits.

/approve

scheduler/plugin/wasm.go Outdated Show resolved Hide resolved
// such as "file://../../path/to/plugin.wasm"
func getURL(ctx context.Context, url string) ([]byte, error) {
if url == "" {
return nil, errors.New("missing url")
Copy link
Member

Choose a reason for hiding this comment

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

This error is going to appear to users. So, can we make it a bit more fancy like "GuestURL is required in the plugin configuration"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved the missing one higher up and backfilled a test, so that they are like the others (prefixed wasm: some error)

guest/plugin/plugin.go Show resolved Hide resolved
This adds `plugin.Set` which makes it easier to write plugins. This also
makes the example that uses it simpler by avoiding nottinygo. This is
simpler because it reduces the amount of flags used, as well a flat
package is easier to write. However, this can't be tested with tinygo
anymore, and is slower.

Hence, this adds an "advanced" example with the former logic, which is
more verbose and tricky, but faster.

This also fixes some bugs in URL parsing due to some logic not copied
over from dapr. Notably, the original logic handled relative paths and
better error messages. This also simplifies the logic further as we were
parsing into URL type, just to convert it back to a string!

Signed-off-by: Adrian Cole <[email protected]>
@codefromthecrypt
Copy link
Contributor Author

squashed and ready, thanks for the look @sanposhiho!

Copy link
Member

@sanposhiho sanposhiho left a comment

Choose a reason for hiding this comment

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

/approve
/lgtm

Thanks!

guestBin, err := readFromURI(ctx, config.GuestURL)
url := config.GuestURL
if url == "" {
return nil, errors.New("wasm: guestURL is required")
Copy link
Member

Choose a reason for hiding this comment

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

👍

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 5, 2023
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: codefromthecrypt, sanposhiho

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [codefromthecrypt,sanposhiho]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot merged commit 293aa59 into kubernetes-sigs:main Aug 5, 2023
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/cleanup Categorizes issue or PR as related to cleaning up code, process, or technical debt. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants