Merge pull request #82951 from ahg-g/ahg-context

Updated ContextData and PluginContext with Clone methods.
This commit is contained in:
Kubernetes Prow Robot 2019-09-23 14:55:49 -07:00 committed by GitHub
commit 05aaeac8b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 4 deletions

View File

@ -37,6 +37,17 @@ func (mc CommunicatingPlugin) Name() string {
return Name return Name
} }
type contextData struct {
data string
}
func (f *contextData) Clone() framework.ContextData {
copy := &contextData{
data: f.data,
}
return copy
}
// Reserve is the functions invoked by the framework at "reserve" extension point. // Reserve is the functions invoked by the framework at "reserve" extension point.
func (mc CommunicatingPlugin) Reserve(pc *framework.PluginContext, pod *v1.Pod, nodeName string) *framework.Status { func (mc CommunicatingPlugin) Reserve(pc *framework.PluginContext, pod *v1.Pod, nodeName string) *framework.Status {
if pod == nil { if pod == nil {
@ -44,7 +55,7 @@ func (mc CommunicatingPlugin) Reserve(pc *framework.PluginContext, pod *v1.Pod,
} }
if pod.Name == "my-test-pod" { if pod.Name == "my-test-pod" {
pc.Lock() pc.Lock()
pc.Write(framework.ContextKey(pod.Name), "never bind") pc.Write(framework.ContextKey(pod.Name), &contextData{data: "never bind"})
pc.Unlock() pc.Unlock()
} }
return nil return nil
@ -57,8 +68,10 @@ func (mc CommunicatingPlugin) PreBind(pc *framework.PluginContext, pod *v1.Pod,
} }
pc.RLock() pc.RLock()
defer pc.RUnlock() defer pc.RUnlock()
if v, e := pc.Read(framework.ContextKey(pod.Name)); e == nil && v == "never bind" { if v, e := pc.Read(framework.ContextKey(pod.Name)); e == nil {
return framework.NewStatus(framework.Unschedulable, "pod is not permitted") if value, ok := v.(*contextData); ok && value.data == "never bind" {
return framework.NewStatus(framework.Unschedulable, "pod is not permitted")
}
} }
return nil return nil
} }

View File

@ -43,6 +43,7 @@ filegroup(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = [ srcs = [
"context_test.go",
"framework_test.go", "framework_test.go",
"interface_test.go", "interface_test.go",
"registry_test.go", "registry_test.go",

View File

@ -27,7 +27,12 @@ const (
) )
// ContextData is a generic type for arbitrary data stored in PluginContext. // ContextData is a generic type for arbitrary data stored in PluginContext.
type ContextData interface{} type ContextData interface {
// Clone is an interface to make a copy of ContextData. For performance reasons,
// clone should make shallow copies for members (e.g., slices or maps) that are not
// impacted by PreFilter's optional AddPod/RemovePod methods.
Clone() ContextData
}
// ContextKey is the type of keys stored in PluginContext. // ContextKey is the type of keys stored in PluginContext.
type ContextKey string type ContextKey string
@ -48,6 +53,15 @@ func NewPluginContext() *PluginContext {
} }
} }
// Clone creates a copy of PluginContext and returns its pointer.
func (c *PluginContext) Clone() *PluginContext {
copy := NewPluginContext()
for k, v := range c.storage {
copy.Write(k, v.Clone())
}
return copy
}
// Read retrieves data with the given "key" from PluginContext. If the key is not // Read retrieves data with the given "key" from PluginContext. If the key is not
// present an error is returned. // present an error is returned.
// This function is not thread safe. In multi-threaded code, lock should be // This function is not thread safe. In multi-threaded code, lock should be

View File

@ -0,0 +1,66 @@
/*
Copyright 2019 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 v1alpha1
import (
"testing"
)
type fakeData struct {
data string
}
func (f *fakeData) Clone() ContextData {
copy := &fakeData{
data: f.data,
}
return copy
}
func TestPluginContextClone(t *testing.T) {
var key ContextKey = "key"
data1 := "value1"
data2 := "value2"
pc := NewPluginContext()
originalValue := &fakeData{
data: data1,
}
pc.Write(key, originalValue)
pcCopy := pc.Clone()
valueCopy, err := pcCopy.Read(key)
if err != nil {
t.Errorf("failed to read copied value: %v", err)
}
if v, ok := valueCopy.(*fakeData); ok && v.data != data1 {
t.Errorf("clone failed, got %q, expected %q", v.data, data1)
}
originalValue.data = data2
original, err := pc.Read(key)
if err != nil {
t.Errorf("failed to read original value: %v", err)
}
if v, ok := original.(*fakeData); ok && v.data != data2 {
t.Errorf("original value should change, got %q, expected %q", v.data, data2)
}
if v, ok := valueCopy.(*fakeData); ok && v.data != data1 {
t.Errorf("cloned copy should not change, got %q, expected %q", v.data, data1)
}
}