mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
Fix node authorizer index recomputation
This commit is contained in:
parent
cad44602e1
commit
d8c00b7f52
@ -189,7 +189,7 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
|
|||||||
neighborsToRemove = append(neighborsToRemove, neighbor)
|
neighborsToRemove = append(neighborsToRemove, neighbor)
|
||||||
} else {
|
} else {
|
||||||
// recompute the destination edge index on this neighbor
|
// recompute the destination edge index on this neighbor
|
||||||
neighborsToRecompute = append(neighborsToRemove, neighbor)
|
neighborsToRecompute = append(neighborsToRecompute, neighbor)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
@ -17,10 +17,17 @@ limitations under the License.
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeleteEdges_locked(t *testing.T) {
|
func TestDeleteEdges_locked(t *testing.T) {
|
||||||
@ -176,3 +183,229 @@ func TestDeleteEdges_locked(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIndex(t *testing.T) {
|
||||||
|
g := NewGraph()
|
||||||
|
g.destinationEdgeThreshold = 3
|
||||||
|
|
||||||
|
a := NewAuthorizer(g, nil, nil).(*NodeAuthorizer)
|
||||||
|
|
||||||
|
addPod := func(podNumber, nodeNumber int) {
|
||||||
|
t.Helper()
|
||||||
|
nodeName := fmt.Sprintf("node%d", nodeNumber)
|
||||||
|
podName := fmt.Sprintf("pod%d", podNumber)
|
||||||
|
pod := &corev1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: podName, Namespace: "ns", UID: types.UID(fmt.Sprintf("pod%duid1", podNumber))},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
NodeName: nodeName,
|
||||||
|
ServiceAccountName: "sa1",
|
||||||
|
DeprecatedServiceAccount: "sa1",
|
||||||
|
Volumes: []corev1.Volume{
|
||||||
|
{Name: "volume1", VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "cm1"}}}},
|
||||||
|
{Name: "volume2", VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "cm2"}}}},
|
||||||
|
{Name: "volume3", VolumeSource: corev1.VolumeSource{ConfigMap: &corev1.ConfigMapVolumeSource{LocalObjectReference: corev1.LocalObjectReference{Name: "cm3"}}}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
g.AddPod(pod)
|
||||||
|
if ok, err := a.hasPathFrom(nodeName, configMapVertexType, "ns", "cm1"); err != nil || !ok {
|
||||||
|
t.Errorf("expected path from %s to cm1, got %v, %v", nodeName, ok, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toString := func(id int) string {
|
||||||
|
for _, namespaceName := range g.vertices {
|
||||||
|
for _, nameVertex := range namespaceName {
|
||||||
|
for _, vertex := range nameVertex {
|
||||||
|
if vertex.id == id {
|
||||||
|
return vertex.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
expectGraph := func(expect map[string][]string) {
|
||||||
|
t.Helper()
|
||||||
|
actual := map[string][]string{}
|
||||||
|
for _, node := range g.graph.Nodes() {
|
||||||
|
sortedTo := []string{}
|
||||||
|
for _, to := range g.graph.From(node) {
|
||||||
|
sortedTo = append(sortedTo, toString(to.ID()))
|
||||||
|
}
|
||||||
|
sort.Strings(sortedTo)
|
||||||
|
actual[toString(node.ID())] = sortedTo
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(expect, actual) {
|
||||||
|
e, _ := json.MarshalIndent(expect, "", " ")
|
||||||
|
a, _ := json.MarshalIndent(actual, "", " ")
|
||||||
|
t.Errorf("expected graph:\n%s\ngot:\n%s", string(e), string(a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expectIndex := func(expect map[string][]string) {
|
||||||
|
t.Helper()
|
||||||
|
actual := map[string][]string{}
|
||||||
|
for from, to := range g.destinationEdgeIndex {
|
||||||
|
sortedValues := []string{}
|
||||||
|
for member := range to.members {
|
||||||
|
sortedValues = append(sortedValues, toString(member))
|
||||||
|
}
|
||||||
|
sort.Strings(sortedValues)
|
||||||
|
actual[toString(from)] = sortedValues
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(expect, actual) {
|
||||||
|
e, _ := json.MarshalIndent(expect, "", " ")
|
||||||
|
a, _ := json.MarshalIndent(actual, "", " ")
|
||||||
|
t.Errorf("expected index:\n%s\ngot:\n%s", string(e), string(a))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; i <= g.destinationEdgeThreshold; i++ {
|
||||||
|
addPod(i, i)
|
||||||
|
if i < g.destinationEdgeThreshold {
|
||||||
|
// if we're under the threshold, no index expected
|
||||||
|
expectIndex(map[string][]string{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expectGraph(map[string][]string{
|
||||||
|
"node:node1": {},
|
||||||
|
"node:node2": {},
|
||||||
|
"node:node3": {},
|
||||||
|
"pod:ns/pod1": {"node:node1"},
|
||||||
|
"pod:ns/pod2": {"node:node2"},
|
||||||
|
"pod:ns/pod3": {"node:node3"},
|
||||||
|
"configmap:ns/cm1": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
"configmap:ns/cm2": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
"configmap:ns/cm3": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
"serviceAccount:ns/sa1": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
})
|
||||||
|
expectIndex(map[string][]string{
|
||||||
|
"configmap:ns/cm1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm2": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm3": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"serviceAccount:ns/sa1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
})
|
||||||
|
|
||||||
|
// delete one to drop below the threshold
|
||||||
|
g.DeletePod("pod1", "ns")
|
||||||
|
expectGraph(map[string][]string{
|
||||||
|
"node:node2": {},
|
||||||
|
"node:node3": {},
|
||||||
|
"pod:ns/pod2": {"node:node2"},
|
||||||
|
"pod:ns/pod3": {"node:node3"},
|
||||||
|
"configmap:ns/cm1": {"pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
"configmap:ns/cm2": {"pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
"configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3"},
|
||||||
|
})
|
||||||
|
expectIndex(map[string][]string{})
|
||||||
|
|
||||||
|
// add two to get above the threshold
|
||||||
|
addPod(1, 1)
|
||||||
|
addPod(4, 1)
|
||||||
|
expectGraph(map[string][]string{
|
||||||
|
"node:node1": {},
|
||||||
|
"node:node2": {},
|
||||||
|
"node:node3": {},
|
||||||
|
"pod:ns/pod1": {"node:node1"},
|
||||||
|
"pod:ns/pod2": {"node:node2"},
|
||||||
|
"pod:ns/pod3": {"node:node3"},
|
||||||
|
"pod:ns/pod4": {"node:node1"},
|
||||||
|
"configmap:ns/cm1": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm2": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm3": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"serviceAccount:ns/sa1": {"pod:ns/pod1", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
})
|
||||||
|
expectIndex(map[string][]string{
|
||||||
|
"configmap:ns/cm1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm2": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm3": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"serviceAccount:ns/sa1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
})
|
||||||
|
|
||||||
|
// delete one to remain above the threshold
|
||||||
|
g.DeletePod("pod1", "ns")
|
||||||
|
expectGraph(map[string][]string{
|
||||||
|
"node:node1": {},
|
||||||
|
"node:node2": {},
|
||||||
|
"node:node3": {},
|
||||||
|
"pod:ns/pod2": {"node:node2"},
|
||||||
|
"pod:ns/pod3": {"node:node3"},
|
||||||
|
"pod:ns/pod4": {"node:node1"},
|
||||||
|
"configmap:ns/cm1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm2": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
})
|
||||||
|
expectIndex(map[string][]string{
|
||||||
|
"configmap:ns/cm1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm2": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm3": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"serviceAccount:ns/sa1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Set node->configmap references
|
||||||
|
g.SetNodeConfigMap("node1", "cm1", "ns")
|
||||||
|
g.SetNodeConfigMap("node2", "cm1", "ns")
|
||||||
|
g.SetNodeConfigMap("node3", "cm1", "ns")
|
||||||
|
expectGraph(map[string][]string{
|
||||||
|
"node:node1": {},
|
||||||
|
"node:node2": {},
|
||||||
|
"node:node3": {},
|
||||||
|
"pod:ns/pod2": {"node:node2"},
|
||||||
|
"pod:ns/pod3": {"node:node3"},
|
||||||
|
"pod:ns/pod4": {"node:node1"},
|
||||||
|
"configmap:ns/cm1": {"node:node1", "node:node2", "node:node3", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm2": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
})
|
||||||
|
expectIndex(map[string][]string{
|
||||||
|
"configmap:ns/cm1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm2": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm3": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"serviceAccount:ns/sa1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update node->configmap reference
|
||||||
|
g.SetNodeConfigMap("node1", "cm2", "ns")
|
||||||
|
expectGraph(map[string][]string{
|
||||||
|
"node:node1": {},
|
||||||
|
"node:node2": {},
|
||||||
|
"node:node3": {},
|
||||||
|
"pod:ns/pod2": {"node:node2"},
|
||||||
|
"pod:ns/pod3": {"node:node3"},
|
||||||
|
"pod:ns/pod4": {"node:node1"},
|
||||||
|
"configmap:ns/cm1": {"node:node2", "node:node3", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm2": {"node:node1", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
})
|
||||||
|
expectIndex(map[string][]string{
|
||||||
|
"configmap:ns/cm1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm2": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm3": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"serviceAccount:ns/sa1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove node->configmap reference
|
||||||
|
g.SetNodeConfigMap("node1", "", "")
|
||||||
|
expectGraph(map[string][]string{
|
||||||
|
"node:node1": {},
|
||||||
|
"node:node2": {},
|
||||||
|
"node:node3": {},
|
||||||
|
"pod:ns/pod2": {"node:node2"},
|
||||||
|
"pod:ns/pod3": {"node:node3"},
|
||||||
|
"pod:ns/pod4": {"node:node1"},
|
||||||
|
"configmap:ns/cm1": {"node:node2", "node:node3", "pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm2": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"configmap:ns/cm3": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
"serviceAccount:ns/sa1": {"pod:ns/pod2", "pod:ns/pod3", "pod:ns/pod4"},
|
||||||
|
})
|
||||||
|
expectIndex(map[string][]string{
|
||||||
|
"configmap:ns/cm1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm2": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"configmap:ns/cm3": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
"serviceAccount:ns/sa1": {"node:node1", "node:node2", "node:node3"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user