1
0

interface_emit_test.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. //go:build linux || darwin
  2. package nebula
  3. import (
  4. "context"
  5. "net/netip"
  6. "testing"
  7. "time"
  8. "github.com/rcrowley/go-metrics"
  9. "github.com/slackhq/nebula/cert"
  10. "github.com/slackhq/nebula/overlay/overlaytest"
  11. "github.com/slackhq/nebula/test"
  12. "github.com/slackhq/nebula/udp"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. )
  16. // Test_emitStats_primesGauges covers issue #907: a Prometheus scrape that
  17. // landed before the first ticker fire used to read 0 for the cert gauges.
  18. // emitStats now primes the gauges before entering the ticker loop. We assert
  19. // the gauge is zero before the first call and non-zero after.
  20. func Test_emitStats_primesGauges(t *testing.T) {
  21. defer metrics.DefaultRegistry.UnregisterAll()
  22. l := test.NewLogger()
  23. hostMap := newHostMap(l)
  24. preferredRanges := []netip.Prefix{netip.MustParsePrefix("10.0.0.0/8")}
  25. hostMap.preferredRanges.Store(&preferredRanges)
  26. notAfter := time.Now().Add(time.Hour)
  27. cs := &CertState{
  28. initiatingVersion: cert.Version1,
  29. privateKey: []byte{},
  30. v1Cert: &dummyCert{version: cert.Version1, notAfter: notAfter},
  31. v1Credential: nil,
  32. }
  33. lh := newTestLighthouse()
  34. ifce := &Interface{
  35. hostMap: hostMap,
  36. inside: &overlaytest.NoopTun{},
  37. outside: &udp.NoopConn{},
  38. firewall: &Firewall{Conntrack: newFirewallConntrack()},
  39. lightHouse: lh,
  40. pki: &PKI{},
  41. handshakeManager: NewHandshakeManager(l, hostMap, lh, &udp.NoopConn{}, defaultHandshakeConfig),
  42. l: l,
  43. // On linux, udp.NewUDPStatsEmitter indexes writers[0] and asserts to
  44. // *udp.StdConn. A zero value works: getMemInfo sees a nil rawConn,
  45. // returns an error, and the emitter falls through to a no-op.
  46. writers: []udp.Conn{&udp.StdConn{}},
  47. }
  48. ifce.pki.cs.Store(cs)
  49. ttlGauge := metrics.GetOrRegisterGauge("certificate.ttl_seconds", nil)
  50. require.Zero(t, ttlGauge.Value(), "gauge should be zero before emitStats runs")
  51. // Pre-cancel the context so emitStats returns after priming the gauges
  52. // without ever reading from ticker.C. The one hour interval is just a
  53. // belt-and-suspenders, the test does not expect the ticker to fire.
  54. ctx, cancel := context.WithCancel(context.Background())
  55. cancel()
  56. ifce.emitStats(ctx, time.Hour)
  57. ttl := ttlGauge.Value()
  58. assert.Positive(t, ttl, "ttl gauge should be primed by emitStats before its first tick")
  59. assert.LessOrEqual(t, ttl, int64(3600))
  60. assert.Equal(t, int64(cert.Version1), metrics.GetOrRegisterGauge("certificate.initiating_version", nil).Value())
  61. assert.Equal(t, int64(cert.Version1), metrics.GetOrRegisterGauge("certificate.max_version", nil).Value())
  62. }