Merge pull request #23570 from vdemeester/change-plugin-install

Update docker plugin install code…
This commit is contained in:
Arnaud Porterie 2016-06-17 00:12:56 +00:00 committed by GitHub
commit 7ef9aec90f
12 changed files with 91 additions and 40 deletions

View file

@ -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
}

View file

@ -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
}
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)
}

View file

@ -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
}

View file

@ -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