plugins_test.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package testing
  14. import (
  15. "fmt"
  16. "net"
  17. "sync"
  18. "testing"
  19. utilsets "k8s.io/apimachinery/pkg/util/sets"
  20. kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
  21. kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
  22. "k8s.io/kubernetes/pkg/kubelet/dockershim/network"
  23. sysctltest "k8s.io/kubernetes/pkg/util/sysctl/testing"
  24. "github.com/golang/mock/gomock"
  25. "github.com/stretchr/testify/assert"
  26. )
  27. func TestSelectDefaultPlugin(t *testing.T) {
  28. all_plugins := []network.NetworkPlugin{}
  29. plug, err := network.InitNetworkPlugin(all_plugins, "", NewFakeHost(nil), kubeletconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU)
  30. if err != nil {
  31. t.Fatalf("Unexpected error in selecting default plugin: %v", err)
  32. }
  33. if plug == nil {
  34. t.Fatalf("Failed to select the default plugin.")
  35. }
  36. if plug.Name() != network.DefaultPluginName {
  37. t.Errorf("Failed to select the default plugin. Expected %s. Got %s", network.DefaultPluginName, plug.Name())
  38. }
  39. }
  40. func TestInit(t *testing.T) {
  41. tests := []struct {
  42. setting string
  43. expectedLen int
  44. }{
  45. {
  46. setting: "net/bridge/bridge-nf-call-iptables",
  47. expectedLen: 1,
  48. },
  49. {
  50. setting: "net/bridge/bridge-nf-call-ip6tables",
  51. expectedLen: 2,
  52. },
  53. }
  54. for _, tt := range tests {
  55. sysctl := sysctltest.NewFake()
  56. sysctl.Settings[tt.setting] = 0
  57. plug := &network.NoopNetworkPlugin{}
  58. plug.Sysctl = sysctl
  59. plug.Init(NewFakeHost(nil), kubeletconfig.HairpinNone, "10.0.0.0/8", network.UseDefaultMTU)
  60. // Verify the sysctl specified is set
  61. assert.Equal(t, 1, sysctl.Settings[tt.setting], tt.setting+" sysctl should have been set")
  62. // Verify iptables is always set
  63. assert.Equal(t, 1, sysctl.Settings["net/bridge/bridge-nf-call-iptables"], "net/bridge/bridge-nf-call-iptables sysctl should have been set")
  64. // Verify ip6tables is only set if it existed
  65. assert.Len(t, sysctl.Settings, tt.expectedLen, "length wrong for "+tt.setting)
  66. }
  67. }
  68. func TestPluginManager(t *testing.T) {
  69. ctrl := gomock.NewController(t)
  70. fnp := NewMockNetworkPlugin(ctrl)
  71. defer fnp.Finish()
  72. pm := network.NewPluginManager(fnp)
  73. fnp.EXPECT().Name().Return("someNetworkPlugin").AnyTimes()
  74. allCreatedWg := sync.WaitGroup{}
  75. allCreatedWg.Add(1)
  76. allDoneWg := sync.WaitGroup{}
  77. // 10 pods, 4 setup/status/teardown runs each. Ensure that network locking
  78. // works and the pod map isn't concurrently accessed
  79. for i := 0; i < 10; i++ {
  80. podName := fmt.Sprintf("pod%d", i)
  81. containerID := kubecontainer.ContainerID{ID: podName}
  82. fnp.EXPECT().SetUpPod("", podName, containerID).Return(nil).Times(4)
  83. fnp.EXPECT().GetPodNetworkStatus("", podName, containerID).Return(&network.PodNetworkStatus{IP: net.ParseIP("1.2.3.4")}, nil).Times(4)
  84. fnp.EXPECT().TearDownPod("", podName, containerID).Return(nil).Times(4)
  85. for x := 0; x < 4; x++ {
  86. allDoneWg.Add(1)
  87. go func(name string, id kubecontainer.ContainerID, num int) {
  88. defer allDoneWg.Done()
  89. // Block all goroutines from running until all have
  90. // been created and are ready. This ensures we
  91. // have more pod network operations running
  92. // concurrently.
  93. allCreatedWg.Wait()
  94. if err := pm.SetUpPod("", name, id, nil, nil); err != nil {
  95. t.Errorf("Failed to set up pod %q: %v", name, err)
  96. return
  97. }
  98. if _, err := pm.GetPodNetworkStatus("", name, id); err != nil {
  99. t.Errorf("Failed to inspect pod %q: %v", name, err)
  100. return
  101. }
  102. if err := pm.TearDownPod("", name, id); err != nil {
  103. t.Errorf("Failed to tear down pod %q: %v", name, err)
  104. return
  105. }
  106. }(podName, containerID, x)
  107. }
  108. }
  109. // Block all goroutines from running until all have been created and started
  110. allCreatedWg.Done()
  111. // Wait for them all to finish
  112. allDoneWg.Wait()
  113. }
  114. type hookableFakeNetworkPluginSetupHook func(namespace, name string, id kubecontainer.ContainerID)
  115. type hookableFakeNetworkPlugin struct {
  116. setupHook hookableFakeNetworkPluginSetupHook
  117. }
  118. func newHookableFakeNetworkPlugin(setupHook hookableFakeNetworkPluginSetupHook) *hookableFakeNetworkPlugin {
  119. return &hookableFakeNetworkPlugin{
  120. setupHook: setupHook,
  121. }
  122. }
  123. func (p *hookableFakeNetworkPlugin) Init(host network.Host, hairpinMode kubeletconfig.HairpinMode, nonMasqueradeCIDR string, mtu int) error {
  124. return nil
  125. }
  126. func (p *hookableFakeNetworkPlugin) Event(name string, details map[string]interface{}) {
  127. }
  128. func (p *hookableFakeNetworkPlugin) Name() string {
  129. return "fakeplugin"
  130. }
  131. func (p *hookableFakeNetworkPlugin) Capabilities() utilsets.Int {
  132. return utilsets.NewInt()
  133. }
  134. func (p *hookableFakeNetworkPlugin) SetUpPod(namespace string, name string, id kubecontainer.ContainerID, annotations, options map[string]string) error {
  135. if p.setupHook != nil {
  136. p.setupHook(namespace, name, id)
  137. }
  138. return nil
  139. }
  140. func (p *hookableFakeNetworkPlugin) TearDownPod(string, string, kubecontainer.ContainerID) error {
  141. return nil
  142. }
  143. func (p *hookableFakeNetworkPlugin) GetPodNetworkStatus(string, string, kubecontainer.ContainerID) (*network.PodNetworkStatus, error) {
  144. return &network.PodNetworkStatus{IP: net.ParseIP("10.1.2.3")}, nil
  145. }
  146. func (p *hookableFakeNetworkPlugin) Status() error {
  147. return nil
  148. }
  149. // Ensure that one pod's network operations don't block another's. If the
  150. // test is successful (eg, first pod doesn't block on second) the test
  151. // will complete. If unsuccessful, it will hang and get killed.
  152. func TestMultiPodParallelNetworkOps(t *testing.T) {
  153. podWg := sync.WaitGroup{}
  154. podWg.Add(1)
  155. // Can't do this with MockNetworkPlugin because the gomock controller
  156. // has its own locks which don't allow the parallel network operation
  157. // to proceed.
  158. didWait := false
  159. fakePlugin := newHookableFakeNetworkPlugin(func(podNamespace, podName string, id kubecontainer.ContainerID) {
  160. if podName == "waiter" {
  161. podWg.Wait()
  162. didWait = true
  163. }
  164. })
  165. pm := network.NewPluginManager(fakePlugin)
  166. opsWg := sync.WaitGroup{}
  167. // Start the pod that will wait for the other to complete
  168. opsWg.Add(1)
  169. go func() {
  170. defer opsWg.Done()
  171. podName := "waiter"
  172. containerID := kubecontainer.ContainerID{ID: podName}
  173. // Setup will block on the runner pod completing. If network
  174. // operations locking isn't correct (eg pod network operations
  175. // block other pods) setUpPod() will never return.
  176. if err := pm.SetUpPod("", podName, containerID, nil, nil); err != nil {
  177. t.Errorf("Failed to set up waiter pod: %v", err)
  178. return
  179. }
  180. if err := pm.TearDownPod("", podName, containerID); err != nil {
  181. t.Errorf("Failed to tear down waiter pod: %v", err)
  182. return
  183. }
  184. }()
  185. opsWg.Add(1)
  186. go func() {
  187. defer opsWg.Done()
  188. // Let other pod proceed
  189. defer podWg.Done()
  190. podName := "runner"
  191. containerID := kubecontainer.ContainerID{ID: podName}
  192. if err := pm.SetUpPod("", podName, containerID, nil, nil); err != nil {
  193. t.Errorf("Failed to set up runner pod: %v", err)
  194. return
  195. }
  196. if err := pm.TearDownPod("", podName, containerID); err != nil {
  197. t.Errorf("Failed to tear down runner pod: %v", err)
  198. return
  199. }
  200. }()
  201. opsWg.Wait()
  202. if !didWait {
  203. t.Errorf("waiter pod didn't wait for runner pod!")
  204. }
  205. }