Change:
Is this a BUG REPORT or FEATURE REQUEST? /kind bug What happened: In ipvs proxy mode, most service functions like "nodeport/loadbalance" is realized by the association of iptables/ipset/ipvs, yet most ipvs proxier ut only verified ipvs rules, which can't ensure service is functional. What you expected to happen: Check both ipvs rules and iptables chains/rules, ipset entries in ipvsproxier ut.
/sig network /area ipvs /assign
What's the current UT coverage number?
Current is 50.2%.
So, can we achieve 70%?
Yeah, we can do that, and that's definitely necessary.

Discussion:
fcmd := fakeexec.FakeCmd{ CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{ func() ([]byte, error) { return []byte("dummy device have been created"), nil }, <ins> func() ([]byte, error) { return []byte(""), nil }, </ins> }, } fexec := &fakeexec.FakeExec{ CommandScript: []fakeexec.FakeCommandAction{ func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, <ins> func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) }, </ins> }, LookPathFunc: func(cmd string) (string, error) { return cmd, nil }, }

return ept } <ins> func TestCleanupLeftovers(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) fp := NewFakeProxier(ipt, ipvs, ipset, nil) svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 svcPortName := proxy.ServicePortName{ NamespacedName: makeNSN("ns1", "svc1"), Port:           "p80", } makeServiceMap(fp, makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *api.Service) { svc.Spec.Type = "NodePort" svc.Spec.ClusterIP = svcIP svc.Spec.Ports = []api.ServicePort{{ Name:     svcPortName.Port, Port:     int32(svcPort), Protocol: api.ProtocolTCP, NodePort: int32(svcNodePort), }} }), ) epIP := "10.180.0.1" makeEndpointsMap(fp, makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *api.Endpoints) { ept.Subsets = []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{ IP: epIP, }}, Ports: []api.EndpointPort{{ Name: svcPortName.Port, Port: int32(svcPort), }}, }} }), ) fp.syncProxyRules() // test cleanup left over if CleanupLeftovers(ipvs, ipt, ipset, true) { t.Errorf("Cleanup leftovers failed") } } </ins> func TestCanUseIPVSProxier(t *testing.T) { testCases := []struct { mods         []string

} } <ins> func TestNodePortUDP(t *testing.T) { nodeIP := net.ParseIP("100.101.102.103") ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) fp := NewFakeProxier(ipt, ipvs, ipset, []net.IP{nodeIP}) svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001 svcPortName := proxy.ServicePortName{ NamespacedName: makeNSN("ns1", "svc1"), Port:           "p80", } makeServiceMap(fp, makeTestService(svcPortName.Namespace, svcPortName.Name, func(svc *api.Service) { svc.Spec.Type = "NodePort" svc.Spec.ClusterIP = svcIP svc.Spec.Ports = []api.ServicePort{{ Name:     svcPortName.Port, Port:     int32(svcPort), Protocol: api.ProtocolUDP, NodePort: int32(svcNodePort), }} }), ) epIP := "10.180.0.1" makeEndpointsMap(fp, makeTestEndpoints(svcPortName.Namespace, svcPortName.Name, func(ept *api.Endpoints) { ept.Subsets = []api.EndpointSubset{{ Addresses: []api.EndpointAddress{{ IP: epIP, }}, Ports: []api.EndpointPort{{ Name: svcPortName.Port, Port: int32(svcPort), }}, }} }), ) fp.nodePortAddresses = []string{"0.0.0.0/0"} fp.syncProxyRules() // Check ipvs service and destinations epVS := &netlinktest.ExpectedVirtualServer{ VSNum: 2, IP: nodeIP.String(), Port: uint16(svcNodePort), Protocol: string(api.ProtocolTCP), RS: []netlinktest.ExpectedRealServer{{ IP: epIP, Port: uint16(svcPort), }}} checkIPVS(t, fp, epVS) // check ipSet rules epIPSet := netlinktest.ExpectedIPSet{ kubeNodePortSetUDP: {{ Port:     svcNodePort, Protocol: strings.ToLower(string(api.ProtocolUDP)), SetType:  utilipset.BitmapPort, }}, } checkIPSet(t, fp, epIPSet) // Check iptables chain and rules epIpt := netlinktest.ExpectedIptablesChain{ string(kubeServicesChain): {{ JumpChain: string(KubeNodePortChain), MatchSet: kubeNodePortSetUDP, }}, string(KubeNodePortChain): {{ JumpChain: string(KubeMarkMasqChain), MatchSet: "", }}, } checkIptables(t, ipt, epIpt) } </ins> func TestNodePort(t *testing.T) { ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake()

fp := NewFakeProxier(ipt, ipvs, ipset, nil) svcIP := "10.20.30.41" svcPort := 80 <del> svcExternalIPs := sets.NewString("50.60.70.81", "2012::51") </del> <ins> svcExternalIPs := sets.NewString("50.60.70.81", "2012::51", "127.0.0.1") </ins> svcPortName := proxy.ServicePortName{ NamespacedName: makeNSN("ns1", "svc1"), Port:           "p80",

if err != nil { t.Errorf("Failed to get ipvs services, err: %v", err) } <del> if len(services) != 3 { t.Errorf("Expect 3 ipvs services, got %d", len(services)) </del> <ins> if len(services) != 4 { t.Errorf("Expect 4 ipvs services, got %d", len(services)) </ins> } found := false for _, svc := range services {

} func TestLoadBalancer(t *testing.T) { <del> ipt := iptablestest.NewFake() ipvs := ipvstest.NewFake() ipset := ipsettest.NewFake(testIPSetVersion) fp := NewFakeProxier(ipt, ipvs, ipset, nil) </del> <ins> ipt, fp := buildFakeProxier() </ins> svcIP := "10.20.30.41" svcPort := 80 svcNodePort := 3001

) fp.syncProxyRules() <ins> // Expect 2 services and 1 destination epVS := &netlinktest.ExpectedVirtualServer{ VSNum: 2, IP: svcLBIP, Port: uint16(svcNodePort), Protocol: string(api.ProtocolTCP), RS: []netlinktest.ExpectedRealServer{{ IP: epIP, Port: uint16(svcPort), }}} checkIPVS(t, fp, epVS) // check ipSet rules epIPSet := netlinktest.ExpectedIPSet{ kubeLoadBalancerSet: {{ IP:       svcLBIP, Port:     svcPort, Protocol: strings.ToLower(string(api.ProtocolTCP)), SetType:  utilipset.HashIPPort, }}, } checkIPSet(t, fp, epIPSet) // Check iptables chain and rules epIpt := netlinktest.ExpectedIptablesChain{ string(kubeServicesChain): {{ JumpChain: string(KubeLoadBalancerChain), MatchSet: kubeLoadBalancerSet, }}, string(kubeLoadBalancerSet): {{ JumpChain: string(KubeMarkMasqChain), MatchSet: "", }}, } checkIptables(t, ipt, epIpt) </ins> } func TestOnlyLocalNodePorts(t *testing.T) {