When a plugin fails to start, we still incorrectly mark it as enabled.
This change verifies that we can dial to the plugin socket to confirm that
the plugin is functional and only then mark the plugin as enabled. Also,
dont delete the plugin on install, if only the enable fails.
Signed-off-by: Anusha Ragunathan <anusha.ragunathan@docker.com>
... | ... |
@@ -60,8 +60,8 @@ func (cli *Client) PluginInstall(ctx context.Context, name string, options types |
60 | 60 |
return |
61 | 61 |
} |
62 | 62 |
|
63 |
- err = cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0}) |
|
64 |
- pw.CloseWithError(err) |
|
63 |
+ enableErr := cli.PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: 0}) |
|
64 |
+ pw.CloseWithError(enableErr) |
|
65 | 65 |
}() |
66 | 66 |
return pr, nil |
67 | 67 |
} |
... | ... |
@@ -5,6 +5,7 @@ package plugin |
5 | 5 |
import ( |
6 | 6 |
"encoding/json" |
7 | 7 |
"fmt" |
8 |
+ "net" |
|
8 | 9 |
"os" |
9 | 10 |
"path/filepath" |
10 | 11 |
"syscall" |
... | ... |
@@ -77,7 +78,8 @@ func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error { |
77 | 77 |
} |
78 | 78 |
|
79 | 79 |
func (pm *Manager) pluginPostStart(p *v2.Plugin, c *controller) error { |
80 |
- client, err := plugins.NewClientWithTimeout("unix://"+filepath.Join(pm.config.ExecRoot, p.GetID(), p.GetSocket()), nil, c.timeoutInSecs) |
|
80 |
+ sockAddr := filepath.Join(pm.config.ExecRoot, p.GetID(), p.GetSocket()) |
|
81 |
+ client, err := plugins.NewClientWithTimeout("unix://"+sockAddr, nil, c.timeoutInSecs) |
|
81 | 82 |
if err != nil { |
82 | 83 |
c.restart = false |
83 | 84 |
shutdownPlugin(p, c, pm.containerdClient) |
... | ... |
@@ -85,6 +87,27 @@ func (pm *Manager) pluginPostStart(p *v2.Plugin, c *controller) error { |
85 | 85 |
} |
86 | 86 |
|
87 | 87 |
p.SetPClient(client) |
88 |
+ |
|
89 |
+ maxRetries := 3 |
|
90 |
+ var retries int |
|
91 |
+ for { |
|
92 |
+ time.Sleep(3 * time.Second) |
|
93 |
+ retries++ |
|
94 |
+ |
|
95 |
+ if retries > maxRetries { |
|
96 |
+ logrus.Debugf("error net dialing plugin: %v", err) |
|
97 |
+ c.restart = false |
|
98 |
+ shutdownPlugin(p, c, pm.containerdClient) |
|
99 |
+ return err |
|
100 |
+ } |
|
101 |
+ |
|
102 |
+ // net dial into the unix socket to see if someone's listening. |
|
103 |
+ conn, err := net.Dial("unix", sockAddr) |
|
104 |
+ if err == nil { |
|
105 |
+ conn.Close() |
|
106 |
+ break |
|
107 |
+ } |
|
108 |
+ } |
|
88 | 109 |
pm.config.Store.SetState(p, true) |
89 | 110 |
pm.config.Store.CallHandler(p) |
90 | 111 |
|