Skip to content

Commit dffca5d

Browse files
committed
fix(inputs.docker): incorporated review comments
1 parent 065bc90 commit dffca5d

File tree

3 files changed

+58
-63
lines changed

3 files changed

+58
-63
lines changed

plugins/inputs/docker/client.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@ import (
1212
"github.com/docker/docker/client"
1313
)
1414

15-
// IsErrConnectionFailed returns true if the error is caused by connection failure.
16-
// This is a passthrough to the docker client library function.
17-
var IsErrConnectionFailed = client.IsErrConnectionFailed
18-
1915
var (
2016
defaultHeaders = map[string]string{"User-Agent": "engine-api-cli-1.0"}
2117
)

plugins/inputs/docker/docker.go

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/docker/docker/api/types/filters"
2222
"github.com/docker/docker/api/types/swarm"
2323
"github.com/docker/docker/api/types/system"
24+
"github.com/docker/docker/client"
2425

2526
"github.com/influxdata/telegraf"
2627
"github.com/influxdata/telegraf/config"
@@ -144,26 +145,22 @@ func (d *Docker) Init() error {
144145
}
145146

146147
func (d *Docker) Start(telegraf.Accumulator) error {
147-
// Get client
148+
// Get client - this only creates the client object, doesn't connect
148149
c, err := d.getNewClient()
149150
if err != nil {
150-
return &internal.StartupError{
151-
Err: fmt.Errorf("failed to create Docker client: %w", err),
152-
Retry: IsErrConnectionFailed(err),
153-
}
151+
return err
154152
}
155153
d.client = c
156154

157-
// Use Ping to check connectivity, this is a lightweight check
155+
// Use Ping to check connectivity - this is a lightweight check
158156
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(d.Timeout))
159-
_, err = d.client.Ping(ctx)
160-
cancel()
161-
if err != nil {
157+
defer cancel()
158+
if _, err := d.client.Ping(ctx); err != nil {
162159
d.client.Close()
163160
d.client = nil
164161
return &internal.StartupError{
165162
Err: fmt.Errorf("failed to ping Docker daemon: %w", err),
166-
Retry: IsErrConnectionFailed(err),
163+
Retry: client.IsErrConnectionFailed(err),
167164
}
168165
}
169166

@@ -193,7 +190,7 @@ func (d *Docker) Start(telegraf.Accumulator) error {
193190
d.client = nil
194191
return &internal.StartupError{
195192
Err: fmt.Errorf("failed to get Docker info: %w", err),
196-
Retry: IsErrConnectionFailed(err),
193+
Retry: client.IsErrConnectionFailed(err),
197194
}
198195
}
199196

@@ -221,10 +218,6 @@ func (d *Docker) Stop() {
221218
}
222219

223220
func (d *Docker) Gather(acc telegraf.Accumulator) error {
224-
if d.client == nil {
225-
return errors.New("docker client not initialized")
226-
}
227-
228221
// Create label filters if not already created
229222
if !d.filtersCreated {
230223
err := d.createLabelFilters()

plugins/inputs/docker/docker_test.go

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ import (
1919

2020
"github.com/influxdata/telegraf"
2121
"github.com/influxdata/telegraf/config"
22-
"github.com/influxdata/telegraf/internal"
2322
"github.com/influxdata/telegraf/internal/choice"
23+
"github.com/influxdata/telegraf/models"
2424
"github.com/influxdata/telegraf/testutil"
2525
)
2626

@@ -1793,38 +1793,41 @@ func TestPodmanStatsCache(t *testing.T) {
17931793
require.Contains(t, d.statsCache, testID)
17941794
}
17951795

1796-
func TestStartWithUnavailableDocker(t *testing.T) {
1797-
// Test that Start returns a retryable StartupError when Docker is unavailable
1798-
var acc testutil.Accumulator
1799-
d := Docker{
1800-
Log: testutil.Logger{},
1796+
func TestStartupErrorBehaviorError(t *testing.T) {
1797+
// Test that model.Start returns error when Ping fails with default "error" behavior
1798+
// Uses the startup-error-behavior framework (TSD-006)
1799+
plugin := &Docker{
1800+
Timeout: config.Duration(100 * time.Millisecond),
18011801
newClient: func(string, *tls.Config) (dockerClient, error) {
1802-
return nil, errors.New("cannot connect to the Docker daemon")
1802+
return &mockClient{
1803+
PingF: func() (types.Ping, error) {
1804+
return types.Ping{}, errors.New("connection refused")
1805+
},
1806+
CloseF: func() error {
1807+
return nil
1808+
},
1809+
}, nil
18031810
},
18041811
newEnvClient: func() (dockerClient, error) {
1805-
return nil, errors.New("cannot connect to the Docker daemon")
1812+
return nil, errors.New("not using env client")
18061813
},
18071814
}
1808-
1809-
require.NoError(t, d.Init())
1810-
1811-
// Start should return a StartupError when Docker is unavailable
1812-
err := d.Start(&acc)
1813-
require.Error(t, err)
1814-
1815-
var startupErr *internal.StartupError
1816-
require.ErrorAs(t, err, &startupErr)
1817-
require.Contains(t, startupErr.Error(), "failed to create Docker client")
1818-
}
1819-
1820-
func TestStartWithPingFailure(t *testing.T) {
1821-
// Test that Start returns a retryable StartupError when Ping fails due to connection issues
1815+
model := models.NewRunningInput(plugin, &models.InputConfig{
1816+
Name: "docker",
1817+
Alias: "error-test",
1818+
})
1819+
model.StartupErrors.Set(0)
1820+
require.NoError(t, model.Init())
1821+
1822+
// Starting the plugin will fail with an error because Ping fails
18221823
var acc testutil.Accumulator
1824+
require.ErrorContains(t, model.Start(&acc), "failed to ping Docker daemon")
1825+
}
18231826

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),
1827+
func TestStartupErrorBehaviorIgnore(t *testing.T) {
1828+
// Test that model.Start returns fatal error with "ignore" behavior when Ping fails
1829+
plugin := &Docker{
1830+
Timeout: config.Duration(100 * time.Millisecond),
18281831
newClient: func(string, *tls.Config) (dockerClient, error) {
18291832
return &mockClient{
18301833
PingF: func() (types.Ping, error) {
@@ -1839,26 +1842,24 @@ func TestStartWithPingFailure(t *testing.T) {
18391842
return nil, errors.New("not using env client")
18401843
},
18411844
}
1842-
1843-
require.NoError(t, d.Init())
1844-
1845-
// Start should return a StartupError when Ping fails
1846-
err := d.Start(&acc)
1845+
model := models.NewRunningInput(plugin, &models.InputConfig{
1846+
Name: "docker",
1847+
Alias: "ignore-test",
1848+
StartupErrorBehavior: "ignore",
1849+
})
1850+
model.StartupErrors.Set(0)
1851+
require.NoError(t, model.Init())
1852+
1853+
// Starting the plugin will fail and model should convert to fatal error
1854+
var acc testutil.Accumulator
1855+
err := model.Start(&acc)
18471856
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)
1857+
require.Contains(t, err.Error(), "failed to ping Docker daemon")
18541858
}
18551859

18561860
func TestStartSuccess(t *testing.T) {
18571861
// Test that Start succeeds when Docker is available
1858-
var acc testutil.Accumulator
1859-
1860-
d := Docker{
1861-
Log: testutil.Logger{},
1862+
plugin := &Docker{
18621863
Timeout: config.Duration(5 * time.Second),
18631864
newClient: func(string, *tls.Config) (dockerClient, error) {
18641865
return &mockClient{
@@ -1883,8 +1884,13 @@ func TestStartSuccess(t *testing.T) {
18831884
return nil, errors.New("not using env client")
18841885
},
18851886
}
1887+
model := models.NewRunningInput(plugin, &models.InputConfig{
1888+
Name: "docker",
1889+
Alias: "success-test",
1890+
})
1891+
model.StartupErrors.Set(0)
1892+
require.NoError(t, model.Init())
18861893

1887-
require.NoError(t, d.Init())
1888-
require.NoError(t, d.Start(&acc))
1889-
require.NotNil(t, d.client)
1894+
var acc testutil.Accumulator
1895+
require.NoError(t, model.Start(&acc))
18901896
}

0 commit comments

Comments
 (0)