@@ -19,6 +19,7 @@ import (
1919
2020 "github.com/influxdata/telegraf"
2121 "github.com/influxdata/telegraf/config"
22+ "github.com/influxdata/telegraf/internal"
2223 "github.com/influxdata/telegraf/internal/choice"
2324 "github.com/influxdata/telegraf/testutil"
2425)
@@ -33,6 +34,7 @@ type mockClient struct {
3334 NodeListF func () ([]swarm.Node , error )
3435 DiskUsageF func () (types.DiskUsage , error )
3536 ClientVersionF func () string
37+ PingF func () (types.Ping , error )
3638 CloseF func () error
3739}
3840
@@ -72,6 +74,10 @@ func (c *mockClient) ClientVersion() string {
7274 return c .ClientVersionF ()
7375}
7476
77+ func (c * mockClient ) Ping (context.Context ) (types.Ping , error ) {
78+ return c .PingF ()
79+ }
80+
7581func (c * mockClient ) Close () error {
7682 return c .CloseF ()
7783}
@@ -104,6 +110,9 @@ var baseClient = mockClient{
104110 ClientVersionF : func () string {
105111 return version
106112 },
113+ PingF : func () (types.Ping , error ) {
114+ return types.Ping {}, nil
115+ },
107116 CloseF : func () error {
108117 return nil
109118 },
@@ -422,7 +431,8 @@ func TestDocker_WindowsMemoryContainerStats(t *testing.T) {
422431 var acc testutil.Accumulator
423432
424433 d := Docker {
425- Log : testutil.Logger {},
434+ Log : testutil.Logger {},
435+ Timeout : config .Duration (5 * time .Second ),
426436 newClient : func (string , * tls.Config ) (dockerClient , error ) {
427437 return & mockClient {
428438 InfoF : func () (system.Info , error ) {
@@ -452,6 +462,9 @@ func TestDocker_WindowsMemoryContainerStats(t *testing.T) {
452462 ClientVersionF : func () string {
453463 return version
454464 },
465+ PingF : func () (types.Ping , error ) {
466+ return types.Ping {}, nil
467+ },
455468 CloseF : func () error {
456469 return nil
457470 },
@@ -1694,6 +1707,7 @@ func TestPodmanDetection(t *testing.T) {
16941707 var acc testutil.Accumulator
16951708 d := Docker {
16961709 Endpoint : tt .endpoint ,
1710+ Timeout : config .Duration (5 * time .Second ),
16971711 newClient : func (string , * tls.Config ) (dockerClient , error ) {
16981712 return & mockClient {
16991713 InfoF : func () (system.Info , error ) {
@@ -1712,6 +1726,9 @@ func TestPodmanDetection(t *testing.T) {
17121726 ClientVersionF : func () string {
17131727 return "1.24.0"
17141728 },
1729+ PingF : func () (types.Ping , error ) {
1730+ return types.Ping {}, nil
1731+ },
17151732 CloseF : func () error {
17161733 return nil
17171734 },
@@ -1777,8 +1794,7 @@ func TestPodmanStatsCache(t *testing.T) {
17771794}
17781795
17791796func TestStartWithUnavailableDocker (t * testing.T ) {
1780- // Test that Telegraf starts successfully even when Docker is unavailable
1781- // This is a regression test for https://github.com/influxdata/telegraf/issues/18089
1797+ // Test that Start returns a retryable StartupError when Docker is unavailable
17821798 var acc testutil.Accumulator
17831799 d := Docker {
17841800 Log : testutil.Logger {},
@@ -1791,42 +1807,70 @@ func TestStartWithUnavailableDocker(t *testing.T) {
17911807 }
17921808
17931809 require .NoError (t , d .Init ())
1794- // Start should NOT return an error even when Docker is unavailable
1795- require .NoError (t , d .Start (& acc ))
1796- // Client should be nil since connection failed
1797- require .Nil (t , d .client )
17981810
1799- // Gather should return an error since Docker is still unavailable
1800- err := d .Gather (& acc )
1811+ // Start should return a StartupError when Docker is unavailable
1812+ err := d .Start (& acc )
18011813 require .Error (t , err )
1802- require .Contains (t , err .Error (), "failed to connect to Docker daemon" )
1814+
1815+ var startupErr * internal.StartupError
1816+ require .ErrorAs (t , err , & startupErr )
1817+ require .Contains (t , startupErr .Error (), "failed to create Docker client" )
18031818}
18041819
1805- func TestLazyClientInitialization (t * testing.T ) {
1806- // Test that client is initialized lazily on first Gather if Start failed to connect
1820+ func TestStartWithPingFailure (t * testing.T ) {
1821+ // Test that Start returns a retryable StartupError when Ping fails due to connection issues
18071822 var acc testutil.Accumulator
18081823
1809- // Track connection attempts
1810- connectionAttempts := 0
1824+ // Create a mock client that succeeds on creation but fails on Ping
1825+ d := Docker {
1826+ Log : testutil.Logger {},
1827+ Timeout : config .Duration (5 * time .Second ),
1828+ newClient : func (string , * tls.Config ) (dockerClient , error ) {
1829+ return & mockClient {
1830+ PingF : func () (types.Ping , error ) {
1831+ return types.Ping {}, errors .New ("connection refused" )
1832+ },
1833+ CloseF : func () error {
1834+ return nil
1835+ },
1836+ }, nil
1837+ },
1838+ newEnvClient : func () (dockerClient , error ) {
1839+ return nil , errors .New ("not using env client" )
1840+ },
1841+ }
1842+
1843+ require .NoError (t , d .Init ())
1844+
1845+ // Start should return a StartupError when Ping fails
1846+ err := d .Start (& acc )
1847+ require .Error (t , err )
1848+
1849+ var startupErr * internal.StartupError
1850+ require .ErrorAs (t , err , & startupErr )
1851+ require .Contains (t , startupErr .Error (), "failed to ping Docker daemon" )
1852+ // Client should be nil since we clean up on failure
1853+ require .Nil (t , d .client )
1854+ }
1855+
1856+ func TestStartSuccess (t * testing.T ) {
1857+ // Test that Start succeeds when Docker is available
1858+ var acc testutil.Accumulator
18111859
18121860 d := Docker {
1813- Log : testutil.Logger {},
1861+ Log : testutil.Logger {},
1862+ Timeout : config .Duration (5 * time .Second ),
18141863 newClient : func (string , * tls.Config ) (dockerClient , error ) {
1815- connectionAttempts ++
1816- // First attempt fails, subsequent attempts succeed
1817- if connectionAttempts == 1 {
1818- return nil , errors .New ("docker daemon not ready" )
1819- }
18201864 return & mockClient {
1865+ PingF : func () (types.Ping , error ) {
1866+ return types.Ping {}, nil
1867+ },
18211868 InfoF : func () (system.Info , error ) {
18221869 return system.Info {
18231870 Name : "docker-desktop" ,
18241871 ServerVersion : "20.10.0" ,
18251872 }, nil
18261873 },
1827- ContainerListF : func (container.ListOptions ) ([]container.Summary , error ) {
1828- return nil , nil
1829- },
18301874 ClientVersionF : func () string {
18311875 return "1.24.0"
18321876 },
@@ -1841,18 +1885,6 @@ func TestLazyClientInitialization(t *testing.T) {
18411885 }
18421886
18431887 require .NoError (t , d .Init ())
1844- // Start should succeed even though connection fails
18451888 require .NoError (t , d .Start (& acc ))
1846- require .Equal (t , 1 , connectionAttempts )
1847- require .Nil (t , d .client )
1848-
1849- // First Gather fails because Docker is still unavailable (same mock returns error on attempt 1)
1850- // Reset connection attempts to simulate Docker becoming available
1851- connectionAttempts = 1 // Set to 1 so next attempt (2) will succeed
1852-
1853- // Second Gather should succeed after lazy initialization
1854- err := d .Gather (& acc )
1855- require .NoError (t , err )
1856- require .Equal (t , 2 , connectionAttempts )
18571889 require .NotNil (t , d .client )
18581890}
0 commit comments