Skip to content

Commit

Permalink
remove handle
Browse files Browse the repository at this point in the history
  • Loading branch information
Gekko0114 committed Jan 5, 2024
1 parent c967daf commit 947ad1d
Show file tree
Hide file tree
Showing 44 changed files with 403 additions and 397 deletions.
21 changes: 18 additions & 3 deletions examples/advanced/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,30 @@ import (
_ "github.com/wasilibs/nottinygc"

"sigs.k8s.io/kube-scheduler-wasm-extension/examples/advanced/plugin"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/config"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/enqueue"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/eventrecorder"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/klog"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/prescore"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/score"
)

// main is compiled to an exported Wasm function named "_start", called by the
// Wasm scheduler plugin during initialization.
func main() {
enqueue.SetPlugin(plugin.New)
prescore.SetPlugin(plugin.New)
score.SetPlugin(plugin.New)
// The plugin package uses only normal Go code, which allows it to be
// unit testable via `tinygo test -target=wasi` as well normal `go test`.
//
// The real implementations, such as `config.Get()` use Wasm host functions
// (go:wasmimport), which cannot be tested with `tinygo test -target=wasi`.
plugin, err := plugin.New(klog.Get(), config.Get(), eventrecorder.Get())
if err != nil {
panic(err)
}
// Instead of using `plugin.Set`, this configures only the interfaces
// implemented by the plugin. The Wasm host only calls functions imported,
// so this prevents additional overhead.
enqueue.SetPlugin(plugin)
prescore.SetPlugin(plugin)
score.SetPlugin(plugin)
}
Binary file modified examples/advanced/main.wasm
Binary file not shown.
16 changes: 7 additions & 9 deletions examples/advanced/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import (

"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api/proto"
handleapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle/api"
eventrecorder "sigs.k8s.io/kube-scheduler-wasm-extension/guest/eventrecorder/api"
klog "sigs.k8s.io/kube-scheduler-wasm-extension/guest/klog/api"
)

Expand All @@ -50,9 +50,9 @@ import (
// - The reverse field inverts the score. For example, when `reverse == true`
// a numeric match gets a results in a lower score than a match.
type NodeNumber struct {
reverse bool
klog klog.Klog
handle handleapi.Handle
reverse bool
klog klog.Klog
eventrecorder eventrecorder.EventRecorder
}

const (
Expand All @@ -75,13 +75,11 @@ func (pl *NodeNumber) EventsToRegister() []api.ClusterEvent {

// PreScore implements api.PreScorePlugin
func (pl *NodeNumber) PreScore(state api.CycleState, pod proto.Pod, _ proto.NodeList) *api.Status {
h := pl.handle
recorder := h.EventRecorder()
pl.klog.InfoS("execute PreScore on NodeNumber plugin", "pod", klog.KObj(pod))

podnum, ok := lastNumber(pod.Spec().GetNodeName())
if !ok {
recorder.Eventf(pod, nil, "PreScore", "not match lastNumber", "Skip", "")
pl.eventrecorder.Eventf(pod, nil, "PreScore", "not match lastNumber", "Skip", "")
return nil // return success even if its suffix is non-number.
}

Expand Down Expand Up @@ -132,15 +130,15 @@ func lastNumber(str string) (uint8, bool) {
//
// Note: This accepts config instead of implicitly calling config.Get for
// testing.
func New(klog klog.Klog, jsonConfig []byte, h handleapi.Handle) (api.Plugin, error) {
func New(klog klog.Klog, jsonConfig []byte, eventrecorder eventrecorder.EventRecorder) (*NodeNumber, error) {
var args nodeNumberArgs
if jsonConfig != nil {
if err := json.Unmarshal(jsonConfig, &args); err != nil {
return nil, fmt.Errorf("decode arg into NodeNumberArgs: %w", err)
}
klog.Info("NodeNumberArgs is successfully applied")
}
return &NodeNumber{klog: klog, reverse: args.Reverse, handle: h}, nil
return &NodeNumber{klog: klog, reverse: args.Reverse, eventrecorder: eventrecorder}, nil
}

type nodeNumberArgs struct {
Expand Down
4 changes: 2 additions & 2 deletions examples/advanced/plugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api/proto"
handleapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle/api"
eventrecorderapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/eventrecorder/api"
klogapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/klog/api"
protoapi "sigs.k8s.io/kube-scheduler-wasm-extension/kubernetes/proto/api"
)
Expand Down Expand Up @@ -53,7 +53,7 @@ func Test_NodeNumber(t *testing.T) {
expectedMatch = !expectedMatch
}
t.Run(name, func(t *testing.T) {
plugin := &NodeNumber{klog: klogapi.UnimplementedKlog{}, reverse: reverse, handle: handleapi.UnimplementedHandle{}}
plugin := &NodeNumber{klog: klogapi.UnimplementedKlog{}, reverse: reverse, eventrecorder: eventrecorderapi.UnimplementedEventRecorder{}}
state := testCycleState{}

status := plugin.PreScore(state, tc.pod, nil)
Expand Down
22 changes: 12 additions & 10 deletions examples/nodenumber/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api/proto"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/config"
handleapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/eventrecorder"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/klog"
klogapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/klog/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/plugin"
Expand All @@ -36,17 +36,21 @@ var args nodeNumberArgs
// main is compiled to a WebAssembly function named "_start", called by the
// wasm scheduler plugin during initialization.
func main() {
if jsonConfig := config.Get(); jsonConfig != nil {
p, err := New(klog.Get(), config.Get())
if err != nil {
panic(err)
}
plugin.Set(p)
}

func New(klog klogapi.Klog, jsonConfig []byte) (api.Plugin, error) {
if jsonConfig != nil {
if err := json.Unmarshal(jsonConfig, &args); err != nil {
panic(fmt.Errorf("decode arg into NodeNumberArgs: %w", err))
}
klog.Info("NodeNumberArgs is successfully applied")
}
plugin.Set(New)
}

func New(klog klogapi.Klog, jsonConfig []byte, h handleapi.Handle) (api.Plugin, error) {
return &NodeNumber{reverse: args.Reverse, handle: h}, nil
return &NodeNumber{reverse: args.Reverse}, nil
}

// NodeNumber is an example plugin that favors nodes that share a numerical
Expand All @@ -63,7 +67,6 @@ func New(klog klogapi.Klog, jsonConfig []byte, h handleapi.Handle) (api.Plugin,
// a numeric match gets a results in a lower score than a match.
type NodeNumber struct {
reverse bool
handle handleapi.Handle
}

type nodeNumberArgs struct {
Expand All @@ -90,8 +93,7 @@ func (pl *NodeNumber) EventsToRegister() []api.ClusterEvent {

// PreScore implements api.PreScorePlugin
func (pl *NodeNumber) PreScore(state api.CycleState, pod proto.Pod, _ proto.NodeList) *api.Status {
h := pl.handle
recorder := h.EventRecorder()
recorder := eventrecorder.Get()

klog.InfoS("execute PreScore on NodeNumber plugin", "pod", klog.KObj(pod))

Expand Down
Binary file modified examples/nodenumber/main.wasm
Binary file not shown.
4 changes: 1 addition & 3 deletions examples/nodenumber/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api/proto"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle"
protoapi "sigs.k8s.io/kube-scheduler-wasm-extension/kubernetes/proto/api"
)

Expand Down Expand Up @@ -52,8 +51,7 @@ func Test_NodeNumber(t *testing.T) {
expectedMatch = !expectedMatch
}
t.Run(name, func(t *testing.T) {
handle := handle.NewFrameworkHandle()
plugin := &NodeNumber{reverse: reverse, handle: handle}
plugin := &NodeNumber{reverse: reverse}
state := testCycleState{}
status := plugin.PreScore(state, tc.pod, nil)
if status != nil {
Expand Down
7 changes: 7 additions & 0 deletions guest/api/proto/proto.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ package proto

import api "sigs.k8s.io/kube-scheduler-wasm-extension/kubernetes/proto/api"

type KObject interface {
Metadata

GetKind() string
GetApiVersion() string
}

// Metadata are fields on top-level types, used for logging and metrics.
type Metadata interface {
GetUid() string
Expand Down
20 changes: 5 additions & 15 deletions guest/bind/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,9 @@ package bind

import (
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/config"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle"
handleapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/internal/cyclestate"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/internal/imports"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/internal/plugin"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/klog"
)

// bind is the current plugin assigned with SetPlugin.
Expand All @@ -35,25 +31,19 @@ var bind api.BindPlugin
//
// func main() {
// plugin := bindPlugin{}
// bind.SetPlugin(func(klog klogapi.Klog, jsonConfig []byte, h handleapi.Handle) (api.Plugin, error) { return plugin, nil })
// bind.SetPlugin(plugin)
// }
//
// type bindPlugin struct{}
//
// func (bindPlugin) Bind(state api.CycleState, pod proto.Pod, nodeName string) (status *api.Status) {
// // Write state you need on Bind
// }
func SetPlugin(pluginFactory handleapi.PluginFactory) {
handle := handle.NewFrameworkHandle()
p, err := pluginFactory(klog.Get(), config.Get(), handle)
if err != nil {
panic(err)
}
var ok bool
bind, ok = p.(api.BindPlugin)
if !ok || bind == nil {
panic("nil BindPlugin or a plugin is not compatible with BindPlugin type")
func SetPlugin(bindPlugin api.BindPlugin) {
if bindPlugin == nil {
panic("nil bindPlugin")
}
bind = bindPlugin
plugin.MustSet(bind)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
limitations under the License.
*/

package clusterevent
package enqueue

import "sigs.k8s.io/kube-scheduler-wasm-extension/guest/api"

// sizeEncodedClusterEvent is the size in bytes to encode
// framework.ClusterEvent with 32-bit little endian gvk and ActionType
const sizeEncodedClusterEvent = 4 + 4

func EncodeClusterEvents(input []api.ClusterEvent) []byte {
func encodeClusterEvents(input []api.ClusterEvent) []byte {
size := len(input) * sizeEncodedClusterEvent
if size == 0 {
return nil // don't allocate an empty slice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
limitations under the License.
*/

package clusterevent
package enqueue

import (
"bytes"
Expand Down Expand Up @@ -72,7 +72,7 @@ func TestEncodeClusterEvents(t *testing.T) {

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
encoded := EncodeClusterEvents(tc.input)
encoded := encodeClusterEvents(tc.input)
if want, have := tc.expected, encoded; (want == nil && have != nil) || !bytes.Equal(want, have) {
t.Fatalf("unexpected value: %v != %v", want, have)
}
Expand Down
23 changes: 6 additions & 17 deletions guest/enqueue/enqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,19 @@ import (
"unsafe"

"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/config"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/enqueue/clusterevent"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle"
handleapi "sigs.k8s.io/kube-scheduler-wasm-extension/guest/handle/api"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/internal/plugin"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/klog"
)

// enqueue is the current plugin assigned with SetPlugin.
var enqueue api.EnqueueExtensions

// SetPlugin is exposed to prevent package cycles.
func SetPlugin(pluginFactory handleapi.PluginFactory) {
handle := handle.NewFrameworkHandle()
p, err := pluginFactory(klog.Get(), config.Get(), handle)
if err != nil {
panic(err)
func SetPlugin(enqueueExtensions api.EnqueueExtensions) {
if enqueueExtensions == nil {
panic("nil enqueueExtensions")
}
var ok bool
enqueue, ok = p.(api.EnqueueExtensions)
if !ok || enqueue == nil {
panic("nil EnqueueExtensions or a plugin is not compatible with EnqueueExtensions type")
}
plugin.MustSet(enqueue)
enqueue = enqueueExtensions
plugin.MustSet(enqueueExtensions)
}

// prevent unused lint errors (lint is run with normal go).
Expand All @@ -66,7 +55,7 @@ func _enqueue() {

// If plugin returned clusterEvents, encode them and call the host with the
// count and memory region.
encoded := clusterevent.EncodeClusterEvents(clusterEvents)
encoded := encodeClusterEvents(clusterEvents)
if encoded != nil {
ptr := uint32(uintptr(unsafe.Pointer(&encoded[0])))
size := uint32(len(encoded))
Expand Down
33 changes: 33 additions & 0 deletions guest/eventrecorder/api/eventrecorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package api

import (
proto "sigs.k8s.io/kube-scheduler-wasm-extension/guest/api/proto"
)

// EventRecorder is a recorder that sends events to the host environment via eventrecorder.eventf.
type EventRecorder interface {
// Eventf calls EventRecorder.Eventf.
Eventf(regarding proto.KObject, related proto.KObject, eventtype, reason, action, note string)
}

type UnimplementedEventRecorder struct{}

// Eventf implements events.EventRecorder.Eventf()
func (UnimplementedEventRecorder) Eventf(regarding proto.KObject, related proto.KObject, eventtype, reason, action, note string) {
}
38 changes: 38 additions & 0 deletions guest/eventrecorder/api/eventrecorder_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package api_test

import (
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/api/proto"
"sigs.k8s.io/kube-scheduler-wasm-extension/guest/eventrecorder/api"
)

var (
eventrecorder api.EventRecorder = api.UnimplementedEventRecorder{}
pod proto.Pod
node proto.Node
)

func ExampleEventRecorder() {
//
eventrecorder.Eventf(pod, pod, "event", "reason", "action", "note")

eventrecorder.Eventf(node, node, "event", "reason", "action", "note")

// Output:
//
}
Loading

0 comments on commit 947ad1d

Please sign in to comment.