Merge pull request #23570 from vdemeester/change-plugin-install
Update docker plugin install code…
This commit is contained in:
commit
7ef9aec90f
12 changed files with 91 additions and 40 deletions
|
@ -40,7 +40,7 @@ func (r *IDResolver) get(ctx context.Context, t interface{}, id string) (string,
|
|||
}
|
||||
return id, nil
|
||||
case swarm.Service:
|
||||
service, err := r.client.ServiceInspect(ctx, id)
|
||||
service, _, err := r.client.ServiceInspectWithRaw(ctx, id)
|
||||
if err != nil {
|
||||
return id, nil
|
||||
}
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
package plugin
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/client"
|
||||
"github.com/docker/docker/cli"
|
||||
"github.com/docker/docker/reference"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/docker/engine-api/types"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -36,8 +39,8 @@ func newInstallCommand(dockerCli *client.DockerCli) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runInstall(dockerCli *client.DockerCli, options pluginOptions) error {
|
||||
named, err := reference.ParseNamed(options.name) // FIXME: validate
|
||||
func runInstall(dockerCli *client.DockerCli, opts pluginOptions) error {
|
||||
named, err := reference.ParseNamed(opts.name) // FIXME: validate
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -56,6 +59,34 @@ func runInstall(dockerCli *client.DockerCli, options pluginOptions) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO: pass noEnable flag
|
||||
return dockerCli.Client().PluginInstall(ctx, ref.String(), encodedAuth, options.grantPerms, false, dockerCli.In(), dockerCli.Out())
|
||||
|
||||
requestPrivilege := dockerCli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "plugin install")
|
||||
|
||||
// TODO: pass acceptAllPermissions and noEnable flag
|
||||
options := types.PluginInstallOptions{
|
||||
RegistryAuth: encodedAuth,
|
||||
Disabled: false,
|
||||
AcceptAllPermissions: opts.grantPerms,
|
||||
AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.name),
|
||||
PrivilegeFunc: requestPrivilege,
|
||||
}
|
||||
|
||||
return dockerCli.Client().PluginInstall(ctx, ref.String(), options)
|
||||
}
|
||||
|
||||
func acceptPrivileges(dockerCli *client.DockerCli, name string) func(privileges types.PluginPrivileges) (bool, error) {
|
||||
return func(privileges types.PluginPrivileges) (bool, error) {
|
||||
fmt.Fprintf(dockerCli.Out(), "Plugin %q requested the following privileges:\n", name)
|
||||
for _, privilege := range privileges {
|
||||
fmt.Fprintf(dockerCli.Out(), " - %s: %v\n", privilege.Name, privilege.Value)
|
||||
}
|
||||
|
||||
fmt.Fprint(dockerCli.Out(), "Do you grant the above permissions? [y/N] ")
|
||||
reader := bufio.NewReader(dockerCli.In())
|
||||
line, _, err := reader.ReadLine()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.ToLower(string(line)) == "y", nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ func runInspect(dockerCli *client.DockerCli, opts inspectOptions) error {
|
|||
ctx := context.Background()
|
||||
|
||||
getRef := func(ref string) (interface{}, []byte, error) {
|
||||
service, err := client.ServiceInspect(ctx, ref)
|
||||
service, _, err := client.ServiceInspectWithRaw(ctx, ref)
|
||||
if err == nil || !apiclient.IsErrServiceNotFound(err) {
|
||||
return service, nil, err
|
||||
}
|
||||
|
|
|
@ -61,7 +61,8 @@ func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string
|
|||
client := dockerCli.Client()
|
||||
ctx := context.Background()
|
||||
|
||||
service, err := client.ServiceInspect(ctx, serviceID)
|
||||
service, _, err := client.ServiceInspectWithRaw(ctx, serviceID)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func runTasks(dockerCli *client.DockerCli, opts tasksOptions) error {
|
|||
client := dockerCli.Client()
|
||||
ctx := context.Background()
|
||||
|
||||
service, err := client.ServiceInspect(ctx, opts.serviceID)
|
||||
service, _, err := client.ServiceInspectWithRaw(ctx, opts.serviceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, serviceID stri
|
|||
client := dockerCli.Client()
|
||||
ctx := context.Background()
|
||||
|
||||
service, err := client.ServiceInspect(ctx, serviceID)
|
||||
service, _, err := client.ServiceInspectWithRaw(ctx, serviceID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ clone git golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://gith
|
|||
clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git
|
||||
clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3
|
||||
clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d
|
||||
clone git github.com/docker/engine-api f50fbe5f9c4c8eeed591549d2c8187f4076f3717
|
||||
clone git github.com/docker/engine-api c57d0447ea1ae71f6dad83c8d8a1215a89869a0c
|
||||
clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
|
||||
clone git github.com/imdario/mergo 0.2.1
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ type NodeAPIClient interface {
|
|||
// ServiceAPIClient defines API client methods for the services
|
||||
type ServiceAPIClient interface {
|
||||
ServiceCreate(ctx context.Context, service swarm.ServiceSpec) (types.ServiceCreateResponse, error)
|
||||
ServiceInspect(ctx context.Context, serviceID string) (swarm.Service, error)
|
||||
ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error)
|
||||
ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error)
|
||||
ServiceRemove(ctx context.Context, serviceID string) error
|
||||
ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec) error
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
@ -29,7 +27,7 @@ type PluginAPIClient interface {
|
|||
PluginRemove(ctx context.Context, name string) error
|
||||
PluginEnable(ctx context.Context, name string) error
|
||||
PluginDisable(ctx context.Context, name string) error
|
||||
PluginInstall(ctx context.Context, name, registryAuth string, acceptAllPermissions, noEnable bool, in io.ReadCloser, out io.Writer) error
|
||||
PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) error
|
||||
PluginPush(ctx context.Context, name string, registryAuth string) error
|
||||
PluginSet(ctx context.Context, name string, args []string) error
|
||||
PluginInspect(ctx context.Context, name string) (*types.Plugin, error)
|
||||
|
|
|
@ -3,21 +3,28 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/engine-api/types"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// PluginInstall installs a plugin
|
||||
func (cli *Client) PluginInstall(ctx context.Context, name, registryAuth string, acceptAllPermissions, noEnable bool, in io.ReadCloser, out io.Writer) error {
|
||||
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
||||
resp, err := cli.post(ctx, "/plugins/pull", url.Values{"name": []string{name}}, nil, headers)
|
||||
func (cli *Client) PluginInstall(ctx context.Context, name string, options types.PluginInstallOptions) error {
|
||||
// FIXME(vdemeester) name is a ref, we might want to parse/validate it here.
|
||||
query := url.Values{}
|
||||
query.Set("name", name)
|
||||
resp, err := cli.tryPluginPull(ctx, query, options.RegistryAuth)
|
||||
if resp.statusCode == http.StatusUnauthorized && options.PrivilegeFunc != nil {
|
||||
newAuthHeader, privilegeErr := options.PrivilegeFunc()
|
||||
if privilegeErr != nil {
|
||||
ensureReaderClosed(resp)
|
||||
return privilegeErr
|
||||
}
|
||||
resp, err = cli.tryPluginPull(ctx, query, newAuthHeader)
|
||||
}
|
||||
if err != nil {
|
||||
ensureReaderClosed(resp)
|
||||
return err
|
||||
|
@ -28,27 +35,24 @@ func (cli *Client) PluginInstall(ctx context.Context, name, registryAuth string,
|
|||
}
|
||||
ensureReaderClosed(resp)
|
||||
|
||||
if !acceptAllPermissions && len(privileges) > 0 {
|
||||
|
||||
fmt.Fprintf(out, "Plugin %q requested the following privileges:\n", name)
|
||||
for _, privilege := range privileges {
|
||||
fmt.Fprintf(out, " - %s: %v\n", privilege.Name, privilege.Value)
|
||||
}
|
||||
|
||||
fmt.Fprint(out, "Do you grant the above permissions? [y/N] ")
|
||||
reader := bufio.NewReader(in)
|
||||
line, _, err := reader.ReadLine()
|
||||
if !options.AcceptAllPermissions && options.AcceptPermissionsFunc != nil && len(privileges) > 0 {
|
||||
accept, err := options.AcceptPermissionsFunc(privileges)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.ToLower(string(line)) != "y" {
|
||||
if !accept {
|
||||
resp, _ := cli.delete(ctx, "/plugins/"+name, nil, nil)
|
||||
ensureReaderClosed(resp)
|
||||
return pluginPermissionDenied{name}
|
||||
}
|
||||
}
|
||||
if noEnable {
|
||||
if options.Disabled {
|
||||
return nil
|
||||
}
|
||||
return cli.PluginEnable(ctx, name)
|
||||
}
|
||||
|
||||
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, registryAuth string) (*serverResponse, error) {
|
||||
headers := map[string][]string{"X-Registry-Auth": {registryAuth}}
|
||||
return cli.post(ctx, "/plugins/pull", query, nil, headers)
|
||||
}
|
||||
|
|
|
@ -1,25 +1,33 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/docker/engine-api/types/swarm"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// ServiceInspect returns the service information.
|
||||
func (cli *Client) ServiceInspect(ctx context.Context, serviceID string) (swarm.Service, error) {
|
||||
// ServiceInspectWithRaw returns the service information and the raw data.
|
||||
func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string) (swarm.Service, []byte, error) {
|
||||
serverResp, err := cli.get(ctx, "/services/"+serviceID, nil, nil)
|
||||
if err != nil {
|
||||
if serverResp.statusCode == http.StatusNotFound {
|
||||
return swarm.Service{}, serviceNotFoundError{serviceID}
|
||||
return swarm.Service{}, nil, serviceNotFoundError{serviceID}
|
||||
}
|
||||
return swarm.Service{}, err
|
||||
return swarm.Service{}, nil, err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
|
||||
body, err := ioutil.ReadAll(serverResp.body)
|
||||
if err != nil {
|
||||
return swarm.Service{}, nil, err
|
||||
}
|
||||
|
||||
var response swarm.Service
|
||||
err = json.NewDecoder(serverResp.body).Decode(&response)
|
||||
ensureReaderClosed(serverResp)
|
||||
return response, err
|
||||
rdr := bytes.NewReader(body)
|
||||
err = json.NewDecoder(rdr).Decode(&response)
|
||||
return response, body, err
|
||||
}
|
||||
|
|
|
@ -7,6 +7,15 @@ import (
|
|||
"fmt"
|
||||
)
|
||||
|
||||
// PluginInstallOptions holds parameters to install a plugin.
|
||||
type PluginInstallOptions struct {
|
||||
Disabled bool
|
||||
AcceptAllPermissions bool
|
||||
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
|
||||
PrivilegeFunc RequestPrivilegeFunc
|
||||
AcceptPermissionsFunc func(PluginPrivileges) (bool, error)
|
||||
}
|
||||
|
||||
// PluginConfig represents the values of settings potentially modifiable by a user
|
||||
type PluginConfig struct {
|
||||
Mounts []PluginMount
|
||||
|
|
Loading…
Add table
Reference in a new issue