Add unit test for child scope mismatch with missing parent

This commit is contained in:
Jordan Liggitt 2021-01-14 10:42:16 -05:00
parent 8cefa493a8
commit 65d43faf3a

View File

@ -1956,6 +1956,167 @@ func TestConflictingData(t *testing.T) {
}),
},
},
{
// https://github.com/kubernetes/kubernetes/issues/98040
name: "cluster-scoped bad child, namespaced good child, missing parent",
steps: []step{
// setup
createObjectInClient("", "v1", "pods", "ns1", makeMetadataObj(pod2ns1, pod1ns1)), // good child
createObjectInClient("", "v1", "nodes", "", makeMetadataObj(node1, pod1nonamespace)), // bad child
// 2,3: observe bad child
processEvent(makeAddEvent(node1, pod1nonamespace)),
assertState(state{
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod1nonamespace, virtual)},
pendingAttemptToDelete: []*node{
makeNode(pod1nonamespace, virtual)}, // virtual parent queued for deletion
}),
// 4,5: observe good child
processEvent(makeAddEvent(pod2ns1, pod1ns1)),
assertState(state{
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(pod1nonamespace, virtual)},
pendingAttemptToDelete: []*node{
makeNode(pod1nonamespace, virtual)}, // virtual parent queued for deletion
}),
// 6,7: process attemptToDelete of bad virtual parent coordinates
processAttemptToDelete(1),
assertState(state{
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(pod1nonamespace, virtual)},
}),
// steady-state is bad cluster child and bad virtual parent coordinates, with no retries
assertState(state{
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod1nonamespace, virtual)},
absentOwnerCache: []objectReference{pod1ns1},
}),
},
},
{
// https://github.com/kubernetes/kubernetes/issues/98040
name: "namespaced good child, cluster-scoped bad child, missing parent",
steps: []step{
// setup
createObjectInClient("", "v1", "pods", "ns1", makeMetadataObj(pod2ns1, pod1ns1)), // good child
createObjectInClient("", "v1", "nodes", "", makeMetadataObj(node1, pod1nonamespace)), // bad child
// 2,3: observe good child
processEvent(makeAddEvent(pod2ns1, pod1ns1)),
assertState(state{
graphNodes: []*node{
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(pod1ns1, virtual)},
pendingAttemptToDelete: []*node{
makeNode(pod1ns1, virtual)}, // virtual parent queued for deletion
}),
// 4,5: observe bad child
processEvent(makeAddEvent(node1, pod1nonamespace)),
assertState(state{
graphNodes: []*node{
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod1ns1, virtual)},
pendingAttemptToDelete: []*node{
makeNode(pod1ns1, virtual), // virtual parent queued for deletion
makeNode(node1, withOwners(pod1nonamespace)), // mismatched child queued for deletion
},
}),
// 6,7: process attemptToDelete of good virtual parent coordinates
processAttemptToDelete(1),
assertState(state{
clientActions: []string{
"get /v1, Resource=pods ns=ns1 name=podname1", // lookup of missing parent, returns 404
},
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(pod1ns1, virtual)},
pendingGraphChanges: []*event{makeVirtualDeleteEvent(pod1ns1)}, // virtual parent not found, queued virtual delete event
pendingAttemptToDelete: []*node{
makeNode(node1, withOwners(pod1nonamespace)), // mismatched child still queued for deletion
},
}),
// 8,9: process attemptToDelete of bad cluster child
processAttemptToDelete(1),
assertState(state{
clientActions: []string{
"get /v1, Resource=nodes name=nodename", // lookup of existing node
},
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(pod1ns1, virtual)},
pendingGraphChanges: []*event{makeVirtualDeleteEvent(pod1ns1)}, // virtual parent virtual delete event still enqueued
}),
// 10,11: process virtual delete event for good virtual parent coordinates
processPendingGraphChanges(1),
assertState(state{
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(pod1nonamespace, virtual)}, // missing virtual parent replaced with alternate coordinates, still virtual
absentOwnerCache: []objectReference{pod1ns1}, // cached absence of missing parent
pendingAttemptToDelete: []*node{
makeNode(pod2ns1, withOwners(pod1ns1)), // good child of missing parent enqueued for deletion
makeNode(pod1nonamespace, virtual), // new virtual parent coordinates enqueued for deletion
},
}),
// 12,13: process attemptToDelete of good child
processAttemptToDelete(1),
assertState(state{
clientActions: []string{
"get /v1, Resource=pods ns=ns1 name=podname2", // lookup of good child
"delete /v1, Resource=pods ns=ns1 name=podname2", // delete of good child
},
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod2ns1, withOwners(pod1ns1)),
makeNode(pod1nonamespace, virtual)},
absentOwnerCache: []objectReference{pod1ns1},
pendingAttemptToDelete: []*node{
makeNode(pod1nonamespace, virtual), // new virtual parent coordinates enqueued for deletion
},
}),
// 14,15: observe deletion of good child
processEvent(makeDeleteEvent(pod2ns1, pod1ns1)),
assertState(state{
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod1nonamespace, virtual)},
absentOwnerCache: []objectReference{pod1ns1},
pendingAttemptToDelete: []*node{
makeNode(pod1nonamespace, virtual), // new virtual parent coordinates enqueued for deletion
},
}),
// 16,17: process attemptToDelete of bad virtual parent coordinates
// steady-state is bad cluster child and bad virtual parent coordinates, with no retries
processAttemptToDelete(1),
assertState(state{
graphNodes: []*node{
makeNode(node1, withOwners(pod1nonamespace)),
makeNode(pod1nonamespace, virtual)},
absentOwnerCache: []objectReference{pod1ns1},
}),
},
},
}
alwaysStarted := make(chan struct{})