PluginInstall installs a plugin
(ctx context.Context, name string, options PluginInstallOptions)
| 41 | |
| 42 | // PluginInstall installs a plugin |
| 43 | func (cli *Client) PluginInstall(ctx context.Context, name string, options PluginInstallOptions) (_ PluginInstallResult, retErr error) { |
| 44 | query := url.Values{} |
| 45 | if _, err := reference.ParseNormalizedNamed(options.RemoteRef); err != nil { |
| 46 | return PluginInstallResult{}, fmt.Errorf("invalid remote reference: %w", err) |
| 47 | } |
| 48 | query.Set("remote", options.RemoteRef) |
| 49 | |
| 50 | privileges, err := cli.checkPluginPermissions(ctx, query, &options) |
| 51 | if err != nil { |
| 52 | return PluginInstallResult{}, err |
| 53 | } |
| 54 | |
| 55 | // set name for plugin pull, if empty should default to remote reference |
| 56 | query.Set("name", name) |
| 57 | |
| 58 | resp, err := cli.tryPluginPull(ctx, query, privileges, options.RegistryAuth) |
| 59 | if err != nil { |
| 60 | return PluginInstallResult{}, err |
| 61 | } |
| 62 | |
| 63 | name = resp.Header.Get("Docker-Plugin-Name") |
| 64 | |
| 65 | pr, pw := io.Pipe() |
| 66 | go func() { // todo: the client should probably be designed more around the actual api |
| 67 | _, err := io.Copy(pw, resp.Body) |
| 68 | if err != nil { |
| 69 | _ = pw.CloseWithError(err) |
| 70 | return |
| 71 | } |
| 72 | defer func() { |
| 73 | if retErr != nil { |
| 74 | delResp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil) |
| 75 | ensureReaderClosed(delResp) |
| 76 | } |
| 77 | }() |
| 78 | if len(options.Args) > 0 { |
| 79 | if _, err := cli.PluginSet(ctx, name, PluginSetOptions{Args: options.Args}); err != nil { |
| 80 | _ = pw.CloseWithError(err) |
| 81 | return |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | if options.Disabled { |
| 86 | _ = pw.Close() |
| 87 | return |
| 88 | } |
| 89 | |
| 90 | _, enableErr := cli.PluginEnable(ctx, name, PluginEnableOptions{Timeout: 0}) |
| 91 | _ = pw.CloseWithError(enableErr) |
| 92 | }() |
| 93 | return PluginInstallResult{pr}, nil |
| 94 | } |
| 95 | |
| 96 | func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, registryAuth string) (*http.Response, error) { |
| 97 | return cli.get(ctx, "/plugins/privileges", query, http.Header{ |
nothing calls this directly
no test coverage detected