mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Cache for pod bindings
This commit is contained in:
		@@ -0,0 +1,87 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2017 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 persistentvolume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/api/core/v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// podBindingCache stores PV binding decisions per pod per node.
 | 
			
		||||
// Pod entries are removed when the Pod is deleted or updated to
 | 
			
		||||
// no longer be schedulable.
 | 
			
		||||
type PodBindingCache interface {
 | 
			
		||||
	// UpdateBindings will update the cache with the given bindings for the
 | 
			
		||||
	// pod and node.
 | 
			
		||||
	UpdateBindings(pod *v1.Pod, node string, bindings []*bindingInfo)
 | 
			
		||||
 | 
			
		||||
	// DeleteBindings will remove all cached bindings for the given pod.
 | 
			
		||||
	DeleteBindings(pod *v1.Pod)
 | 
			
		||||
 | 
			
		||||
	// GetBindings will return the cached bindings for the given pod and node.
 | 
			
		||||
	GetBindings(pod *v1.Pod, node string) []*bindingInfo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type podBindingCache struct {
 | 
			
		||||
	mutex sync.Mutex
 | 
			
		||||
 | 
			
		||||
	// Key = pod name
 | 
			
		||||
	// Value = nodeBindings
 | 
			
		||||
	bindings map[string]nodeBindings
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key = nodeName
 | 
			
		||||
// Value = array of bindingInfo
 | 
			
		||||
type nodeBindings map[string][]*bindingInfo
 | 
			
		||||
 | 
			
		||||
func NewPodBindingCache() PodBindingCache {
 | 
			
		||||
	return &podBindingCache{bindings: map[string]nodeBindings{}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *podBindingCache) DeleteBindings(pod *v1.Pod) {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	defer c.mutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	podName := getPodName(pod)
 | 
			
		||||
	delete(c.bindings, podName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *podBindingCache) UpdateBindings(pod *v1.Pod, node string, bindings []*bindingInfo) {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	defer c.mutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	podName := getPodName(pod)
 | 
			
		||||
	nodeBinding, ok := c.bindings[podName]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		nodeBinding = nodeBindings{}
 | 
			
		||||
		c.bindings[podName] = nodeBinding
 | 
			
		||||
	}
 | 
			
		||||
	nodeBinding[node] = bindings
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *podBindingCache) GetBindings(pod *v1.Pod, node string) []*bindingInfo {
 | 
			
		||||
	c.mutex.Lock()
 | 
			
		||||
	defer c.mutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	podName := getPodName(pod)
 | 
			
		||||
	nodeBindings, ok := c.bindings[podName]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return nodeBindings[node]
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,112 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2017 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 persistentvolume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/api/core/v1"
 | 
			
		||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestUpdateGetBindings(t *testing.T) {
 | 
			
		||||
	scenarios := map[string]struct {
 | 
			
		||||
		updateBindings []*bindingInfo
 | 
			
		||||
		updatePod      string
 | 
			
		||||
		updateNode     string
 | 
			
		||||
 | 
			
		||||
		getBindings []*bindingInfo
 | 
			
		||||
		getPod      string
 | 
			
		||||
		getNode     string
 | 
			
		||||
	}{
 | 
			
		||||
		"no-pod": {
 | 
			
		||||
			getPod:  "pod1",
 | 
			
		||||
			getNode: "node1",
 | 
			
		||||
		},
 | 
			
		||||
		"no-node": {
 | 
			
		||||
			updatePod:      "pod1",
 | 
			
		||||
			updateNode:     "node1",
 | 
			
		||||
			updateBindings: []*bindingInfo{},
 | 
			
		||||
			getPod:         "pod1",
 | 
			
		||||
			getNode:        "node2",
 | 
			
		||||
		},
 | 
			
		||||
		"binding-exists": {
 | 
			
		||||
			updatePod:      "pod1",
 | 
			
		||||
			updateNode:     "node1",
 | 
			
		||||
			updateBindings: []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}},
 | 
			
		||||
			getPod:         "pod1",
 | 
			
		||||
			getNode:        "node1",
 | 
			
		||||
			getBindings:    []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for name, scenario := range scenarios {
 | 
			
		||||
		cache := NewPodBindingCache()
 | 
			
		||||
 | 
			
		||||
		// Perform updates
 | 
			
		||||
		updatePod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: scenario.updatePod, Namespace: "ns"}}
 | 
			
		||||
		cache.UpdateBindings(updatePod, scenario.updateNode, scenario.updateBindings)
 | 
			
		||||
 | 
			
		||||
		// Verify updated bindings
 | 
			
		||||
		bindings := cache.GetBindings(updatePod, scenario.updateNode)
 | 
			
		||||
		if !reflect.DeepEqual(bindings, scenario.updateBindings) {
 | 
			
		||||
			t.Errorf("Test %v failed: returned bindings after update different. Got %+v, expected %+v", name, bindings, scenario.updateBindings)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Get bindings
 | 
			
		||||
		getPod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: scenario.getPod, Namespace: "ns"}}
 | 
			
		||||
		bindings = cache.GetBindings(getPod, scenario.getNode)
 | 
			
		||||
		if !reflect.DeepEqual(bindings, scenario.getBindings) {
 | 
			
		||||
			t.Errorf("Test %v failed: unexpected bindings returned. Got %+v, expected %+v", name, bindings, scenario.updateBindings)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeleteBindings(t *testing.T) {
 | 
			
		||||
	initialBindings := []*bindingInfo{{pvc: &v1.PersistentVolumeClaim{ObjectMeta: metav1.ObjectMeta{Name: "pvc1"}}}}
 | 
			
		||||
	cache := NewPodBindingCache()
 | 
			
		||||
 | 
			
		||||
	pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod1", Namespace: "ns"}}
 | 
			
		||||
 | 
			
		||||
	// Get nil bindings
 | 
			
		||||
	bindings := cache.GetBindings(pod, "node1")
 | 
			
		||||
	if bindings != nil {
 | 
			
		||||
		t.Errorf("Test failed: expected inital nil bindings, got %+v", bindings)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Delete nothing
 | 
			
		||||
	cache.DeleteBindings(pod)
 | 
			
		||||
 | 
			
		||||
	// Perform updates
 | 
			
		||||
	cache.UpdateBindings(pod, "node1", initialBindings)
 | 
			
		||||
 | 
			
		||||
	// Get bindings
 | 
			
		||||
	bindings = cache.GetBindings(pod, "node1")
 | 
			
		||||
	if !reflect.DeepEqual(bindings, initialBindings) {
 | 
			
		||||
		t.Errorf("Test failed: expected bindings %+v, got %+v", initialBindings, bindings)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Delete
 | 
			
		||||
	cache.DeleteBindings(pod)
 | 
			
		||||
 | 
			
		||||
	// Get bindings
 | 
			
		||||
	bindings = cache.GetBindings(pod, "node1")
 | 
			
		||||
	if bindings != nil {
 | 
			
		||||
		t.Errorf("Test failed: expected nil bindings, got %+v", bindings)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user