Change:
Is this a BUG REPORT or FEATURE REQUEST?: /kind enhancement /sig apps Description: is a key function of DaemonSet; it's better to have more unit test case for it, e.g. node status, pod on the node. There's several test cases to the DaemonSet's finial decision, which are kind of integration test to me; prefer to provide more unit test case for this key function.
GitHub didn't allow me to assign the following users: mathspanda. Note that only can be assigned. <detailsIn response to : /assign Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
do you have any specific cases or shall I figure out something? I can take a look at this issue if you don't mind.
, , thanks very much for our effort on this enhancement; as you known, DaemonSet will use scheduler's predicates to decide which node can place pods; there's several predicates errors , the purpose of this issue is to trigger every error in unit test for code coverage.
Sure, thanks. I'll cover these predicates.
Also I've found interesting issue when I wanted to add test for predicate. It looks like is not handled or maybe I did something wrong, I couldn't find check. According following comments it should fail because AWS EBS forbids any two pods mounting the same volume ID : Test case: Any thoughts? is it correct behavior?

Discussion:
} } <ins> func resourceContainerSpec(memory, cpu string) v1.ResourceRequirements { return v1.ResourceRequirements{ Requests: allocatableResources(memory, cpu), } } </ins> func resourcePodSpecWithoutNodeName(memory, cpu string) v1.PodSpec { return v1.PodSpec{ Containers: []v1.Container{{

func TestNodeShouldRunDaemonPod(t *testing.T) { cases := []struct { <ins> predicateName                                    string </ins> podsOnNode                                       []*v1.Pod nodeCondition                                    []v1.NodeCondition ds                                               *extensions.DaemonSet

err                                              error }{ { <ins> predicateName: "ShouldRunDaemonPod", </ins> ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel},

shouldContinueRunning: true, }, { <ins> predicateName: "InsufficientResourceError", </ins> ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel},

shouldContinueRunning: true, }, { <ins> predicateName: "ErrPodNotMatchHostName", </ins> ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel},

shouldContinueRunning: false, }, { <ins> predicateName: "ErrPodNotFitsHostPorts", </ins> podsOnNode: []*v1.Pod{ { Spec: v1.PodSpec{

shouldSchedule:        false, shouldContinueRunning: false, }, <ins> { predicateName: "InsufficientResourceError", podsOnNode: []*v1.Pod{ { Spec: v1.PodSpec{ Containers: []v1.Container{{ Ports: []v1.ContainerPort{{ HostPort: 666, }}, Resources: resourceContainerSpec("50M", "0.5"), }}, }, }, }, ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: simpleDaemonSetLabel, }, Spec: resourcePodSpec("", "100M", "0.5"), }, }, }, wantToRun:             true, shouldSchedule:        false, shouldContinueRunning: true, }, { predicateName: "ShouldRunDaemonPod", podsOnNode: []*v1.Pod{ { Spec: v1.PodSpec{ Containers: []v1.Container{{ Ports: []v1.ContainerPort{{ HostPort: 666, }}, Resources: resourceContainerSpec("50M", "0.5"), }}, }, }, }, ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: simpleDaemonSetLabel, }, Spec: resourcePodSpec("", "50M", "0.5"), }, }, }, wantToRun:             true, shouldSchedule:        true, shouldContinueRunning: true, }, { predicateName: "ErrNodeSelectorNotMatch", ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: simpleDaemonSetLabel, }, Spec: v1.PodSpec{ NodeSelector: simpleDaemonSetLabel2, }, }, }, }, wantToRun:             false, shouldSchedule:        false, shouldContinueRunning: false, }, { predicateName: "ShouldRunDaemonPod", ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: simpleDaemonSetLabel, }, Spec: v1.PodSpec{ NodeSelector: simpleDaemonSetLabel, }, }, }, }, wantToRun:             true, shouldSchedule:        true, shouldContinueRunning: true, }, { predicateName: "ErrPodAffinityNotMatch", ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: simpleDaemonSetLabel, }, Spec: v1.PodSpec{ Affinity: &v1.Affinity{ NodeAffinity: &v1.NodeAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { MatchExpressions: []v1.NodeSelectorRequirement{ { Key:      "type", Operator: v1.NodeSelectorOpIn, Values:   []string{"test"}, }, }, }, }, }, }, }, }, }, }, }, wantToRun:             false, shouldSchedule:        false, shouldContinueRunning: false, }, { predicateName: "ShouldRunDaemonPod", ds: &extensions.DaemonSet{ Spec: extensions.DaemonSetSpec{ Selector: &metav1.LabelSelector{MatchLabels: simpleDaemonSetLabel}, Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: simpleDaemonSetLabel, }, Spec: v1.PodSpec{ Affinity: &v1.Affinity{ NodeAffinity: &v1.NodeAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{ NodeSelectorTerms: []v1.NodeSelectorTerm{ { MatchExpressions: []v1.NodeSelectorRequirement{ { Key:      "type", Operator: v1.NodeSelectorOpIn, Values:   []string{"production"}, }, }, }, }, }, }, }, }, }, }, }, wantToRun:             true, shouldSchedule:        true, shouldContinueRunning: true, }, </ins> } for i, c := range cases { for _, strategy := range updateStrategies() { <del> node := newNode("test-node", nil) </del> <ins> node := newNode("test-node", simpleDaemonSetLabel) </ins> node.Status.Conditions = append(node.Status.Conditions, c.nodeCondition...) node.Status.Allocatable = allocatableResources("100M", "1") manager, _, _ := newTestController()

wantToRun, shouldSchedule, shouldContinueRunning, err := manager.nodeShouldRunDaemonPod(node, c.ds) if wantToRun != c.wantToRun { <del> t.Errorf("[%v] expected wantToRun: %v, got: %v", i, c.wantToRun, wantToRun) </del> <ins> t.Errorf("[%v] strategy: %v, predicateName: %v expected wantToRun: %v, got: %v", i, c.ds.Spec.UpdateStrategy.Type, c.predicateName, c.wantToRun, wantToRun) </ins> } if shouldSchedule != c.shouldSchedule { <del> t.Errorf("[%v] expected shouldSchedule: %v, got: %v", i, c.shouldSchedule, shouldSchedule) </del> <ins> t.Errorf("[%v] strategy: %v, predicateName: %v expected shouldSchedule: %v, got: %v", i, c.ds.Spec.UpdateStrategy.Type, c.predicateName, c.shouldSchedule, shouldSchedule) </ins> } if shouldContinueRunning != c.shouldContinueRunning { <del> t.Errorf("[%v] expected shouldContinueRunning: %v, got: %v", i, c.shouldContinueRunning, shouldContinueRunning) </del> <ins> t.Errorf("[%v] strategy: %v, predicateName: %v expected shouldContinueRunning: %v, got: %v", i, c.ds.Spec.UpdateStrategy.Type, c.predicateName, c.shouldContinueRunning, shouldContinueRunning) </ins> } if err != c.err { <del> t.Errorf("[%v] expected err: %v, got: %v", i, c.err, err) </del> <ins> t.Errorf("[%v] strategy: %v, predicateName: %v expected err: %v, got: %v", i, c.predicateName, c.ds.Spec.UpdateStrategy.Type, c.err, err) </ins> } } }