context_unix.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. //go:build linux || freebsd
  2. // +build linux freebsd
  3. package testutils
  4. import (
  5. "runtime"
  6. "testing"
  7. "github.com/docker/docker/libnetwork/ns"
  8. "github.com/vishvananda/netns"
  9. )
  10. // SetupTestOSContext joins a new network namespace, and returns its associated
  11. // teardown function.
  12. //
  13. // Example usage:
  14. //
  15. // defer SetupTestOSContext(t)()
  16. func SetupTestOSContext(t *testing.T) func() {
  17. origNS, err := netns.Get()
  18. if err != nil {
  19. t.Fatalf("Failed to open initial netns: %v", err)
  20. }
  21. restore := func() {
  22. if err := netns.Set(origNS); err != nil {
  23. t.Logf("Warning: failed to restore thread netns (%v)", err)
  24. } else {
  25. runtime.UnlockOSThread()
  26. }
  27. if err := origNS.Close(); err != nil {
  28. t.Logf("Warning: netns closing failed (%v)", err)
  29. }
  30. }
  31. runtime.LockOSThread()
  32. newNS, err := netns.New()
  33. if err != nil {
  34. // netns.New() is not atomic: it could have encountered an error
  35. // after unsharing the current thread's network namespace.
  36. restore()
  37. t.Fatalf("Failed to enter netns: %v", err)
  38. }
  39. // Since we are switching to a new test namespace make
  40. // sure to re-initialize initNs context
  41. ns.Init()
  42. nl := ns.NlHandle()
  43. lo, err := nl.LinkByName("lo")
  44. if err != nil {
  45. restore()
  46. t.Fatalf("Failed to get handle to loopback interface 'lo' in new netns: %v", err)
  47. }
  48. if err := nl.LinkSetUp(lo); err != nil {
  49. restore()
  50. t.Fatalf("Failed to enable loopback interface in new netns: %v", err)
  51. }
  52. return func() {
  53. if err := newNS.Close(); err != nil {
  54. t.Logf("Warning: netns closing failed (%v)", err)
  55. }
  56. restore()
  57. ns.Init()
  58. }
  59. }