diff --git a/api/server/router/network/network.go b/api/server/router/network/network.go index eaf52aa2a9..6d31cb4c58 100644 --- a/api/server/router/network/network.go +++ b/api/server/router/network/network.go @@ -2,21 +2,18 @@ package network import ( "github.com/docker/docker/api/server/router" - "github.com/docker/docker/daemon/cluster" ) // networkRouter is a router to talk with the network controller type networkRouter struct { backend Backend - cluster *cluster.Cluster routes []router.Route } // NewRouter initializes a new network router -func NewRouter(b Backend, c *cluster.Cluster) router.Router { +func NewRouter(b Backend) router.Router { r := &networkRouter{ backend: b, - cluster: c, } r.initRoutes() return r diff --git a/api/server/router/network/network_routes.go b/api/server/router/network/network_routes.go index 6f2041e35e..540460ca58 100644 --- a/api/server/router/network/network_routes.go +++ b/api/server/router/network/network_routes.go @@ -48,20 +48,7 @@ func (n *networkRouter) getNetworksList(ctx context.Context, w http.ResponseWrit list := []types.NetworkResource{} - if nr, err := n.cluster.GetNetworks(); err == nil { - list = append(list, nr...) - } - - // Combine the network list returned by Docker daemon if it is not already - // returned by the cluster manager -SKIP: for _, nw := range n.backend.GetNetworks() { - for _, nl := range list { - if nl.ID == nw.ID() { - continue SKIP - } - } - var nr *types.NetworkResource // Versions < 1.28 fetches all the containers attached to a network // in a network list api call. It is a heavy weight operation when @@ -135,29 +122,6 @@ func (n *networkRouter) getNetwork(ctx context.Context, w http.ResponseWriter, r } } - nr, _ := n.cluster.GetNetworks() - for _, network := range nr { - if network.ID == term && isMatchingScope(network.Scope, scope) { - return httputils.WriteJSON(w, http.StatusOK, network) - } - if network.Name == term && isMatchingScope(network.Scope, scope) { - // Check the ID collision as we are in swarm scope here, and - // the map (of the listByFullName) may have already had a - // network with the same ID (from local scope previously) - if _, ok := listByFullName[network.ID]; !ok { - listByFullName[network.ID] = network - } - } - if strings.HasPrefix(network.ID, term) && isMatchingScope(network.Scope, scope) { - // Check the ID collision as we are in swarm scope here, and - // the map (of the listByPartialID) may have already had a - // network with the same ID (from local scope previously) - if _, ok := listByPartialID[network.ID]; !ok { - listByPartialID[network.ID] = network - } - } - } - // Find based on full name, returns true only if no duplicates if len(listByFullName) == 1 { for _, v := range listByFullName { @@ -196,33 +160,9 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr return err } - if nws, err := n.cluster.GetNetworksByName(create.Name); err == nil && len(nws) > 0 { - return libnetwork.NetworkNameError(create.Name) - } - nw, err := n.backend.CreateNetwork(create) if err != nil { - var warning string - if _, ok := err.(libnetwork.NetworkNameError); ok { - // check if user defined CheckDuplicate, if set true, return err - // otherwise prepare a warning message - if create.CheckDuplicate { - return libnetwork.NetworkNameError(create.Name) - } - warning = libnetwork.NetworkNameError(create.Name).Error() - } - - if _, ok := err.(libnetwork.ManagerRedirectError); !ok { - return err - } - id, err := n.cluster.CreateNetwork(create) - if err != nil { - return err - } - nw = &types.NetworkCreateResponse{ - ID: id, - Warning: warning, - } + return err } return httputils.WriteJSON(w, http.StatusCreated, nw) @@ -266,13 +206,6 @@ func (n *networkRouter) deleteNetwork(ctx context.Context, w http.ResponseWriter if err := httputils.ParseForm(r); err != nil { return err } - if _, err := n.cluster.GetNetwork(vars["id"]); err == nil { - if err = n.cluster.RemoveNetwork(vars["id"]); err != nil { - return err - } - w.WriteHeader(http.StatusNoContent) - return nil - } if err := n.backend.DeleteNetwork(vars["id"]); err != nil { return err } diff --git a/api/server/router/system/system.go b/api/server/router/system/system.go index a64631e8aa..6ce0f436ef 100644 --- a/api/server/router/system/system.go +++ b/api/server/router/system/system.go @@ -3,23 +3,20 @@ package system import ( "github.com/docker/docker/api/server/router" "github.com/docker/docker/builder/fscache" - "github.com/docker/docker/daemon/cluster" ) // systemRouter provides information about the Docker system overall. // It gathers information about host, daemon and container events. type systemRouter struct { backend Backend - cluster *cluster.Cluster routes []router.Route builder *fscache.FSCache } // NewRouter initializes a new system router -func NewRouter(b Backend, c *cluster.Cluster, fscache *fscache.FSCache) router.Router { +func NewRouter(b Backend, fscache *fscache.FSCache) router.Router { r := &systemRouter{ backend: b, - cluster: c, builder: fscache, } diff --git a/api/server/router/system/system_routes.go b/api/server/router/system/system_routes.go index 30fb000e1d..c0a8071ae0 100644 --- a/api/server/router/system/system_routes.go +++ b/api/server/router/system/system_routes.go @@ -36,9 +36,6 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht if err != nil { return err } - if s.cluster != nil { - info.Swarm = s.cluster.Info() - } if versions.LessThan(httputils.VersionFromContext(ctx), "1.25") { // TODO: handle this conversion in engine-api diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index 89bfbb4d2c..893266f1fa 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -1,7 +1,6 @@ package dockerd import ( - "context" "crypto/tls" "fmt" "os" @@ -17,14 +16,11 @@ import ( "github.com/docker/docker/api/server/middleware" "github.com/docker/docker/api/server/router" "github.com/docker/docker/api/server/router/build" - checkpointrouter "github.com/docker/docker/api/server/router/checkpoint" "github.com/docker/docker/api/server/router/container" distributionrouter "github.com/docker/docker/api/server/router/distribution" "github.com/docker/docker/api/server/router/image" "github.com/docker/docker/api/server/router/network" - pluginrouter "github.com/docker/docker/api/server/router/plugin" sessionrouter "github.com/docker/docker/api/server/router/session" - swarmrouter "github.com/docker/docker/api/server/router/swarm" systemrouter "github.com/docker/docker/api/server/router/system" "github.com/docker/docker/api/server/router/volume" "github.com/docker/docker/builder/dockerfile" @@ -32,7 +28,6 @@ import ( "github.com/docker/docker/cli/debug" "github.com/docker/docker/client/session" "github.com/docker/docker/daemon" - "github.com/docker/docker/daemon/cluster" "github.com/docker/docker/daemon/config" "github.com/docker/docker/daemon/logger" "github.com/docker/docker/dockerversion" @@ -49,7 +44,6 @@ import ( "github.com/docker/docker/registry" "github.com/docker/docker/runconfig" "github.com/docker/go-connections/tlsconfig" - swarmapi "github.com/docker/swarmkit/api" "github.com/pkg/errors" "github.com/spf13/pflag" ) @@ -242,36 +236,6 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) { } } - // TODO: createAndStartCluster() - name, _ := os.Hostname() - - // Use a buffered channel to pass changes from store watch API to daemon - // A buffer allows store watch API and daemon processing to not wait for each other - watchStream := make(chan *swarmapi.WatchMessage, 32) - - c, err := cluster.New(cluster.Config{ - Root: cli.Config.Root, - Name: name, - Backend: d, - NetworkSubnetsProvider: d, - DefaultAdvertiseAddr: cli.Config.SwarmDefaultAdvertiseAddr, - RuntimeRoot: cli.getSwarmRunRoot(), - WatchStream: watchStream, - }) - if err != nil { - logrus.Fatalf("Error creating cluster component: %v", err) - } - d.SetCluster(c) - err = c.Start() - if err != nil { - logrus.Fatalf("Error starting cluster component: %v", err) - } - - // Restart all autostart containers which has a swarm endpoint - // and is not yet running now that we have successfully - // initialized the cluster. - d.RestartSwarmContainers() - logrus.Info("Daemon has completed initialization") cli.d = d @@ -281,15 +245,9 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) { return err } routerOptions.api = cli.api - routerOptions.cluster = c initRouter(routerOptions) - // process cluster change notifications - watchCtx, cancel := context.WithCancel(context.Background()) - defer cancel() - go d.ProcessClusterNotifications(watchCtx, watchStream) - cli.setupConfigReloadTrap() // The serve API routine never exits unless an error occurs @@ -304,7 +262,6 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) { // Daemon is fully initialized and handling API traffic // Wait for serve API to complete errAPI := <-serveAPIWait - c.Cleanup() shutdownDaemon(d) containerdRemote.Cleanup() if errAPI != nil { @@ -320,7 +277,6 @@ type routerOptions struct { buildCache *fscache.FSCache daemon *daemon.Daemon api *apiserver.Server - cluster *cluster.Cluster } func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptions, error) { @@ -509,20 +465,17 @@ func initRouter(opts routerOptions) { routers := []router.Router{ // we need to add the checkpoint router before the container router or the DELETE gets masked - checkpointrouter.NewRouter(opts.daemon, decoder), container.NewRouter(opts.daemon, decoder), image.NewRouter(opts.daemon, decoder), - systemrouter.NewRouter(opts.daemon, opts.cluster, opts.buildCache), + systemrouter.NewRouter(opts.daemon, opts.buildCache), volume.NewRouter(opts.daemon), build.NewRouter(opts.buildBackend, opts.daemon), sessionrouter.NewRouter(opts.sessionManager), - swarmrouter.NewRouter(opts.cluster), - pluginrouter.NewRouter(opts.daemon.PluginManager()), distributionrouter.NewRouter(opts.daemon), } if opts.daemon.NetworkControllerEnabled() { - routers = append(routers, network.NewRouter(opts.daemon, opts.cluster)) + routers = append(routers, network.NewRouter(opts.daemon)) } if opts.daemon.HasExperimental() { diff --git a/container/container.go b/container/container.go index 57d81cfd80..d2aa70731c 100644 --- a/container/container.go +++ b/container/container.go @@ -43,7 +43,6 @@ import ( "github.com/docker/libnetwork/netlabel" "github.com/docker/libnetwork/options" "github.com/docker/libnetwork/types" - agentexec "github.com/docker/swarmkit/agent/exec" "golang.org/x/net/context" ) @@ -88,7 +87,7 @@ type Container struct { MountPoints map[string]*volume.MountPoint HostConfig *containertypes.HostConfig `json:"-"` // do not serialize the host config in the json, otherwise we'll make the container unportable ExecCommands *exec.Store `json:"-"` - DependencyStore agentexec.DependencyGetter `json:"-"` + DependencyStore interface{} `json:"-"` SecretReferences []*swarmtypes.SecretReference ConfigReferences []*swarmtypes.ConfigReference // logDriver for closing diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index 277c83e083..080434d516 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -5,9 +5,7 @@ package daemon import ( "context" "fmt" - "io/ioutil" "os" - "path/filepath" "strconv" "syscall" "time" @@ -169,58 +167,7 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) { return errors.Wrap(err, "unable to setup secret mount") } - if c.DependencyStore == nil { - return fmt.Errorf("secret store is not initialized") - } - - for _, s := range c.SecretReferences { - // TODO (ehazlett): use type switch when more are supported - if s.File == nil { - logrus.Error("secret target type is not a file target") - continue - } - - // secrets are created in the SecretMountPath on the host, at a - // single level - fPath := c.SecretFilePath(*s) - if err := idtools.MkdirAllAndChown(filepath.Dir(fPath), 0700, rootIDs); err != nil { - return errors.Wrap(err, "error creating secret mount path") - } - - logrus.WithFields(logrus.Fields{ - "name": s.File.Name, - "path": fPath, - }).Debug("injecting secret") - secret, err := c.DependencyStore.Secrets().Get(s.SecretID) - if err != nil { - return errors.Wrap(err, "unable to get secret from secret store") - } - if err := ioutil.WriteFile(fPath, secret.Spec.Data, s.File.Mode); err != nil { - return errors.Wrap(err, "error injecting secret") - } - - uid, err := strconv.Atoi(s.File.UID) - if err != nil { - return err - } - gid, err := strconv.Atoi(s.File.GID) - if err != nil { - return err - } - - if err := os.Chown(fPath, rootIDs.UID+uid, rootIDs.GID+gid); err != nil { - return errors.Wrap(err, "error setting ownership for secret") - } - } - - label.Relabel(localMountPath, c.MountLabel, false) - - // remount secrets ro - if err := mount.Mount("tmpfs", localMountPath, "tmpfs", "remount,ro,"+tmpfsOwnership); err != nil { - return errors.Wrap(err, "unable to remount secret dir as readonly") - } - - return nil + return fmt.Errorf("secret store is not initialized") } func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) { @@ -246,49 +193,7 @@ func (daemon *Daemon) setupConfigDir(c *container.Container) (setupErr error) { } }() - if c.DependencyStore == nil { - return fmt.Errorf("config store is not initialized") - } - - for _, configRef := range c.ConfigReferences { - // TODO (ehazlett): use type switch when more are supported - if configRef.File == nil { - logrus.Error("config target type is not a file target") - continue - } - - fPath := c.ConfigFilePath(*configRef) - - log := logrus.WithFields(logrus.Fields{"name": configRef.File.Name, "path": fPath}) - - if err := idtools.MkdirAllAndChown(filepath.Dir(fPath), 0700, rootIDs); err != nil { - return errors.Wrap(err, "error creating config path") - } - - log.Debug("injecting config") - config, err := c.DependencyStore.Configs().Get(configRef.ConfigID) - if err != nil { - return errors.Wrap(err, "unable to get config from config store") - } - if err := ioutil.WriteFile(fPath, config.Spec.Data, configRef.File.Mode); err != nil { - return errors.Wrap(err, "error injecting config") - } - - uid, err := strconv.Atoi(configRef.File.UID) - if err != nil { - return err - } - gid, err := strconv.Atoi(configRef.File.GID) - if err != nil { - return err - } - - if err := os.Chown(fPath, rootIDs.UID+uid, rootIDs.GID+gid); err != nil { - return errors.Wrap(err, "error setting ownership for config") - } - } - - return nil + return fmt.Errorf("config store is not initialized") } func killProcessDirectly(cntr *container.Container) error { diff --git a/daemon/dependency.go b/daemon/dependency.go deleted file mode 100644 index 83144e6865..0000000000 --- a/daemon/dependency.go +++ /dev/null @@ -1,17 +0,0 @@ -package daemon - -import ( - "github.com/docker/swarmkit/agent/exec" -) - -// SetContainerDependencyStore sets the dependency store backend for the container -func (daemon *Daemon) SetContainerDependencyStore(name string, store exec.DependencyGetter) error { - c, err := daemon.GetContainer(name) - if err != nil { - return err - } - - c.DependencyStore = store - - return nil -} diff --git a/daemon/events.go b/daemon/events.go index f5d188cf0b..8fe8e1b640 100644 --- a/daemon/events.go +++ b/daemon/events.go @@ -1,27 +1,14 @@ package daemon import ( - "context" - "strconv" "strings" "time" - "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/container" daemonevents "github.com/docker/docker/daemon/events" "github.com/docker/libnetwork" - swarmapi "github.com/docker/swarmkit/api" - gogotypes "github.com/gogo/protobuf/types" -) - -var ( - clusterEventAction = map[swarmapi.WatchActionKind]string{ - swarmapi.WatchActionKindCreate: "create", - swarmapi.WatchActionKindUpdate: "update", - swarmapi.WatchActionKindRemove: "remove", - } ) // LogContainerEvent generates an event related to a container with only the default attributes. @@ -143,180 +130,3 @@ func copyAttributes(attributes, labels map[string]string) { attributes[k] = v } } - -// ProcessClusterNotifications gets changes from store and add them to event list -func (daemon *Daemon) ProcessClusterNotifications(ctx context.Context, watchStream chan *swarmapi.WatchMessage) { - for { - select { - case <-ctx.Done(): - return - case message, ok := <-watchStream: - if !ok { - logrus.Debug("cluster event channel has stopped") - return - } - daemon.generateClusterEvent(message) - } - } -} - -func (daemon *Daemon) generateClusterEvent(msg *swarmapi.WatchMessage) { - for _, event := range msg.Events { - if event.Object == nil { - logrus.Errorf("event without object: %v", event) - continue - } - switch v := event.Object.GetObject().(type) { - case *swarmapi.Object_Node: - daemon.logNodeEvent(event.Action, v.Node, event.OldObject.GetNode()) - case *swarmapi.Object_Service: - daemon.logServiceEvent(event.Action, v.Service, event.OldObject.GetService()) - case *swarmapi.Object_Network: - daemon.logNetworkEvent(event.Action, v.Network, event.OldObject.GetNetwork()) - case *swarmapi.Object_Secret: - daemon.logSecretEvent(event.Action, v.Secret, event.OldObject.GetSecret()) - default: - logrus.Warnf("unrecognized event: %v", event) - } - } -} - -func (daemon *Daemon) logNetworkEvent(action swarmapi.WatchActionKind, net *swarmapi.Network, oldNet *swarmapi.Network) { - attributes := map[string]string{ - "name": net.Spec.Annotations.Name, - } - eventTime := eventTimestamp(net.Meta, action) - daemon.logClusterEvent(action, net.ID, "network", attributes, eventTime) -} - -func (daemon *Daemon) logSecretEvent(action swarmapi.WatchActionKind, secret *swarmapi.Secret, oldSecret *swarmapi.Secret) { - attributes := map[string]string{ - "name": secret.Spec.Annotations.Name, - } - eventTime := eventTimestamp(secret.Meta, action) - daemon.logClusterEvent(action, secret.ID, "secret", attributes, eventTime) -} - -func (daemon *Daemon) logNodeEvent(action swarmapi.WatchActionKind, node *swarmapi.Node, oldNode *swarmapi.Node) { - name := node.Spec.Annotations.Name - if name == "" && node.Description != nil { - name = node.Description.Hostname - } - attributes := map[string]string{ - "name": name, - } - eventTime := eventTimestamp(node.Meta, action) - // In an update event, display the changes in attributes - if action == swarmapi.WatchActionKindUpdate && oldNode != nil { - if node.Spec.Availability != oldNode.Spec.Availability { - attributes["availability.old"] = strings.ToLower(oldNode.Spec.Availability.String()) - attributes["availability.new"] = strings.ToLower(node.Spec.Availability.String()) - } - if node.Role != oldNode.Role { - attributes["role.old"] = strings.ToLower(oldNode.Role.String()) - attributes["role.new"] = strings.ToLower(node.Role.String()) - } - if node.Status.State != oldNode.Status.State { - attributes["state.old"] = strings.ToLower(oldNode.Status.State.String()) - attributes["state.new"] = strings.ToLower(node.Status.State.String()) - } - // This handles change within manager role - if node.ManagerStatus != nil && oldNode.ManagerStatus != nil { - // leader change - if node.ManagerStatus.Leader != oldNode.ManagerStatus.Leader { - if node.ManagerStatus.Leader { - attributes["leader.old"] = "false" - attributes["leader.new"] = "true" - } else { - attributes["leader.old"] = "true" - attributes["leader.new"] = "false" - } - } - if node.ManagerStatus.Reachability != oldNode.ManagerStatus.Reachability { - attributes["reachability.old"] = strings.ToLower(oldNode.ManagerStatus.Reachability.String()) - attributes["reachability.new"] = strings.ToLower(node.ManagerStatus.Reachability.String()) - } - } - } - - daemon.logClusterEvent(action, node.ID, "node", attributes, eventTime) -} - -func (daemon *Daemon) logServiceEvent(action swarmapi.WatchActionKind, service *swarmapi.Service, oldService *swarmapi.Service) { - attributes := map[string]string{ - "name": service.Spec.Annotations.Name, - } - eventTime := eventTimestamp(service.Meta, action) - - if action == swarmapi.WatchActionKindUpdate && oldService != nil { - // check image - if x, ok := service.Spec.Task.GetRuntime().(*swarmapi.TaskSpec_Container); ok { - containerSpec := x.Container - if y, ok := oldService.Spec.Task.GetRuntime().(*swarmapi.TaskSpec_Container); ok { - oldContainerSpec := y.Container - if containerSpec.Image != oldContainerSpec.Image { - attributes["image.old"] = oldContainerSpec.Image - attributes["image.new"] = containerSpec.Image - } - } else { - // This should not happen. - logrus.Errorf("service %s runtime changed from %T to %T", service.Spec.Annotations.Name, oldService.Spec.Task.GetRuntime(), service.Spec.Task.GetRuntime()) - } - } - // check replicated count change - if x, ok := service.Spec.GetMode().(*swarmapi.ServiceSpec_Replicated); ok { - replicas := x.Replicated.Replicas - if y, ok := oldService.Spec.GetMode().(*swarmapi.ServiceSpec_Replicated); ok { - oldReplicas := y.Replicated.Replicas - if replicas != oldReplicas { - attributes["replicas.old"] = strconv.FormatUint(oldReplicas, 10) - attributes["replicas.new"] = strconv.FormatUint(replicas, 10) - } - } else { - // This should not happen. - logrus.Errorf("service %s mode changed from %T to %T", service.Spec.Annotations.Name, oldService.Spec.GetMode(), service.Spec.GetMode()) - } - } - if service.UpdateStatus != nil { - if oldService.UpdateStatus == nil { - attributes["updatestate.new"] = strings.ToLower(service.UpdateStatus.State.String()) - } else if service.UpdateStatus.State != oldService.UpdateStatus.State { - attributes["updatestate.old"] = strings.ToLower(oldService.UpdateStatus.State.String()) - attributes["updatestate.new"] = strings.ToLower(service.UpdateStatus.State.String()) - } - } - } - daemon.logClusterEvent(action, service.ID, "service", attributes, eventTime) -} - -func (daemon *Daemon) logClusterEvent(action swarmapi.WatchActionKind, id, eventType string, attributes map[string]string, eventTime time.Time) { - actor := events.Actor{ - ID: id, - Attributes: attributes, - } - - jm := events.Message{ - Action: clusterEventAction[action], - Type: eventType, - Actor: actor, - Scope: "swarm", - Time: eventTime.UTC().Unix(), - TimeNano: eventTime.UTC().UnixNano(), - } - daemon.EventsService.PublishMessage(jm) -} - -func eventTimestamp(meta swarmapi.Meta, action swarmapi.WatchActionKind) time.Time { - var eventTime time.Time - switch action { - case swarmapi.WatchActionKindCreate: - eventTime, _ = gogotypes.TimestampFromProto(meta.CreatedAt) - case swarmapi.WatchActionKindUpdate: - eventTime, _ = gogotypes.TimestampFromProto(meta.UpdatedAt) - case swarmapi.WatchActionKindRemove: - // There is no timestamp from store message for remove operations. - // Use current time. - eventTime = time.Now() - } - return eventTime -} diff --git a/vendor.conf b/vendor.conf index d96b3db19e..70d69d0a25 100644 --- a/vendor.conf +++ b/vendor.conf @@ -8,7 +8,6 @@ github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a github.com/go-check/check 4ed411733c5785b40214c70bce814c3a3a689609 https://github.com/cpuguy83/check.git github.com/gorilla/context v1.1 github.com/gorilla/mux v1.1 -github.com/jhowardmsft/opengcs v0.0.7 github.com/kr/pty 5cf931ef8f github.com/mattn/go-shellwords v1.0.3 github.com/tchap/go-patricia v2.2.6 @@ -130,11 +129,10 @@ github.com/opencontainers/selinux v1.0.0-rc1 # docker CLI github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c -github.com/docker/cli 9609891f575ae6c7763e01ec498ac1dbe741fba3 https://github.com/resin-os/docker-cli +github.com/docker/cli 62a0ec3494bea5f8b8cb9fc295f17a0e0e8a118a https://github.com/resin-os/docker-cli github.com/docker/docker-credential-helpers v0.5.1 github.com/docker/go d30aec9fd63c35133f8f79c3412ad91a3b08be06 github.com/docker/notary v0.4.2 -github.com/flynn-archive/go-shlex 3f9db97f856818214da2e1057f8ad84803971cff github.com/mitchellh/mapstructure f3009df150dadf309fdee4a54ed65c124afad715 github.com/xeipuuv/gojsonpointer e0fe6f68307607d540ed8eac07a342c33fa1b54a github.com/xeipuuv/gojsonreference e02fc20de94c78484cd5ffb007f8af96be030a45 diff --git a/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile.go b/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile.go deleted file mode 100644 index 07e2c8b081..0000000000 --- a/vendor/github.com/docker/cli/cli/command/bundlefile/bundlefile.go +++ /dev/null @@ -1,70 +0,0 @@ -package bundlefile - -import ( - "encoding/json" - "io" - - "github.com/pkg/errors" -) - -// Bundlefile stores the contents of a bundlefile -type Bundlefile struct { - Version string - Services map[string]Service -} - -// Service is a service from a bundlefile -type Service struct { - Image string - Command []string `json:",omitempty"` - Args []string `json:",omitempty"` - Env []string `json:",omitempty"` - Labels map[string]string `json:",omitempty"` - Ports []Port `json:",omitempty"` - WorkingDir *string `json:",omitempty"` - User *string `json:",omitempty"` - Networks []string `json:",omitempty"` -} - -// Port is a port as defined in a bundlefile -type Port struct { - Protocol string - Port uint32 -} - -// LoadFile loads a bundlefile from a path to the file -func LoadFile(reader io.Reader) (*Bundlefile, error) { - bundlefile := &Bundlefile{} - - decoder := json.NewDecoder(reader) - if err := decoder.Decode(bundlefile); err != nil { - switch jsonErr := err.(type) { - case *json.SyntaxError: - return nil, errors.Errorf( - "JSON syntax error at byte %v: %s", - jsonErr.Offset, - jsonErr.Error()) - case *json.UnmarshalTypeError: - return nil, errors.Errorf( - "Unexpected type at byte %v. Expected %s but received %s.", - jsonErr.Offset, - jsonErr.Type, - jsonErr.Value) - } - return nil, err - } - - return bundlefile, nil -} - -// Print writes the contents of the bundlefile to the output writer -// as human readable json -func Print(out io.Writer, bundle *Bundlefile) error { - bytes, err := json.MarshalIndent(*bundle, "", " ") - if err != nil { - return err - } - - _, err = out.Write(bytes) - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/cmd.go b/vendor/github.com/docker/cli/cli/command/checkpoint/cmd.go deleted file mode 100644 index 30e9ce364c..0000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/cmd.go +++ /dev/null @@ -1,24 +0,0 @@ -package checkpoint - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewCheckpointCommand returns the `checkpoint` subcommand (only in experimental) -func NewCheckpointCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "checkpoint", - Short: "Manage checkpoints", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"experimental": "", "version": "1.25"}, - } - cmd.AddCommand( - newCreateCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/create.go b/vendor/github.com/docker/cli/cli/command/checkpoint/create.go deleted file mode 100644 index 974b44ab83..0000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/create.go +++ /dev/null @@ -1,58 +0,0 @@ -package checkpoint - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -type createOptions struct { - container string - checkpoint string - checkpointDir string - leaveRunning bool -} - -func newCreateCommand(dockerCli command.Cli) *cobra.Command { - var opts createOptions - - cmd := &cobra.Command{ - Use: "create [OPTIONS] CONTAINER CHECKPOINT", - Short: "Create a checkpoint from a running container", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - opts.container = args[0] - opts.checkpoint = args[1] - return runCreate(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVar(&opts.leaveRunning, "leave-running", false, "Leave the container running after checkpoint") - flags.StringVarP(&opts.checkpointDir, "checkpoint-dir", "", "", "Use a custom checkpoint storage directory") - - return cmd -} - -func runCreate(dockerCli command.Cli, opts createOptions) error { - client := dockerCli.Client() - - checkpointOpts := types.CheckpointCreateOptions{ - CheckpointID: opts.checkpoint, - CheckpointDir: opts.checkpointDir, - Exit: !opts.leaveRunning, - } - - err := client.CheckpointCreate(context.Background(), opts.container, checkpointOpts) - if err != nil { - return err - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", opts.checkpoint) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/list.go b/vendor/github.com/docker/cli/cli/command/checkpoint/list.go deleted file mode 100644 index 758aa69936..0000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/list.go +++ /dev/null @@ -1,54 +0,0 @@ -package checkpoint - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -type listOptions struct { - checkpointDir string -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - var opts listOptions - - cmd := &cobra.Command{ - Use: "ls [OPTIONS] CONTAINER", - Aliases: []string{"list"}, - Short: "List checkpoints for a container", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, args[0], opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.checkpointDir, "checkpoint-dir", "", "", "Use a custom checkpoint storage directory") - - return cmd - -} - -func runList(dockerCli command.Cli, container string, opts listOptions) error { - client := dockerCli.Client() - - listOpts := types.CheckpointListOptions{ - CheckpointDir: opts.checkpointDir, - } - - checkpoints, err := client.CheckpointList(context.Background(), container, listOpts) - if err != nil { - return err - } - - cpCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewCheckpointFormat(formatter.TableFormatKey), - } - return formatter.CheckpointWrite(cpCtx, checkpoints) -} diff --git a/vendor/github.com/docker/cli/cli/command/checkpoint/remove.go b/vendor/github.com/docker/cli/cli/command/checkpoint/remove.go deleted file mode 100644 index 298adbaef7..0000000000 --- a/vendor/github.com/docker/cli/cli/command/checkpoint/remove.go +++ /dev/null @@ -1,44 +0,0 @@ -package checkpoint - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" -) - -type removeOptions struct { - checkpointDir string -} - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - var opts removeOptions - - cmd := &cobra.Command{ - Use: "rm [OPTIONS] CONTAINER CHECKPOINT", - Aliases: []string{"remove"}, - Short: "Remove a checkpoint", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, args[0], args[1], opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.checkpointDir, "checkpoint-dir", "", "", "Use a custom checkpoint storage directory") - - return cmd -} - -func runRemove(dockerCli command.Cli, container string, checkpoint string, opts removeOptions) error { - client := dockerCli.Client() - - removeOpts := types.CheckpointDeleteOptions{ - CheckpointID: checkpoint, - CheckpointDir: opts.checkpointDir, - } - - return client.CheckpointDelete(context.Background(), container, removeOpts) -} diff --git a/vendor/github.com/docker/cli/cli/command/commands/commands.go b/vendor/github.com/docker/cli/cli/command/commands/commands.go index c6fc8d6ace..9f29dacc3f 100644 --- a/vendor/github.com/docker/cli/cli/command/commands/commands.go +++ b/vendor/github.com/docker/cli/cli/command/commands/commands.go @@ -4,18 +4,10 @@ import ( "os" "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/checkpoint" - "github.com/docker/cli/cli/command/config" "github.com/docker/cli/cli/command/container" "github.com/docker/cli/cli/command/image" "github.com/docker/cli/cli/command/network" - "github.com/docker/cli/cli/command/node" - "github.com/docker/cli/cli/command/plugin" "github.com/docker/cli/cli/command/registry" - "github.com/docker/cli/cli/command/secret" - "github.com/docker/cli/cli/command/service" - "github.com/docker/cli/cli/command/stack" - "github.com/docker/cli/cli/command/swarm" "github.com/docker/cli/cli/command/system" "github.com/docker/cli/cli/command/volume" "github.com/spf13/cobra" @@ -24,12 +16,6 @@ import ( // AddCommands adds all the commands from cli/command to the root command func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) { cmd.AddCommand( - // checkpoint - checkpoint.NewCheckpointCommand(dockerCli), - - // config - config.NewConfigCommand(dockerCli), - // container container.NewContainerCommand(dockerCli), container.NewRunCommand(dockerCli), @@ -38,37 +24,18 @@ func AddCommands(cmd *cobra.Command, dockerCli *command.DockerCli) { image.NewImageCommand(dockerCli), image.NewBuildCommand(dockerCli), - // node - node.NewNodeCommand(dockerCli), - // network network.NewNetworkCommand(dockerCli), - // plugin - plugin.NewPluginCommand(dockerCli), - // registry registry.NewLoginCommand(dockerCli), registry.NewLogoutCommand(dockerCli), registry.NewSearchCommand(dockerCli), - // secret - secret.NewSecretCommand(dockerCli), - - // service - service.NewServiceCommand(dockerCli), - // system system.NewSystemCommand(dockerCli), system.NewVersionCommand(dockerCli), - // stack - stack.NewStackCommand(dockerCli), - stack.NewTopLevelDeployCommand(dockerCli), - - // swarm - swarm.NewSwarmCommand(dockerCli), - // volume volume.NewVolumeCommand(dockerCli), diff --git a/vendor/github.com/docker/cli/cli/command/config/cmd.go b/vendor/github.com/docker/cli/cli/command/config/cmd.go deleted file mode 100644 index 1f762596c2..0000000000 --- a/vendor/github.com/docker/cli/cli/command/config/cmd.go +++ /dev/null @@ -1,27 +0,0 @@ -package config - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewConfigCommand returns a cobra command for `config` subcommands -// nolint: interfacer -func NewConfigCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "config", - Short: "Manage Docker configs", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.30"}, - } - cmd.AddCommand( - newConfigListCommand(dockerCli), - newConfigCreateCommand(dockerCli), - newConfigInspectCommand(dockerCli), - newConfigRemoveCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/config/create.go b/vendor/github.com/docker/cli/cli/command/config/create.go deleted file mode 100644 index 437137c160..0000000000 --- a/vendor/github.com/docker/cli/cli/command/config/create.go +++ /dev/null @@ -1,79 +0,0 @@ -package config - -import ( - "fmt" - "io" - "io/ioutil" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/system" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type createOptions struct { - name string - file string - labels opts.ListOpts -} - -func newConfigCreateCommand(dockerCli command.Cli) *cobra.Command { - createOpts := createOptions{ - labels: opts.NewListOpts(opts.ValidateEnv), - } - - cmd := &cobra.Command{ - Use: "create [OPTIONS] CONFIG file|-", - Short: "Create a configuration file from a file or STDIN as content", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - createOpts.name = args[0] - createOpts.file = args[1] - return runConfigCreate(dockerCli, createOpts) - }, - } - flags := cmd.Flags() - flags.VarP(&createOpts.labels, "label", "l", "Config labels") - - return cmd -} - -func runConfigCreate(dockerCli command.Cli, options createOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var in io.Reader = dockerCli.In() - if options.file != "-" { - file, err := system.OpenSequential(options.file) - if err != nil { - return err - } - in = file - defer file.Close() - } - - configData, err := ioutil.ReadAll(in) - if err != nil { - return errors.Errorf("Error reading content from %q: %v", options.file, err) - } - - spec := swarm.ConfigSpec{ - Annotations: swarm.Annotations{ - Name: options.name, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - }, - Data: configData, - } - - r, err := client.ConfigCreate(ctx, spec) - if err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), r.ID) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/config/inspect.go b/vendor/github.com/docker/cli/cli/command/config/inspect.go deleted file mode 100644 index d7a3422a71..0000000000 --- a/vendor/github.com/docker/cli/cli/command/config/inspect.go +++ /dev/null @@ -1,66 +0,0 @@ -package config - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - names []string - format string - pretty bool -} - -func newConfigInspectCommand(dockerCli command.Cli) *cobra.Command { - opts := inspectOptions{} - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] CONFIG [CONFIG...]", - Short: "Display detailed information on one or more configuration files", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.names = args - return runConfigInspect(dockerCli, opts) - }, - } - - cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - cmd.Flags().BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runConfigInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(id string) (interface{}, []byte, error) { - return client.ConfigInspectWithRaw(ctx, id) - } - f := opts.format - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return fmt.Errorf("Cannot supply extra formatting options to the pretty template") - } - - configCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewConfigFormat(f, false), - } - - if err := formatter.ConfigInspectWrite(configCtx, opts.names, getRef); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil - -} diff --git a/vendor/github.com/docker/cli/cli/command/config/ls.go b/vendor/github.com/docker/cli/cli/command/config/ls.go deleted file mode 100644 index f01e3b9154..0000000000 --- a/vendor/github.com/docker/cli/cli/command/config/ls.go +++ /dev/null @@ -1,63 +0,0 @@ -package config - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newConfigListCommand(dockerCli command.Cli) *cobra.Command { - listOpts := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List configs", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runConfigList(dockerCli, listOpts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&listOpts.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVarP(&listOpts.format, "format", "", "", "Pretty-print configs using a Go template") - flags.VarP(&listOpts.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runConfigList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - configs, err := client.ConfigList(ctx, types.ConfigListOptions{Filters: options.filter.Value()}) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().ConfigFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().ConfigFormat - } else { - format = formatter.TableFormatKey - } - } - - configCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewConfigFormat(format, options.quiet), - } - return formatter.ConfigWrite(configCtx, configs) -} diff --git a/vendor/github.com/docker/cli/cli/command/config/remove.go b/vendor/github.com/docker/cli/cli/command/config/remove.go deleted file mode 100644 index 5512986d90..0000000000 --- a/vendor/github.com/docker/cli/cli/command/config/remove.go +++ /dev/null @@ -1,53 +0,0 @@ -package config - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type removeOptions struct { - names []string -} - -func newConfigRemoveCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "rm CONFIG [CONFIG...]", - Aliases: []string{"remove"}, - Short: "Remove one or more configuration files", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts := removeOptions{ - names: args, - } - return runConfigRemove(dockerCli, opts) - }, - } -} - -func runConfigRemove(dockerCli command.Cli, opts removeOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - - for _, name := range opts.names { - if err := client.ConfigRemove(ctx, name); err != nil { - errs = append(errs, err.Error()) - continue - } - - fmt.Fprintln(dockerCli.Out(), name) - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/idresolver/idresolver.go b/vendor/github.com/docker/cli/cli/command/idresolver/idresolver.go deleted file mode 100644 index 6088b64b59..0000000000 --- a/vendor/github.com/docker/cli/cli/command/idresolver/idresolver.go +++ /dev/null @@ -1,70 +0,0 @@ -package idresolver - -import ( - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/pkg/errors" -) - -// IDResolver provides ID to Name resolution. -type IDResolver struct { - client client.APIClient - noResolve bool - cache map[string]string -} - -// New creates a new IDResolver. -func New(client client.APIClient, noResolve bool) *IDResolver { - return &IDResolver{ - client: client, - noResolve: noResolve, - cache: make(map[string]string), - } -} - -func (r *IDResolver) get(ctx context.Context, t interface{}, id string) (string, error) { - switch t.(type) { - case swarm.Node: - node, _, err := r.client.NodeInspectWithRaw(ctx, id) - if err != nil { - return id, nil - } - if node.Spec.Annotations.Name != "" { - return node.Spec.Annotations.Name, nil - } - if node.Description.Hostname != "" { - return node.Description.Hostname, nil - } - return id, nil - case swarm.Service: - service, _, err := r.client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{}) - if err != nil { - return id, nil - } - return service.Spec.Annotations.Name, nil - default: - return "", errors.Errorf("unsupported type") - } - -} - -// Resolve will attempt to resolve an ID to a Name by querying the manager. -// Results are stored into a cache. -// If the `-n` flag is used in the command-line, resolution is disabled. -func (r *IDResolver) Resolve(ctx context.Context, t interface{}, id string) (string, error) { - if r.noResolve { - return id, nil - } - if name, ok := r.cache[id]; ok { - return name, nil - } - name, err := r.get(ctx, t, id) - if err != nil { - return "", err - } - r.cache[id] = name - return name, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/cmd.go b/vendor/github.com/docker/cli/cli/command/node/cmd.go deleted file mode 100644 index b3090d5d71..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/cmd.go +++ /dev/null @@ -1,57 +0,0 @@ -package node - -import ( - "errors" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - apiclient "github.com/docker/docker/client" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -// NewNodeCommand returns a cobra command for `node` subcommands -func NewNodeCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "node", - Short: "Manage Swarm nodes", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.24"}, - } - cmd.AddCommand( - newDemoteCommand(dockerCli), - newInspectCommand(dockerCli), - newListCommand(dockerCli), - newPromoteCommand(dockerCli), - newRemoveCommand(dockerCli), - newPsCommand(dockerCli), - newUpdateCommand(dockerCli), - ) - return cmd -} - -// Reference returns the reference of a node. The special value "self" for a node -// reference is mapped to the current node, hence the node ID is retrieved using -// the `/info` endpoint. -func Reference(ctx context.Context, client apiclient.APIClient, ref string) (string, error) { - if ref == "self" { - info, err := client.Info(ctx) - if err != nil { - return "", err - } - if info.Swarm.NodeID == "" { - // If there's no node ID in /info, the node probably - // isn't a manager. Call a swarm-specific endpoint to - // get a more specific error message. - _, err = client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return "", err - } - return "", errors.New("node ID not found in /info") - } - return info.Swarm.NodeID, nil - } - return ref, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/demote.go b/vendor/github.com/docker/cli/cli/command/node/demote.go deleted file mode 100644 index 5250dfc0be..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/demote.go +++ /dev/null @@ -1,36 +0,0 @@ -package node - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/spf13/cobra" -) - -func newDemoteCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "demote NODE [NODE...]", - Short: "Demote one or more nodes from manager in the swarm", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runDemote(dockerCli, args) - }, - } -} - -func runDemote(dockerCli command.Cli, nodes []string) error { - demote := func(node *swarm.Node) error { - if node.Spec.Role == swarm.NodeRoleWorker { - fmt.Fprintf(dockerCli.Out(), "Node %s is already a worker.\n", node.ID) - return errNoRoleChange - } - node.Spec.Role = swarm.NodeRoleWorker - return nil - } - success := func(nodeID string) { - fmt.Fprintf(dockerCli.Out(), "Manager %s demoted in the swarm.\n", nodeID) - } - return updateNodes(dockerCli, nodes, demote, success) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/inspect.go b/vendor/github.com/docker/cli/cli/command/node/inspect.go deleted file mode 100644 index ffb4efe459..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/inspect.go +++ /dev/null @@ -1,72 +0,0 @@ -package node - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - nodeIds []string - format string - pretty bool -} - -func newInspectCommand(dockerCli command.Cli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] self|NODE [NODE...]", - Short: "Display detailed information on one or more nodes", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.nodeIds = args - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - flags.BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(ref string) (interface{}, []byte, error) { - nodeRef, err := Reference(ctx, client, ref) - if err != nil { - return nil, nil, err - } - node, _, err := client.NodeInspectWithRaw(ctx, nodeRef) - return node, nil, err - } - f := opts.format - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return fmt.Errorf("Cannot supply extra formatting options to the pretty template") - } - - nodeCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewNodeFormat(f, false), - } - - if err := formatter.NodeInspectWrite(nodeCtx, opts.nodeIds, getRef); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/list.go b/vendor/github.com/docker/cli/cli/command/node/list.go deleted file mode 100644 index 0c3d7e1abc..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/list.go +++ /dev/null @@ -1,72 +0,0 @@ -package node - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List nodes in the swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print nodes using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - nodes, err := client.NodeList( - ctx, - types.NodeListOptions{Filters: options.filter.Value()}) - if err != nil { - return err - } - - info := types.Info{} - if len(nodes) > 0 && !options.quiet { - // only non-empty nodes and not quiet, should we call /info api - info, err = client.Info(ctx) - if err != nil { - return err - } - } - - format := options.format - if len(format) == 0 { - format = formatter.TableFormatKey - if len(dockerCli.ConfigFile().NodesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().NodesFormat - } - } - - nodesCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewNodeFormat(format, options.quiet), - } - return formatter.NodeWrite(nodesCtx, nodes, info) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/opts.go b/vendor/github.com/docker/cli/cli/command/node/opts.go deleted file mode 100644 index e30e5de910..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/opts.go +++ /dev/null @@ -1,23 +0,0 @@ -package node - -import ( - "github.com/docker/cli/opts" -) - -type nodeOptions struct { - annotations - role string - availability string -} - -type annotations struct { - labels opts.ListOpts -} - -func newNodeOptions() *nodeOptions { - return &nodeOptions{ - annotations: annotations{ - labels: opts.NewListOpts(nil), - }, - } -} diff --git a/vendor/github.com/docker/cli/cli/command/node/promote.go b/vendor/github.com/docker/cli/cli/command/node/promote.go deleted file mode 100644 index 4612cc13ff..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/promote.go +++ /dev/null @@ -1,36 +0,0 @@ -package node - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/spf13/cobra" -) - -func newPromoteCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "promote NODE [NODE...]", - Short: "Promote one or more nodes to manager in the swarm", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runPromote(dockerCli, args) - }, - } -} - -func runPromote(dockerCli command.Cli, nodes []string) error { - promote := func(node *swarm.Node) error { - if node.Spec.Role == swarm.NodeRoleManager { - fmt.Fprintf(dockerCli.Out(), "Node %s is already a manager.\n", node.ID) - return errNoRoleChange - } - node.Spec.Role = swarm.NodeRoleManager - return nil - } - success := func(nodeID string) { - fmt.Fprintf(dockerCli.Out(), "Node %s promoted to a manager in the swarm.\n", nodeID) - } - return updateNodes(dockerCli, nodes, promote, success) -} diff --git a/vendor/github.com/docker/cli/cli/command/node/ps.go b/vendor/github.com/docker/cli/cli/command/node/ps.go deleted file mode 100644 index 6a586a3bcc..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/ps.go +++ /dev/null @@ -1,109 +0,0 @@ -package node - -import ( - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/cli/command/task" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type psOptions struct { - nodeIDs []string - noResolve bool - noTrunc bool - quiet bool - format string - filter opts.FilterOpt -} - -func newPsCommand(dockerCli command.Cli) *cobra.Command { - options := psOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ps [OPTIONS] [NODE...]", - Short: "List tasks running on one or more nodes, defaults to current node", - Args: cli.RequiresMinArgs(0), - RunE: func(cmd *cobra.Command, args []string) error { - options.nodeIDs = []string{"self"} - - if len(args) != 0 { - options.nodeIDs = args - } - - return runPs(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&options.noResolve, "no-resolve", false, "Do not map IDs to Names") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - flags.StringVar(&options.format, "format", "", "Pretty-print tasks using a Go template") - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display task IDs") - - return cmd -} - -func runPs(dockerCli command.Cli, options psOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var ( - errs []string - tasks []swarm.Task - ) - - for _, nodeID := range options.nodeIDs { - nodeRef, err := Reference(ctx, client, nodeID) - if err != nil { - errs = append(errs, err.Error()) - continue - } - - node, _, err := client.NodeInspectWithRaw(ctx, nodeRef) - if err != nil { - errs = append(errs, err.Error()) - continue - } - - filter := options.filter.Value() - filter.Add("node", node.ID) - - nodeTasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) - if err != nil { - errs = append(errs, err.Error()) - continue - } - - tasks = append(tasks, nodeTasks...) - } - - format := options.format - if len(format) == 0 { - if dockerCli.ConfigFile() != nil && len(dockerCli.ConfigFile().TasksFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().TasksFormat - } else { - format = formatter.TableFormatKey - } - } - - if len(errs) == 0 || len(tasks) != 0 { - if err := task.Print(ctx, dockerCli, tasks, idresolver.New(client, options.noResolve), !options.noTrunc, options.quiet, format); err != nil { - errs = append(errs, err.Error()) - } - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/remove.go b/vendor/github.com/docker/cli/cli/command/node/remove.go deleted file mode 100644 index d23ec2fb5c..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/remove.go +++ /dev/null @@ -1,57 +0,0 @@ -package node - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type removeOptions struct { - force bool -} - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - opts := removeOptions{} - - cmd := &cobra.Command{ - Use: "rm [OPTIONS] NODE [NODE...]", - Aliases: []string{"remove"}, - Short: "Remove one or more nodes from the swarm", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, args, opts) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&opts.force, "force", "f", false, "Force remove a node from the swarm") - return cmd -} - -func runRemove(dockerCli command.Cli, args []string, opts removeOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - - for _, nodeID := range args { - err := client.NodeRemove(ctx, nodeID, types.NodeRemoveOptions{Force: opts.force}) - if err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintf(dockerCli.Out(), "%s\n", nodeID) - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/node/update.go b/vendor/github.com/docker/cli/cli/command/node/update.go deleted file mode 100644 index 017cf7dcb5..0000000000 --- a/vendor/github.com/docker/cli/cli/command/node/update.go +++ /dev/null @@ -1,120 +0,0 @@ -package node - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -var ( - errNoRoleChange = errors.New("role was already set to the requested value") -) - -func newUpdateCommand(dockerCli command.Cli) *cobra.Command { - options := newNodeOptions() - - cmd := &cobra.Command{ - Use: "update [OPTIONS] NODE", - Short: "Update a node", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runUpdate(dockerCli, cmd.Flags(), args[0]) - }, - } - - flags := cmd.Flags() - flags.StringVar(&options.role, flagRole, "", `Role of the node ("worker"|"manager")`) - flags.StringVar(&options.availability, flagAvailability, "", `Availability of the node ("active"|"pause"|"drain")`) - flags.Var(&options.annotations.labels, flagLabelAdd, "Add or update a node label (key=value)") - labelKeys := opts.NewListOpts(nil) - flags.Var(&labelKeys, flagLabelRemove, "Remove a node label if exists") - return cmd -} - -func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, nodeID string) error { - success := func(_ string) { - fmt.Fprintln(dockerCli.Out(), nodeID) - } - return updateNodes(dockerCli, []string{nodeID}, mergeNodeUpdate(flags), success) -} - -func updateNodes(dockerCli command.Cli, nodes []string, mergeNode func(node *swarm.Node) error, success func(nodeID string)) error { - client := dockerCli.Client() - ctx := context.Background() - - for _, nodeID := range nodes { - node, _, err := client.NodeInspectWithRaw(ctx, nodeID) - if err != nil { - return err - } - - err = mergeNode(&node) - if err != nil { - if err == errNoRoleChange { - continue - } - return err - } - err = client.NodeUpdate(ctx, node.ID, node.Version, node.Spec) - if err != nil { - return err - } - success(nodeID) - } - return nil -} - -func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) error { - return func(node *swarm.Node) error { - spec := &node.Spec - - if flags.Changed(flagRole) { - str, err := flags.GetString(flagRole) - if err != nil { - return err - } - spec.Role = swarm.NodeRole(str) - } - if flags.Changed(flagAvailability) { - str, err := flags.GetString(flagAvailability) - if err != nil { - return err - } - spec.Availability = swarm.NodeAvailability(str) - } - if spec.Annotations.Labels == nil { - spec.Annotations.Labels = make(map[string]string) - } - if flags.Changed(flagLabelAdd) { - labels := flags.Lookup(flagLabelAdd).Value.(*opts.ListOpts).GetAll() - for k, v := range opts.ConvertKVStringsToMap(labels) { - spec.Annotations.Labels[k] = v - } - } - if flags.Changed(flagLabelRemove) { - keys := flags.Lookup(flagLabelRemove).Value.(*opts.ListOpts).GetAll() - for _, k := range keys { - // if a key doesn't exist, fail the command explicitly - if _, exists := spec.Annotations.Labels[k]; !exists { - return errors.Errorf("key %s doesn't exist in node's labels", k) - } - delete(spec.Annotations.Labels, k) - } - } - return nil - } -} - -const ( - flagRole = "role" - flagAvailability = "availability" - flagLabelAdd = "label-add" - flagLabelRemove = "label-rm" -) diff --git a/vendor/github.com/docker/cli/cli/command/plugin/cmd.go b/vendor/github.com/docker/cli/cli/command/plugin/cmd.go deleted file mode 100644 index c298934937..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/cmd.go +++ /dev/null @@ -1,33 +0,0 @@ -package plugin - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewPluginCommand returns a cobra command for `plugin` subcommands -// nolint: interfacer -func NewPluginCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "plugin", - Short: "Manage plugins", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.25"}, - } - - cmd.AddCommand( - newDisableCommand(dockerCli), - newEnableCommand(dockerCli), - newInspectCommand(dockerCli), - newInstallCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - newSetCommand(dockerCli), - newPushCommand(dockerCli), - newCreateCommand(dockerCli), - newUpgradeCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/create.go b/vendor/github.com/docker/cli/cli/command/plugin/create.go deleted file mode 100644 index 5184ce1da5..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/create.go +++ /dev/null @@ -1,128 +0,0 @@ -package plugin - -import ( - "encoding/json" - "fmt" - "io" - "os" - "path/filepath" - - "github.com/Sirupsen/logrus" - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/archive" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -// validateTag checks if the given repoName can be resolved. -func validateTag(rawRepo string) error { - _, err := reference.ParseNormalizedNamed(rawRepo) - - return err -} - -// validateConfig ensures that a valid config.json is available in the given path -func validateConfig(path string) error { - dt, err := os.Open(filepath.Join(path, "config.json")) - if err != nil { - return err - } - - m := types.PluginConfig{} - err = json.NewDecoder(dt).Decode(&m) - dt.Close() - - return err -} - -// validateContextDir validates the given dir and returns abs path on success. -func validateContextDir(contextDir string) (string, error) { - absContextDir, err := filepath.Abs(contextDir) - if err != nil { - return "", err - } - stat, err := os.Lstat(absContextDir) - if err != nil { - return "", err - } - - if !stat.IsDir() { - return "", errors.Errorf("context must be a directory") - } - - return absContextDir, nil -} - -type pluginCreateOptions struct { - repoName string - context string - compress bool -} - -func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command { - options := pluginCreateOptions{} - - cmd := &cobra.Command{ - Use: "create [OPTIONS] PLUGIN PLUGIN-DATA-DIR", - Short: "Create a plugin from a rootfs and configuration. Plugin data directory must contain config.json and rootfs directory.", - Args: cli.RequiresMinArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - options.repoName = args[0] - options.context = args[1] - return runCreate(dockerCli, options) - }, - } - - flags := cmd.Flags() - - flags.BoolVar(&options.compress, "compress", false, "Compress the context using gzip") - - return cmd -} - -func runCreate(dockerCli *command.DockerCli, options pluginCreateOptions) error { - var ( - createCtx io.ReadCloser - err error - ) - - if err := validateTag(options.repoName); err != nil { - return err - } - - absContextDir, err := validateContextDir(options.context) - if err != nil { - return err - } - - if err := validateConfig(options.context); err != nil { - return err - } - - compression := archive.Uncompressed - if options.compress { - logrus.Debugf("compression enabled") - compression = archive.Gzip - } - - createCtx, err = archive.TarWithOptions(absContextDir, &archive.TarOptions{ - Compression: compression, - }) - - if err != nil { - return err - } - - ctx := context.Background() - - createOptions := types.PluginCreateOptions{RepoName: options.repoName} - if err = dockerCli.Client().PluginCreate(ctx, createCtx, createOptions); err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), options.repoName) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/disable.go b/vendor/github.com/docker/cli/cli/command/plugin/disable.go deleted file mode 100644 index 1ab33ccf82..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/disable.go +++ /dev/null @@ -1,36 +0,0 @@ -package plugin - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -func newDisableCommand(dockerCli *command.DockerCli) *cobra.Command { - var force bool - - cmd := &cobra.Command{ - Use: "disable [OPTIONS] PLUGIN", - Short: "Disable a plugin", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runDisable(dockerCli, args[0], force) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&force, "force", "f", false, "Force the disable of an active plugin") - return cmd -} - -func runDisable(dockerCli *command.DockerCli, name string, force bool) error { - if err := dockerCli.Client().PluginDisable(context.Background(), name, types.PluginDisableOptions{Force: force}); err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), name) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/enable.go b/vendor/github.com/docker/cli/cli/command/plugin/enable.go deleted file mode 100644 index 53a7acd0c2..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/enable.go +++ /dev/null @@ -1,48 +0,0 @@ -package plugin - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type enableOpts struct { - timeout int - name string -} - -func newEnableCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts enableOpts - - cmd := &cobra.Command{ - Use: "enable [OPTIONS] PLUGIN", - Short: "Enable a plugin", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.name = args[0] - return runEnable(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.IntVar(&opts.timeout, "timeout", 0, "HTTP client timeout (in seconds)") - return cmd -} - -func runEnable(dockerCli *command.DockerCli, opts *enableOpts) error { - name := opts.name - if opts.timeout < 0 { - return errors.Errorf("negative timeout %d is invalid", opts.timeout) - } - - if err := dockerCli.Client().PluginEnable(context.Background(), name, types.PluginEnableOptions{Timeout: opts.timeout}); err != nil { - return err - } - fmt.Fprintln(dockerCli.Out(), name) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/inspect.go b/vendor/github.com/docker/cli/cli/command/plugin/inspect.go deleted file mode 100644 index 00ae300d57..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/inspect.go +++ /dev/null @@ -1,42 +0,0 @@ -package plugin - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/inspect" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - pluginNames []string - format string -} - -func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] PLUGIN [PLUGIN...]", - Short: "Display detailed information on one or more plugins", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.pluginNames = args - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - return cmd -} - -func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - getRef := func(ref string) (interface{}, []byte, error) { - return client.PluginInspectWithRaw(ctx, ref) - } - - return inspect.Inspect(dockerCli.Out(), opts.pluginNames, opts.format, getRef) -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/install.go b/vendor/github.com/docker/cli/cli/command/plugin/install.go deleted file mode 100644 index 85fd8bad5f..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/install.go +++ /dev/null @@ -1,168 +0,0 @@ -package plugin - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/registry" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -type pluginOptions struct { - remote string - localName string - grantPerms bool - disable bool - args []string - skipRemoteCheck bool -} - -func loadPullFlags(opts *pluginOptions, flags *pflag.FlagSet) { - flags.BoolVar(&opts.grantPerms, "grant-all-permissions", false, "Grant all permissions necessary to run the plugin") - command.AddTrustVerificationFlags(flags) -} - -func newInstallCommand(dockerCli *command.DockerCli) *cobra.Command { - var options pluginOptions - cmd := &cobra.Command{ - Use: "install [OPTIONS] PLUGIN [KEY=VALUE...]", - Short: "Install a plugin", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.remote = args[0] - if len(args) > 1 { - options.args = args[1:] - } - return runInstall(dockerCli, options) - }, - } - - flags := cmd.Flags() - loadPullFlags(&options, flags) - flags.BoolVar(&options.disable, "disable", false, "Do not enable the plugin on install") - flags.StringVar(&options.localName, "alias", "", "Local name for plugin") - return cmd -} - -type pluginRegistryService struct { - registry.Service -} - -func (s pluginRegistryService) ResolveRepository(name reference.Named) (repoInfo *registry.RepositoryInfo, err error) { - repoInfo, err = s.Service.ResolveRepository(name) - if repoInfo != nil { - repoInfo.Class = "plugin" - } - return -} - -func newRegistryService() registry.Service { - return pluginRegistryService{ - Service: registry.NewService(registry.ServiceOptions{V2Only: true}), - } -} - -func buildPullConfig(ctx context.Context, dockerCli *command.DockerCli, opts pluginOptions, cmdName string) (types.PluginInstallOptions, error) { - // Names with both tag and digest will be treated by the daemon - // as a pull by digest with a local name for the tag - // (if no local name is provided). - ref, err := reference.ParseNormalizedNamed(opts.remote) - if err != nil { - return types.PluginInstallOptions{}, err - } - - repoInfo, err := registry.ParseRepositoryInfo(ref) - if err != nil { - return types.PluginInstallOptions{}, err - } - - remote := ref.String() - - _, isCanonical := ref.(reference.Canonical) - if command.IsTrusted() && !isCanonical { - ref = reference.TagNameOnly(ref) - nt, ok := ref.(reference.NamedTagged) - if !ok { - return types.PluginInstallOptions{}, errors.Errorf("invalid name: %s", ref.String()) - } - - ctx := context.Background() - trusted, err := image.TrustedReference(ctx, dockerCli, nt, newRegistryService()) - if err != nil { - return types.PluginInstallOptions{}, err - } - remote = reference.FamiliarString(trusted) - } - - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) - - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return types.PluginInstallOptions{}, err - } - registryAuthFunc := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, cmdName) - - options := types.PluginInstallOptions{ - RegistryAuth: encodedAuth, - RemoteRef: remote, - Disabled: opts.disable, - AcceptAllPermissions: opts.grantPerms, - AcceptPermissionsFunc: acceptPrivileges(dockerCli, opts.remote), - // TODO: Rename PrivilegeFunc, it has nothing to do with privileges - PrivilegeFunc: registryAuthFunc, - Args: opts.args, - } - return options, nil -} - -func runInstall(dockerCli *command.DockerCli, opts pluginOptions) error { - var localName string - if opts.localName != "" { - aref, err := reference.ParseNormalizedNamed(opts.localName) - if err != nil { - return err - } - if _, ok := aref.(reference.Canonical); ok { - return errors.Errorf("invalid name: %s", opts.localName) - } - localName = reference.FamiliarString(reference.TagNameOnly(aref)) - } - - ctx := context.Background() - options, err := buildPullConfig(ctx, dockerCli, opts, "plugin install") - if err != nil { - return err - } - responseBody, err := dockerCli.Client().PluginInstall(ctx, localName, options) - if err != nil { - if strings.Contains(err.Error(), "(image) when fetching") { - return errors.New(err.Error() + " - Use `docker image pull`") - } - return err - } - defer responseBody.Close() - if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil { - return err - } - fmt.Fprintf(dockerCli.Out(), "Installed plugin %s\n", opts.remote) // todo: return proper values from the API for this result - return nil -} - -func acceptPrivileges(dockerCli *command.DockerCli, name string) func(privileges types.PluginPrivileges) (bool, error) { - return func(privileges types.PluginPrivileges) (bool, error) { - fmt.Fprintf(dockerCli.Out(), "Plugin %q is requesting the following privileges:\n", name) - for _, privilege := range privileges { - fmt.Fprintf(dockerCli.Out(), " - %s: %v\n", privilege.Name, privilege.Value) - } - return command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Do you grant the above permissions?"), nil - } -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/list.go b/vendor/github.com/docker/cli/cli/command/plugin/list.go deleted file mode 100644 index c4bbeb5b46..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/list.go +++ /dev/null @@ -1,63 +0,0 @@ -package plugin - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - noTrunc bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli *command.DockerCli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Short: "List plugins", - Aliases: []string{"list"}, - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - - flags := cmd.Flags() - - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display plugin IDs") - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Don't truncate output") - flags.StringVar(&options.format, "format", "", "Pretty-print plugins using a Go template") - flags.VarP(&options.filter, "filter", "f", "Provide filter values (e.g. 'enabled=true')") - - return cmd -} - -func runList(dockerCli *command.DockerCli, options listOptions) error { - plugins, err := dockerCli.Client().PluginList(context.Background(), options.filter.Value()) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().PluginsFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().PluginsFormat - } else { - format = formatter.TableFormatKey - } - } - - pluginsCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewPluginFormat(format, options.quiet), - Trunc: !options.noTrunc, - } - return formatter.PluginWrite(pluginsCtx, plugins) -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/push.go b/vendor/github.com/docker/cli/cli/command/plugin/push.go deleted file mode 100644 index 68d25157c6..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/push.go +++ /dev/null @@ -1,69 +0,0 @@ -package plugin - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/image" - "github.com/docker/distribution/reference" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/docker/docker/registry" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func newPushCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "push [OPTIONS] PLUGIN[:TAG]", - Short: "Push a plugin to a registry", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runPush(dockerCli, args[0]) - }, - } - - flags := cmd.Flags() - - command.AddTrustSigningFlags(flags) - - return cmd -} - -func runPush(dockerCli command.Cli, name string) error { - named, err := reference.ParseNormalizedNamed(name) - if err != nil { - return err - } - if _, ok := named.(reference.Canonical); ok { - return errors.Errorf("invalid name: %s", name) - } - - named = reference.TagNameOnly(named) - - ctx := context.Background() - - repoInfo, err := registry.ParseRepositoryInfo(named) - if err != nil { - return err - } - authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index) - - encodedAuth, err := command.EncodeAuthToBase64(authConfig) - if err != nil { - return err - } - - responseBody, err := dockerCli.Client().PluginPush(ctx, reference.FamiliarString(named), encodedAuth) - if err != nil { - return err - } - defer responseBody.Close() - - if command.IsTrusted() { - repoInfo.Class = "plugin" - return image.PushTrustedReference(dockerCli, repoInfo, named, authConfig, responseBody) - } - - return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil) -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/remove.go b/vendor/github.com/docker/cli/cli/command/plugin/remove.go deleted file mode 100644 index 32211147e7..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/remove.go +++ /dev/null @@ -1,55 +0,0 @@ -package plugin - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type rmOptions struct { - force bool - - plugins []string -} - -func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts rmOptions - - cmd := &cobra.Command{ - Use: "rm [OPTIONS] PLUGIN [PLUGIN...]", - Short: "Remove one or more plugins", - Aliases: []string{"remove"}, - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.plugins = args - return runRemove(dockerCli, &opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.force, "force", "f", false, "Force the removal of an active plugin") - return cmd -} - -func runRemove(dockerCli *command.DockerCli, opts *rmOptions) error { - ctx := context.Background() - - var errs cli.Errors - for _, name := range opts.plugins { - // TODO: pass names to api instead of making multiple api calls - if err := dockerCli.Client().PluginRemove(ctx, name, types.PluginRemoveOptions{Force: opts.force}); err != nil { - errs = append(errs, err) - continue - } - fmt.Fprintln(dockerCli.Out(), name) - } - // Do not simplify to `return errs` because even if errs == nil, it is not a nil-error interface value. - if errs != nil { - return errs - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/set.go b/vendor/github.com/docker/cli/cli/command/plugin/set.go deleted file mode 100644 index 7a69995cdb..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/set.go +++ /dev/null @@ -1,22 +0,0 @@ -package plugin - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -func newSetCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "set PLUGIN KEY=VALUE [KEY=VALUE...]", - Short: "Change settings for a plugin", - Args: cli.RequiresMinArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - return dockerCli.Client().PluginSet(context.Background(), args[0], args[1:]) - }, - } - - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/plugin/upgrade.go b/vendor/github.com/docker/cli/cli/command/plugin/upgrade.go deleted file mode 100644 index 0e3f56ff62..0000000000 --- a/vendor/github.com/docker/cli/cli/command/plugin/upgrade.go +++ /dev/null @@ -1,90 +0,0 @@ -package plugin - -import ( - "context" - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/distribution/reference" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func newUpgradeCommand(dockerCli *command.DockerCli) *cobra.Command { - var options pluginOptions - cmd := &cobra.Command{ - Use: "upgrade [OPTIONS] PLUGIN [REMOTE]", - Short: "Upgrade an existing plugin", - Args: cli.RequiresRangeArgs(1, 2), - RunE: func(cmd *cobra.Command, args []string) error { - options.localName = args[0] - if len(args) == 2 { - options.remote = args[1] - } - return runUpgrade(dockerCli, options) - }, - Tags: map[string]string{"version": "1.26"}, - } - - flags := cmd.Flags() - loadPullFlags(&options, flags) - flags.BoolVar(&options.skipRemoteCheck, "skip-remote-check", false, "Do not check if specified remote plugin matches existing plugin image") - return cmd -} - -func runUpgrade(dockerCli *command.DockerCli, opts pluginOptions) error { - ctx := context.Background() - p, _, err := dockerCli.Client().PluginInspectWithRaw(ctx, opts.localName) - if err != nil { - return errors.Errorf("error reading plugin data: %v", err) - } - - if p.Enabled { - return errors.Errorf("the plugin must be disabled before upgrading") - } - - opts.localName = p.Name - if opts.remote == "" { - opts.remote = p.PluginReference - } - remote, err := reference.ParseNormalizedNamed(opts.remote) - if err != nil { - return errors.Wrap(err, "error parsing remote upgrade image reference") - } - remote = reference.TagNameOnly(remote) - - old, err := reference.ParseNormalizedNamed(p.PluginReference) - if err != nil { - return errors.Wrap(err, "error parsing current image reference") - } - old = reference.TagNameOnly(old) - - fmt.Fprintf(dockerCli.Out(), "Upgrading plugin %s from %s to %s\n", p.Name, reference.FamiliarString(old), reference.FamiliarString(remote)) - if !opts.skipRemoteCheck && remote.String() != old.String() { - if !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Plugin images do not match, are you sure?") { - return errors.New("canceling upgrade request") - } - } - - options, err := buildPullConfig(ctx, dockerCli, opts, "plugin upgrade") - if err != nil { - return err - } - - responseBody, err := dockerCli.Client().PluginUpgrade(ctx, opts.localName, options) - if err != nil { - if strings.Contains(err.Error(), "target is image") { - return errors.New(err.Error() + " - Use `docker image pull`") - } - return err - } - defer responseBody.Close() - if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil { - return err - } - fmt.Fprintf(dockerCli.Out(), "Upgraded plugin %s to %s\n", opts.localName, opts.remote) // todo: return proper values from the API for this result - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/cmd.go b/vendor/github.com/docker/cli/cli/command/secret/cmd.go deleted file mode 100644 index 9f8e84345e..0000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/cmd.go +++ /dev/null @@ -1,27 +0,0 @@ -package secret - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewSecretCommand returns a cobra command for `secret` subcommands -// nolint: interfacer -func NewSecretCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "secret", - Short: "Manage Docker secrets", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.25"}, - } - cmd.AddCommand( - newSecretListCommand(dockerCli), - newSecretCreateCommand(dockerCli), - newSecretInspectCommand(dockerCli), - newSecretRemoveCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/create.go b/vendor/github.com/docker/cli/cli/command/secret/create.go deleted file mode 100644 index 20efaec752..0000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/create.go +++ /dev/null @@ -1,79 +0,0 @@ -package secret - -import ( - "fmt" - "io" - "io/ioutil" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/system" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type createOptions struct { - name string - file string - labels opts.ListOpts -} - -func newSecretCreateCommand(dockerCli command.Cli) *cobra.Command { - options := createOptions{ - labels: opts.NewListOpts(opts.ValidateEnv), - } - - cmd := &cobra.Command{ - Use: "create [OPTIONS] SECRET file|-", - Short: "Create a secret from a file or STDIN as content", - Args: cli.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - options.name = args[0] - options.file = args[1] - return runSecretCreate(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.VarP(&options.labels, "label", "l", "Secret labels") - - return cmd -} - -func runSecretCreate(dockerCli command.Cli, options createOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var in io.Reader = dockerCli.In() - if options.file != "-" { - file, err := system.OpenSequential(options.file) - if err != nil { - return err - } - in = file - defer file.Close() - } - - secretData, err := ioutil.ReadAll(in) - if err != nil { - return errors.Errorf("Error reading content from %q: %v", options.file, err) - } - - spec := swarm.SecretSpec{ - Annotations: swarm.Annotations{ - Name: options.name, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - }, - Data: secretData, - } - - r, err := client.SecretCreate(ctx, spec) - if err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), r.ID) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/inspect.go b/vendor/github.com/docker/cli/cli/command/secret/inspect.go deleted file mode 100644 index 51410487a5..0000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/inspect.go +++ /dev/null @@ -1,65 +0,0 @@ -package secret - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type inspectOptions struct { - names []string - format string - pretty bool -} - -func newSecretInspectCommand(dockerCli command.Cli) *cobra.Command { - opts := inspectOptions{} - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] SECRET [SECRET...]", - Short: "Display detailed information on one or more secrets", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.names = args - return runSecretInspect(dockerCli, opts) - }, - } - - cmd.Flags().StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - cmd.Flags().BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runSecretInspect(dockerCli command.Cli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(id string) (interface{}, []byte, error) { - return client.SecretInspectWithRaw(ctx, id) - } - f := opts.format - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return fmt.Errorf("Cannot supply extra formatting options to the pretty template") - } - - secretCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewSecretFormat(f, false), - } - - if err := formatter.SecretInspectWrite(secretCtx, opts.names, getRef); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/ls.go b/vendor/github.com/docker/cli/cli/command/secret/ls.go deleted file mode 100644 index 35bc3da0f2..0000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/ls.go +++ /dev/null @@ -1,61 +0,0 @@ -package secret - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newSecretListCommand(dockerCli command.Cli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List secrets", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runSecretList(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVarP(&options.format, "format", "", "", "Pretty-print secrets using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runSecretList(dockerCli command.Cli, options listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - secrets, err := client.SecretList(ctx, types.SecretListOptions{Filters: options.filter.Value()}) - if err != nil { - return err - } - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().SecretFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().SecretFormat - } else { - format = formatter.TableFormatKey - } - } - secretCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewSecretFormat(format, options.quiet), - } - return formatter.SecretWrite(secretCtx, secrets) -} diff --git a/vendor/github.com/docker/cli/cli/command/secret/remove.go b/vendor/github.com/docker/cli/cli/command/secret/remove.go deleted file mode 100644 index 969b9ceb75..0000000000 --- a/vendor/github.com/docker/cli/cli/command/secret/remove.go +++ /dev/null @@ -1,53 +0,0 @@ -package secret - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type removeOptions struct { - names []string -} - -func newSecretRemoveCommand(dockerCli command.Cli) *cobra.Command { - return &cobra.Command{ - Use: "rm SECRET [SECRET...]", - Aliases: []string{"remove"}, - Short: "Remove one or more secrets", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts := removeOptions{ - names: args, - } - return runSecretRemove(dockerCli, opts) - }, - } -} - -func runSecretRemove(dockerCli command.Cli, opts removeOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - - for _, name := range opts.names { - if err := client.SecretRemove(ctx, name); err != nil { - errs = append(errs, err.Error()) - continue - } - - fmt.Fprintln(dockerCli.Out(), name) - } - - if len(errs) > 0 { - return errors.Errorf("%s", strings.Join(errs, "\n")) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/cmd.go b/vendor/github.com/docker/cli/cli/command/service/cmd.go deleted file mode 100644 index 94e3a97d4e..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/cmd.go +++ /dev/null @@ -1,31 +0,0 @@ -package service - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewServiceCommand returns a cobra command for `service` subcommands -// nolint: interfacer -func NewServiceCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "service", - Short: "Manage services", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.24"}, - } - cmd.AddCommand( - newCreateCommand(dockerCli), - newInspectCommand(dockerCli), - newPsCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - newScaleCommand(dockerCli), - newUpdateCommand(dockerCli), - newLogsCommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/service/create.go b/vendor/github.com/docker/cli/cli/command/service/create.go deleted file mode 100644 index ef73ec19ed..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/create.go +++ /dev/null @@ -1,135 +0,0 @@ -package service - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command { - opts := newServiceOptions() - - cmd := &cobra.Command{ - Use: "create [OPTIONS] IMAGE [COMMAND] [ARG...]", - Short: "Create a new service", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.image = args[0] - if len(args) > 1 { - opts.args = args[1:] - } - return runCreate(dockerCli, cmd.Flags(), opts) - }, - } - flags := cmd.Flags() - flags.StringVar(&opts.mode, flagMode, "replicated", "Service mode (replicated or global)") - flags.StringVar(&opts.name, flagName, "", "Service name") - - addServiceFlags(flags, opts, buildServiceDefaultFlagMapping()) - - flags.VarP(&opts.labels, flagLabel, "l", "Service labels") - flags.Var(&opts.containerLabels, flagContainerLabel, "Container labels") - flags.VarP(&opts.env, flagEnv, "e", "Set environment variables") - flags.Var(&opts.envFile, flagEnvFile, "Read in a file of environment variables") - flags.Var(&opts.mounts, flagMount, "Attach a filesystem mount to the service") - flags.Var(&opts.constraints, flagConstraint, "Placement constraints") - flags.Var(&opts.placementPrefs, flagPlacementPref, "Add a placement preference") - flags.SetAnnotation(flagPlacementPref, "version", []string{"1.28"}) - flags.Var(&opts.networks, flagNetwork, "Network attachments") - flags.Var(&opts.secrets, flagSecret, "Specify secrets to expose to the service") - flags.SetAnnotation(flagSecret, "version", []string{"1.25"}) - flags.Var(&opts.configs, flagConfig, "Specify configurations to expose to the service") - flags.SetAnnotation(flagConfig, "version", []string{"1.30"}) - flags.VarP(&opts.endpoint.publishPorts, flagPublish, "p", "Publish a port as a node port") - flags.Var(&opts.groups, flagGroup, "Set one or more supplementary user groups for the container") - flags.SetAnnotation(flagGroup, "version", []string{"1.25"}) - flags.Var(&opts.dns, flagDNS, "Set custom DNS servers") - flags.SetAnnotation(flagDNS, "version", []string{"1.25"}) - flags.Var(&opts.dnsOption, flagDNSOption, "Set DNS options") - flags.SetAnnotation(flagDNSOption, "version", []string{"1.25"}) - flags.Var(&opts.dnsSearch, flagDNSSearch, "Set custom DNS search domains") - flags.SetAnnotation(flagDNSSearch, "version", []string{"1.25"}) - flags.Var(&opts.hosts, flagHost, "Set one or more custom host-to-IP mappings (host:ip)") - flags.SetAnnotation(flagHost, "version", []string{"1.25"}) - - flags.SetInterspersed(false) - return cmd -} - -func runCreate(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *serviceOptions) error { - apiClient := dockerCli.Client() - createOpts := types.ServiceCreateOptions{} - - ctx := context.Background() - - service, err := opts.ToService(ctx, apiClient, flags) - if err != nil { - return err - } - - specifiedSecrets := opts.secrets.Value() - if len(specifiedSecrets) > 0 { - // parse and validate secrets - secrets, err := ParseSecrets(apiClient, specifiedSecrets) - if err != nil { - return err - } - service.TaskTemplate.ContainerSpec.Secrets = secrets - } - - specifiedConfigs := opts.configs.Value() - if len(specifiedConfigs) > 0 { - // parse and validate configs - configs, err := ParseConfigs(apiClient, specifiedConfigs) - if err != nil { - return err - } - service.TaskTemplate.ContainerSpec.Configs = configs - } - - if err := resolveServiceImageDigestContentTrust(dockerCli, &service); err != nil { - return err - } - - // only send auth if flag was set - if opts.registryAuth { - // Retrieve encoded auth token from the image reference - encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, opts.image) - if err != nil { - return err - } - createOpts.EncodedRegistryAuth = encodedAuth - } - - // query registry if flag disabling it was not set - if !opts.noResolveImage && versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.30") { - createOpts.QueryRegistry = true - } - - response, err := apiClient.ServiceCreate(ctx, service, createOpts) - if err != nil { - return err - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", response.ID) - - if opts.detach { - if !flags.Changed("detach") { - fmt.Fprintln(dockerCli.Err(), "Since --detach=false was not specified, tasks will be created in the background.\n"+ - "In a future release, --detach=false will become the default.") - } - return nil - } - - return waitOnService(ctx, dockerCli, response.ID, opts) -} diff --git a/vendor/github.com/docker/cli/cli/command/service/helpers.go b/vendor/github.com/docker/cli/cli/command/service/helpers.go deleted file mode 100644 index 8bc745dcef..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/helpers.go +++ /dev/null @@ -1,33 +0,0 @@ -package service - -import ( - "io" - "io/ioutil" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/service/progress" - "github.com/docker/docker/pkg/jsonmessage" - "golang.org/x/net/context" -) - -// waitOnService waits for the service to converge. It outputs a progress bar, -// if appropriate based on the CLI flags. -func waitOnService(ctx context.Context, dockerCli *command.DockerCli, serviceID string, opts *serviceOptions) error { - errChan := make(chan error, 1) - pipeReader, pipeWriter := io.Pipe() - - go func() { - errChan <- progress.ServiceProgress(ctx, dockerCli.Client(), serviceID, pipeWriter) - }() - - if opts.quiet { - go io.Copy(ioutil.Discard, pipeReader) - return <-errChan - } - - err := jsonmessage.DisplayJSONMessagesToStream(pipeReader, dockerCli.Out(), nil) - if err == nil { - err = <-errChan - } - return err -} diff --git a/vendor/github.com/docker/cli/cli/command/service/inspect.go b/vendor/github.com/docker/cli/cli/command/service/inspect.go deleted file mode 100644 index ea0009d3a5..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/inspect.go +++ /dev/null @@ -1,94 +0,0 @@ -package service - -import ( - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/docker/api/types" - apiclient "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type inspectOptions struct { - refs []string - format string - pretty bool -} - -func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts inspectOptions - - cmd := &cobra.Command{ - Use: "inspect [OPTIONS] SERVICE [SERVICE...]", - Short: "Display detailed information on one or more services", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.refs = args - - if opts.pretty && len(opts.format) > 0 { - return errors.Errorf("--format is incompatible with human friendly format") - } - return runInspect(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template") - flags.BoolVar(&opts.pretty, "pretty", false, "Print the information in a human friendly format") - return cmd -} - -func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.pretty { - opts.format = "pretty" - } - - getRef := func(ref string) (interface{}, []byte, error) { - // Service inspect shows defaults values in empty fields. - service, _, err := client.ServiceInspectWithRaw(ctx, ref, types.ServiceInspectOptions{InsertDefaults: true}) - if err == nil || !apiclient.IsErrServiceNotFound(err) { - return service, nil, err - } - return nil, nil, errors.Errorf("Error: no such service: %s", ref) - } - - getNetwork := func(ref string) (interface{}, []byte, error) { - network, _, err := client.NetworkInspectWithRaw(ctx, ref, types.NetworkInspectOptions{Scope: "swarm"}) - if err == nil || !apiclient.IsErrNetworkNotFound(err) { - return network, nil, err - } - return nil, nil, errors.Errorf("Error: no such network: %s", ref) - } - - f := opts.format - if len(f) == 0 { - f = "raw" - if len(dockerCli.ConfigFile().ServiceInspectFormat) > 0 { - f = dockerCli.ConfigFile().ServiceInspectFormat - } - } - - // check if the user is trying to apply a template to the pretty format, which - // is not supported - if strings.HasPrefix(f, "pretty") && f != "pretty" { - return errors.Errorf("Cannot supply extra formatting options to the pretty template") - } - - serviceCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewServiceFormat(f), - } - - if err := formatter.ServiceInspectWrite(serviceCtx, opts.refs, getRef, getNetwork); err != nil { - return cli.StatusError{StatusCode: 1, Status: err.Error()} - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/list.go b/vendor/github.com/docker/cli/cli/command/service/list.go deleted file mode 100644 index 5b359d307a..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/list.go +++ /dev/null @@ -1,129 +0,0 @@ -package service - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - quiet bool - format string - filter opts.FilterOpt -} - -func newListCommand(dockerCli *command.DockerCli) *cobra.Command { - options := listOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ls [OPTIONS]", - Aliases: []string{"list"}, - Short: "List services", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, options) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print services using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runList(dockerCli *command.DockerCli, options listOptions) error { - ctx := context.Background() - client := dockerCli.Client() - - serviceFilters := options.filter.Value() - services, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceFilters}) - if err != nil { - return err - } - - info := map[string]formatter.ServiceListInfo{} - if len(services) > 0 && !options.quiet { - // only non-empty services and not quiet, should we call TaskList and NodeList api - taskFilter := filters.NewArgs() - for _, service := range services { - taskFilter.Add("service", service.ID) - } - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter}) - if err != nil { - return err - } - - nodes, err := client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return err - } - - info = GetServicesStatus(services, nodes, tasks) - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().ServicesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().ServicesFormat - } else { - format = formatter.TableFormatKey - } - } - - servicesCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewServiceListFormat(format, options.quiet), - } - return formatter.ServiceListWrite(servicesCtx, services, info) -} - -// GetServicesStatus returns a map of mode and replicas -func GetServicesStatus(services []swarm.Service, nodes []swarm.Node, tasks []swarm.Task) map[string]formatter.ServiceListInfo { - running := map[string]int{} - tasksNoShutdown := map[string]int{} - - activeNodes := make(map[string]struct{}) - for _, n := range nodes { - if n.Status.State != swarm.NodeStateDown { - activeNodes[n.ID] = struct{}{} - } - } - - for _, task := range tasks { - if task.DesiredState != swarm.TaskStateShutdown { - tasksNoShutdown[task.ServiceID]++ - } - - if _, nodeActive := activeNodes[task.NodeID]; nodeActive && task.Status.State == swarm.TaskStateRunning { - running[task.ServiceID]++ - } - } - - info := map[string]formatter.ServiceListInfo{} - for _, service := range services { - info[service.ID] = formatter.ServiceListInfo{} - if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil { - info[service.ID] = formatter.ServiceListInfo{ - Mode: "replicated", - Replicas: fmt.Sprintf("%d/%d", running[service.ID], *service.Spec.Mode.Replicated.Replicas), - } - } else if service.Spec.Mode.Global != nil { - info[service.ID] = formatter.ServiceListInfo{ - Mode: "global", - Replicas: fmt.Sprintf("%d/%d", running[service.ID], tasksNoShutdown[service.ID]), - } - } - } - return info -} diff --git a/vendor/github.com/docker/cli/cli/command/service/logs.go b/vendor/github.com/docker/cli/cli/command/service/logs.go deleted file mode 100644 index 3d3b3f1d46..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/logs.go +++ /dev/null @@ -1,349 +0,0 @@ -package service - -import ( - "bytes" - "fmt" - "io" - "sort" - "strconv" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/stdcopy" - "github.com/docker/docker/pkg/stringid" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -type logsOptions struct { - noResolve bool - noTrunc bool - noTaskIDs bool - follow bool - since string - timestamps bool - tail string - details bool - raw bool - - target string -} - -func newLogsCommand(dockerCli *command.DockerCli) *cobra.Command { - var opts logsOptions - - cmd := &cobra.Command{ - Use: "logs [OPTIONS] SERVICE|TASK", - Short: "Fetch the logs of a service or task", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.target = args[0] - return runLogs(dockerCli, &opts) - }, - Tags: map[string]string{"version": "1.29"}, - } - - flags := cmd.Flags() - // options specific to service logs - flags.BoolVar(&opts.noResolve, "no-resolve", false, "Do not map IDs to Names in output") - flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&opts.raw, "raw", false, "Do not neatly format logs") - flags.SetAnnotation("raw", "version", []string{"1.30"}) - flags.BoolVar(&opts.noTaskIDs, "no-task-ids", false, "Do not include task IDs in output") - // options identical to container logs - flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output") - flags.StringVar(&opts.since, "since", "", "Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)") - flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps") - flags.BoolVar(&opts.details, "details", false, "Show extra details provided to logs") - flags.SetAnnotation("details", "version", []string{"1.30"}) - flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs") - return cmd -} - -func runLogs(dockerCli *command.DockerCli, opts *logsOptions) error { - ctx := context.Background() - - options := types.ContainerLogsOptions{ - ShowStdout: true, - ShowStderr: true, - Since: opts.since, - Timestamps: opts.timestamps, - Follow: opts.follow, - Tail: opts.tail, - // get the details if we request it OR if we're not doing raw mode - // (we need them for the context to pretty print) - Details: opts.details || !opts.raw, - } - - cli := dockerCli.Client() - - var ( - maxLength = 1 - responseBody io.ReadCloser - tty bool - // logfunc is used to delay the call to logs so that we can do some - // processing before we actually get the logs - logfunc func(context.Context, string, types.ContainerLogsOptions) (io.ReadCloser, error) - ) - - service, _, err := cli.ServiceInspectWithRaw(ctx, opts.target, types.ServiceInspectOptions{}) - if err != nil { - // if it's any error other than service not found, it's Real - if !client.IsErrServiceNotFound(err) { - return err - } - task, _, err := cli.TaskInspectWithRaw(ctx, opts.target) - if err != nil { - if client.IsErrTaskNotFound(err) { - // if the task isn't found, rewrite the error to be clear - // that we looked for services AND tasks and found none - err = fmt.Errorf("no such task or service: %v", opts.target) - } - return err - } - - tty = task.Spec.ContainerSpec.TTY - maxLength = getMaxLength(task.Slot) - - // use the TaskLogs api function - logfunc = cli.TaskLogs - } else { - // use ServiceLogs api function - logfunc = cli.ServiceLogs - tty = service.Spec.TaskTemplate.ContainerSpec.TTY - if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil { - // if replicas are initialized, figure out if we need to pad them - replicas := *service.Spec.Mode.Replicated.Replicas - maxLength = getMaxLength(int(replicas)) - } - } - - // we can't prettify tty logs. tell the user that this is the case. - // this is why we assign the logs function to a variable and delay calling - // it. we want to check this before we make the call and checking twice in - // each branch is even sloppier than this CLI disaster already is - if tty && !opts.raw { - return errors.New("tty service logs only supported with --raw") - } - - // now get the logs - responseBody, err = logfunc(ctx, opts.target, options) - if err != nil { - return err - } - defer responseBody.Close() - - // tty logs get straight copied. they're not muxed with stdcopy - if tty { - _, err = io.Copy(dockerCli.Out(), responseBody) - return err - } - - // otherwise, logs are multiplexed. if we're doing pretty printing, also - // create a task formatter. - var stdout, stderr io.Writer - stdout = dockerCli.Out() - stderr = dockerCli.Err() - if !opts.raw { - taskFormatter := newTaskFormatter(cli, opts, maxLength) - - stdout = &logWriter{ctx: ctx, opts: opts, f: taskFormatter, w: stdout} - stderr = &logWriter{ctx: ctx, opts: opts, f: taskFormatter, w: stderr} - } - - _, err = stdcopy.StdCopy(stdout, stderr, responseBody) - return err -} - -// getMaxLength gets the maximum length of the number in base 10 -func getMaxLength(i int) int { - return len(strconv.Itoa(i)) -} - -type taskFormatter struct { - client client.APIClient - opts *logsOptions - padding int - - r *idresolver.IDResolver - // cache saves a pre-cooked logContext formatted string based on a - // logcontext object, so we don't have to resolve names every time - cache map[logContext]string -} - -func newTaskFormatter(client client.APIClient, opts *logsOptions, padding int) *taskFormatter { - return &taskFormatter{ - client: client, - opts: opts, - padding: padding, - r: idresolver.New(client, opts.noResolve), - cache: make(map[logContext]string), - } -} - -func (f *taskFormatter) format(ctx context.Context, logCtx logContext) (string, error) { - if cached, ok := f.cache[logCtx]; ok { - return cached, nil - } - - nodeName, err := f.r.Resolve(ctx, swarm.Node{}, logCtx.nodeID) - if err != nil { - return "", err - } - - serviceName, err := f.r.Resolve(ctx, swarm.Service{}, logCtx.serviceID) - if err != nil { - return "", err - } - - task, _, err := f.client.TaskInspectWithRaw(ctx, logCtx.taskID) - if err != nil { - return "", err - } - - taskName := fmt.Sprintf("%s.%d", serviceName, task.Slot) - if !f.opts.noTaskIDs { - if f.opts.noTrunc { - taskName += fmt.Sprintf(".%s", task.ID) - } else { - taskName += fmt.Sprintf(".%s", stringid.TruncateID(task.ID)) - } - } - - paddingCount := f.padding - getMaxLength(task.Slot) - padding := "" - if paddingCount > 0 { - padding = strings.Repeat(" ", paddingCount) - } - formatted := taskName + "@" + nodeName + padding - f.cache[logCtx] = formatted - return formatted, nil -} - -type logWriter struct { - ctx context.Context - opts *logsOptions - f *taskFormatter - w io.Writer -} - -func (lw *logWriter) Write(buf []byte) (int, error) { - // this works but ONLY because stdcopy calls write a whole line at a time. - // if this ends up horribly broken or panics, check to see if stdcopy has - // reneged on that assumption. (@god forgive me) - // also this only works because the logs format is, like, barely parsable. - // if something changes in the logs format, this is gonna break - - // there should always be at least 2 parts: details and message. if there - // is no timestamp, details will be first (index 0) when we split on - // spaces. if there is a timestamp, details will be 2nd (`index 1) - detailsIndex := 0 - numParts := 2 - if lw.opts.timestamps { - detailsIndex++ - numParts++ - } - - // break up the log line into parts. - parts := bytes.SplitN(buf, []byte(" "), numParts) - if len(parts) != numParts { - return 0, errors.Errorf("invalid context in log message: %v", string(buf)) - } - // parse the details out - details, err := client.ParseLogDetails(string(parts[detailsIndex])) - if err != nil { - return 0, err - } - // and then create a context from the details - // this removes the context-specific details from the details map, so we - // can more easily print the details later - logCtx, err := lw.parseContext(details) - if err != nil { - return 0, err - } - - output := []byte{} - // if we included timestamps, add them to the front - if lw.opts.timestamps { - output = append(output, parts[0]...) - output = append(output, ' ') - } - // add the context, nice and formatted - formatted, err := lw.f.format(lw.ctx, logCtx) - if err != nil { - return 0, err - } - output = append(output, []byte(formatted+" | ")...) - // if the user asked for details, add them to be log message - if lw.opts.details { - // ugh i hate this it's basically a dupe of api/server/httputils/write_log_stream.go:stringAttrs() - // ok but we're gonna do it a bit different - - // there are optimizations that can be made here. for starters, i'd - // suggest caching the details keys. then, we can maybe draw maps and - // slices from a pool to avoid alloc overhead on them. idk if it's - // worth the time yet. - - // first we need a slice - d := make([]string, 0, len(details)) - // then let's add all the pairs - for k := range details { - d = append(d, k+"="+details[k]) - } - // then sort em - sort.Strings(d) - // then join and append - output = append(output, []byte(strings.Join(d, ","))...) - output = append(output, ' ') - } - - // add the log message itself, finally - output = append(output, parts[detailsIndex+1]...) - - _, err = lw.w.Write(output) - if err != nil { - return 0, err - } - - return len(buf), nil -} - -// parseContext returns a log context and REMOVES the context from the details map -func (lw *logWriter) parseContext(details map[string]string) (logContext, error) { - nodeID, ok := details["com.docker.swarm.node.id"] - if !ok { - return logContext{}, errors.Errorf("missing node id in details: %v", details) - } - delete(details, "com.docker.swarm.node.id") - - serviceID, ok := details["com.docker.swarm.service.id"] - if !ok { - return logContext{}, errors.Errorf("missing service id in details: %v", details) - } - delete(details, "com.docker.swarm.service.id") - - taskID, ok := details["com.docker.swarm.task.id"] - if !ok { - return logContext{}, errors.Errorf("missing task id in details: %s", details) - } - delete(details, "com.docker.swarm.task.id") - - return logContext{ - nodeID: nodeID, - serviceID: serviceID, - taskID: taskID, - }, nil -} - -type logContext struct { - nodeID string - serviceID string - taskID string -} diff --git a/vendor/github.com/docker/cli/cli/command/service/opts.go b/vendor/github.com/docker/cli/cli/command/service/opts.go deleted file mode 100644 index 4c1425c42c..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/opts.go +++ /dev/null @@ -1,874 +0,0 @@ -package service - -import ( - "fmt" - "sort" - "strconv" - "strings" - "time" - - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/swarmkit/api" - "github.com/docker/swarmkit/api/defaults" - shlex "github.com/flynn-archive/go-shlex" - gogotypes "github.com/gogo/protobuf/types" - "github.com/pkg/errors" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -type int64Value interface { - Value() int64 -} - -// Uint64Opt represents a uint64. -type Uint64Opt struct { - value *uint64 -} - -// Set a new value on the option -func (i *Uint64Opt) Set(s string) error { - v, err := strconv.ParseUint(s, 0, 64) - i.value = &v - return err -} - -// Type returns the type of this option, which will be displayed in `--help` output -func (i *Uint64Opt) Type() string { - return "uint" -} - -// String returns a string repr of this option -func (i *Uint64Opt) String() string { - if i.value != nil { - return fmt.Sprintf("%v", *i.value) - } - return "" -} - -// Value returns the uint64 -func (i *Uint64Opt) Value() *uint64 { - return i.value -} - -type floatValue float32 - -func (f *floatValue) Set(s string) error { - v, err := strconv.ParseFloat(s, 32) - *f = floatValue(v) - return err -} - -func (f *floatValue) Type() string { - return "float" -} - -func (f *floatValue) String() string { - return strconv.FormatFloat(float64(*f), 'g', -1, 32) -} - -func (f *floatValue) Value() float32 { - return float32(*f) -} - -// placementPrefOpts holds a list of placement preferences. -type placementPrefOpts struct { - prefs []swarm.PlacementPreference - strings []string -} - -func (opts *placementPrefOpts) String() string { - if len(opts.strings) == 0 { - return "" - } - return fmt.Sprintf("%v", opts.strings) -} - -// Set validates the input value and adds it to the internal slices. -// Note: in the future strategies other than "spread", may be supported, -// as well as additional comma-separated options. -func (opts *placementPrefOpts) Set(value string) error { - fields := strings.Split(value, "=") - if len(fields) != 2 { - return errors.New(`placement preference must be of the format "="`) - } - if fields[0] != "spread" { - return errors.Errorf("unsupported placement preference %s (only spread is supported)", fields[0]) - } - - opts.prefs = append(opts.prefs, swarm.PlacementPreference{ - Spread: &swarm.SpreadOver{ - SpreadDescriptor: fields[1], - }, - }) - opts.strings = append(opts.strings, value) - return nil -} - -// Type returns a string name for this Option type -func (opts *placementPrefOpts) Type() string { - return "pref" -} - -// ShlexOpt is a flag Value which parses a string as a list of shell words -type ShlexOpt []string - -// Set the value -func (s *ShlexOpt) Set(value string) error { - valueSlice, err := shlex.Split(value) - *s = ShlexOpt(valueSlice) - return err -} - -// Type returns the tyep of the value -func (s *ShlexOpt) Type() string { - return "command" -} - -func (s *ShlexOpt) String() string { - if len(*s) == 0 { - return "" - } - return fmt.Sprint(*s) -} - -// Value returns the value as a string slice -func (s *ShlexOpt) Value() []string { - return []string(*s) -} - -type updateOptions struct { - parallelism uint64 - delay time.Duration - monitor time.Duration - onFailure string - maxFailureRatio floatValue - order string -} - -func updateConfigFromDefaults(defaultUpdateConfig *api.UpdateConfig) *swarm.UpdateConfig { - defaultFailureAction := strings.ToLower(api.UpdateConfig_FailureAction_name[int32(defaultUpdateConfig.FailureAction)]) - defaultMonitor, _ := gogotypes.DurationFromProto(defaultUpdateConfig.Monitor) - return &swarm.UpdateConfig{ - Parallelism: defaultUpdateConfig.Parallelism, - Delay: defaultUpdateConfig.Delay, - Monitor: defaultMonitor, - FailureAction: defaultFailureAction, - MaxFailureRatio: defaultUpdateConfig.MaxFailureRatio, - Order: defaultOrder(defaultUpdateConfig.Order), - } -} - -func (opts updateOptions) updateConfig(flags *pflag.FlagSet) *swarm.UpdateConfig { - if !anyChanged(flags, flagUpdateParallelism, flagUpdateDelay, flagUpdateMonitor, flagUpdateFailureAction, flagUpdateMaxFailureRatio) { - return nil - } - - updateConfig := updateConfigFromDefaults(defaults.Service.Update) - - if flags.Changed(flagUpdateParallelism) { - updateConfig.Parallelism = opts.parallelism - } - if flags.Changed(flagUpdateDelay) { - updateConfig.Delay = opts.delay - } - if flags.Changed(flagUpdateMonitor) { - updateConfig.Monitor = opts.monitor - } - if flags.Changed(flagUpdateFailureAction) { - updateConfig.FailureAction = opts.onFailure - } - if flags.Changed(flagUpdateMaxFailureRatio) { - updateConfig.MaxFailureRatio = opts.maxFailureRatio.Value() - } - if flags.Changed(flagUpdateOrder) { - updateConfig.Order = opts.order - } - - return updateConfig -} - -func (opts updateOptions) rollbackConfig(flags *pflag.FlagSet) *swarm.UpdateConfig { - if !anyChanged(flags, flagRollbackParallelism, flagRollbackDelay, flagRollbackMonitor, flagRollbackFailureAction, flagRollbackMaxFailureRatio) { - return nil - } - - updateConfig := updateConfigFromDefaults(defaults.Service.Rollback) - - if flags.Changed(flagRollbackParallelism) { - updateConfig.Parallelism = opts.parallelism - } - if flags.Changed(flagRollbackDelay) { - updateConfig.Delay = opts.delay - } - if flags.Changed(flagRollbackMonitor) { - updateConfig.Monitor = opts.monitor - } - if flags.Changed(flagRollbackFailureAction) { - updateConfig.FailureAction = opts.onFailure - } - if flags.Changed(flagRollbackMaxFailureRatio) { - updateConfig.MaxFailureRatio = opts.maxFailureRatio.Value() - } - if flags.Changed(flagRollbackOrder) { - updateConfig.Order = opts.order - } - - return updateConfig -} - -type resourceOptions struct { - limitCPU opts.NanoCPUs - limitMemBytes opts.MemBytes - resCPU opts.NanoCPUs - resMemBytes opts.MemBytes -} - -func (r *resourceOptions) ToResourceRequirements() *swarm.ResourceRequirements { - return &swarm.ResourceRequirements{ - Limits: &swarm.Resources{ - NanoCPUs: r.limitCPU.Value(), - MemoryBytes: r.limitMemBytes.Value(), - }, - Reservations: &swarm.Resources{ - NanoCPUs: r.resCPU.Value(), - MemoryBytes: r.resMemBytes.Value(), - }, - } -} - -type restartPolicyOptions struct { - condition string - delay opts.DurationOpt - maxAttempts Uint64Opt - window opts.DurationOpt -} - -func defaultRestartPolicy() *swarm.RestartPolicy { - defaultMaxAttempts := defaults.Service.Task.Restart.MaxAttempts - rp := &swarm.RestartPolicy{ - MaxAttempts: &defaultMaxAttempts, - } - - if defaults.Service.Task.Restart.Delay != nil { - defaultRestartDelay, _ := gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay) - rp.Delay = &defaultRestartDelay - } - if defaults.Service.Task.Restart.Window != nil { - defaultRestartWindow, _ := gogotypes.DurationFromProto(defaults.Service.Task.Restart.Window) - rp.Window = &defaultRestartWindow - } - rp.Condition = defaultRestartCondition() - - return rp -} - -func defaultRestartCondition() swarm.RestartPolicyCondition { - switch defaults.Service.Task.Restart.Condition { - case api.RestartOnNone: - return "none" - case api.RestartOnFailure: - return "on-failure" - case api.RestartOnAny: - return "any" - default: - return "" - } -} - -func defaultOrder(order api.UpdateConfig_UpdateOrder) string { - switch order { - case api.UpdateConfig_STOP_FIRST: - return "stop-first" - case api.UpdateConfig_START_FIRST: - return "start-first" - default: - return "" - } -} - -func (r *restartPolicyOptions) ToRestartPolicy(flags *pflag.FlagSet) *swarm.RestartPolicy { - if !anyChanged(flags, flagRestartDelay, flagRestartMaxAttempts, flagRestartWindow, flagRestartCondition) { - return nil - } - - restartPolicy := defaultRestartPolicy() - - if flags.Changed(flagRestartDelay) { - restartPolicy.Delay = r.delay.Value() - } - if flags.Changed(flagRestartCondition) { - restartPolicy.Condition = swarm.RestartPolicyCondition(r.condition) - } - if flags.Changed(flagRestartMaxAttempts) { - restartPolicy.MaxAttempts = r.maxAttempts.Value() - } - if flags.Changed(flagRestartWindow) { - restartPolicy.Window = r.window.Value() - } - - return restartPolicy -} - -type credentialSpecOpt struct { - value *swarm.CredentialSpec - source string -} - -func (c *credentialSpecOpt) Set(value string) error { - c.source = value - c.value = &swarm.CredentialSpec{} - switch { - case strings.HasPrefix(value, "file://"): - c.value.File = strings.TrimPrefix(value, "file://") - case strings.HasPrefix(value, "registry://"): - c.value.Registry = strings.TrimPrefix(value, "registry://") - default: - return errors.New("Invalid credential spec - value must be prefixed file:// or registry:// followed by a value") - } - - return nil -} - -func (c *credentialSpecOpt) Type() string { - return "credential-spec" -} - -func (c *credentialSpecOpt) String() string { - return c.source -} - -func (c *credentialSpecOpt) Value() *swarm.CredentialSpec { - return c.value -} - -func convertNetworks(ctx context.Context, apiClient client.NetworkAPIClient, networks opts.NetworkOpt) ([]swarm.NetworkAttachmentConfig, error) { - var netAttach []swarm.NetworkAttachmentConfig - for _, net := range networks.Value() { - networkIDOrName := net.Target - _, err := apiClient.NetworkInspect(ctx, networkIDOrName, types.NetworkInspectOptions{Scope: "swarm"}) - if err != nil { - return nil, err - } - netAttach = append(netAttach, swarm.NetworkAttachmentConfig{ // nolint: gosimple - Target: net.Target, - Aliases: net.Aliases, - DriverOpts: net.DriverOpts, - }) - } - sort.Sort(byNetworkTarget(netAttach)) - return netAttach, nil -} - -type endpointOptions struct { - mode string - publishPorts opts.PortOpt -} - -func (e *endpointOptions) ToEndpointSpec() *swarm.EndpointSpec { - return &swarm.EndpointSpec{ - Mode: swarm.ResolutionMode(strings.ToLower(e.mode)), - Ports: e.publishPorts.Value(), - } -} - -type logDriverOptions struct { - name string - opts opts.ListOpts -} - -func newLogDriverOptions() logDriverOptions { - return logDriverOptions{opts: opts.NewListOpts(opts.ValidateEnv)} -} - -func (ldo *logDriverOptions) toLogDriver() *swarm.Driver { - if ldo.name == "" { - return nil - } - - // set the log driver only if specified. - return &swarm.Driver{ - Name: ldo.name, - Options: opts.ConvertKVStringsToMap(ldo.opts.GetAll()), - } -} - -type healthCheckOptions struct { - cmd string - interval opts.PositiveDurationOpt - timeout opts.PositiveDurationOpt - retries int - startPeriod opts.PositiveDurationOpt - noHealthcheck bool -} - -func (opts *healthCheckOptions) toHealthConfig() (*container.HealthConfig, error) { - var healthConfig *container.HealthConfig - haveHealthSettings := opts.cmd != "" || - opts.interval.Value() != nil || - opts.timeout.Value() != nil || - opts.retries != 0 - if opts.noHealthcheck { - if haveHealthSettings { - return nil, errors.Errorf("--%s conflicts with --health-* options", flagNoHealthcheck) - } - healthConfig = &container.HealthConfig{Test: []string{"NONE"}} - } else if haveHealthSettings { - var test []string - if opts.cmd != "" { - test = []string{"CMD-SHELL", opts.cmd} - } - var interval, timeout, startPeriod time.Duration - if ptr := opts.interval.Value(); ptr != nil { - interval = *ptr - } - if ptr := opts.timeout.Value(); ptr != nil { - timeout = *ptr - } - if ptr := opts.startPeriod.Value(); ptr != nil { - startPeriod = *ptr - } - healthConfig = &container.HealthConfig{ - Test: test, - Interval: interval, - Timeout: timeout, - Retries: opts.retries, - StartPeriod: startPeriod, - } - } - return healthConfig, nil -} - -// convertExtraHostsToSwarmHosts converts an array of extra hosts in cli -// : -// into a swarmkit host format: -// IP_address canonical_hostname [aliases...] -// This assumes input value (:) has already been validated -func convertExtraHostsToSwarmHosts(extraHosts []string) []string { - hosts := []string{} - for _, extraHost := range extraHosts { - parts := strings.SplitN(extraHost, ":", 2) - hosts = append(hosts, fmt.Sprintf("%s %s", parts[1], parts[0])) - } - return hosts -} - -type serviceOptions struct { - detach bool - quiet bool - - name string - labels opts.ListOpts - containerLabels opts.ListOpts - image string - entrypoint ShlexOpt - args []string - hostname string - env opts.ListOpts - envFile opts.ListOpts - workdir string - user string - groups opts.ListOpts - credentialSpec credentialSpecOpt - stopSignal string - tty bool - readOnly bool - mounts opts.MountOpt - dns opts.ListOpts - dnsSearch opts.ListOpts - dnsOption opts.ListOpts - hosts opts.ListOpts - - resources resourceOptions - stopGrace opts.DurationOpt - - replicas Uint64Opt - mode string - - restartPolicy restartPolicyOptions - constraints opts.ListOpts - placementPrefs placementPrefOpts - update updateOptions - rollback updateOptions - networks opts.NetworkOpt - endpoint endpointOptions - - registryAuth bool - noResolveImage bool - - logDriver logDriverOptions - - healthcheck healthCheckOptions - secrets opts.SecretOpt - configs opts.ConfigOpt -} - -func newServiceOptions() *serviceOptions { - return &serviceOptions{ - labels: opts.NewListOpts(opts.ValidateEnv), - constraints: opts.NewListOpts(nil), - containerLabels: opts.NewListOpts(opts.ValidateEnv), - env: opts.NewListOpts(opts.ValidateEnv), - envFile: opts.NewListOpts(nil), - groups: opts.NewListOpts(nil), - logDriver: newLogDriverOptions(), - dns: opts.NewListOpts(opts.ValidateIPAddress), - dnsOption: opts.NewListOpts(nil), - dnsSearch: opts.NewListOpts(opts.ValidateDNSSearch), - hosts: opts.NewListOpts(opts.ValidateExtraHost), - } -} - -func (options *serviceOptions) ToServiceMode() (swarm.ServiceMode, error) { - serviceMode := swarm.ServiceMode{} - switch options.mode { - case "global": - if options.replicas.Value() != nil { - return serviceMode, errors.Errorf("replicas can only be used with replicated mode") - } - - serviceMode.Global = &swarm.GlobalService{} - case "replicated": - serviceMode.Replicated = &swarm.ReplicatedService{ - Replicas: options.replicas.Value(), - } - default: - return serviceMode, errors.Errorf("Unknown mode: %s, only replicated and global supported", options.mode) - } - return serviceMode, nil -} - -func (options *serviceOptions) ToStopGracePeriod(flags *pflag.FlagSet) *time.Duration { - if flags.Changed(flagStopGracePeriod) { - return options.stopGrace.Value() - } - return nil -} - -func (options *serviceOptions) ToService(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet) (swarm.ServiceSpec, error) { - var service swarm.ServiceSpec - - envVariables, err := opts.ReadKVStrings(options.envFile.GetAll(), options.env.GetAll()) - if err != nil { - return service, err - } - - currentEnv := make([]string, 0, len(envVariables)) - for _, env := range envVariables { // need to process each var, in order - k := strings.SplitN(env, "=", 2)[0] - for i, current := range currentEnv { // remove duplicates - if current == env { - continue // no update required, may hide this behind flag to preserve order of envVariables - } - if strings.HasPrefix(current, k+"=") { - currentEnv = append(currentEnv[:i], currentEnv[i+1:]...) - } - } - currentEnv = append(currentEnv, env) - } - - healthConfig, err := options.healthcheck.toHealthConfig() - if err != nil { - return service, err - } - - serviceMode, err := options.ToServiceMode() - if err != nil { - return service, err - } - - networks, err := convertNetworks(ctx, apiClient, options.networks) - if err != nil { - return service, err - } - - service = swarm.ServiceSpec{ - Annotations: swarm.Annotations{ - Name: options.name, - Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()), - }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: swarm.ContainerSpec{ - Image: options.image, - Args: options.args, - Command: options.entrypoint.Value(), - Env: currentEnv, - Hostname: options.hostname, - Labels: opts.ConvertKVStringsToMap(options.containerLabels.GetAll()), - Dir: options.workdir, - User: options.user, - Groups: options.groups.GetAll(), - StopSignal: options.stopSignal, - TTY: options.tty, - ReadOnly: options.readOnly, - Mounts: options.mounts.Value(), - DNSConfig: &swarm.DNSConfig{ - Nameservers: options.dns.GetAll(), - Search: options.dnsSearch.GetAll(), - Options: options.dnsOption.GetAll(), - }, - Hosts: convertExtraHostsToSwarmHosts(options.hosts.GetAll()), - StopGracePeriod: options.ToStopGracePeriod(flags), - Healthcheck: healthConfig, - }, - Networks: networks, - Resources: options.resources.ToResourceRequirements(), - RestartPolicy: options.restartPolicy.ToRestartPolicy(flags), - Placement: &swarm.Placement{ - Constraints: options.constraints.GetAll(), - Preferences: options.placementPrefs.prefs, - }, - LogDriver: options.logDriver.toLogDriver(), - }, - Mode: serviceMode, - UpdateConfig: options.update.updateConfig(flags), - RollbackConfig: options.update.rollbackConfig(flags), - EndpointSpec: options.endpoint.ToEndpointSpec(), - } - - if options.credentialSpec.Value() != nil { - service.TaskTemplate.ContainerSpec.Privileges = &swarm.Privileges{ - CredentialSpec: options.credentialSpec.Value(), - } - } - - return service, nil -} - -type flagDefaults map[string]interface{} - -func (fd flagDefaults) getUint64(flagName string) uint64 { - if val, ok := fd[flagName].(uint64); ok { - return val - } - return 0 -} - -func (fd flagDefaults) getString(flagName string) string { - if val, ok := fd[flagName].(string); ok { - return val - } - return "" -} - -func buildServiceDefaultFlagMapping() flagDefaults { - defaultFlagValues := make(map[string]interface{}) - - defaultFlagValues[flagStopGracePeriod], _ = gogotypes.DurationFromProto(defaults.Service.Task.GetContainer().StopGracePeriod) - defaultFlagValues[flagRestartCondition] = `"` + defaultRestartCondition() + `"` - defaultFlagValues[flagRestartDelay], _ = gogotypes.DurationFromProto(defaults.Service.Task.Restart.Delay) - - if defaults.Service.Task.Restart.MaxAttempts != 0 { - defaultFlagValues[flagRestartMaxAttempts] = defaults.Service.Task.Restart.MaxAttempts - } - - defaultRestartWindow, _ := gogotypes.DurationFromProto(defaults.Service.Task.Restart.Window) - if defaultRestartWindow != 0 { - defaultFlagValues[flagRestartWindow] = defaultRestartWindow - } - - defaultFlagValues[flagUpdateParallelism] = defaults.Service.Update.Parallelism - defaultFlagValues[flagUpdateDelay] = defaults.Service.Update.Delay - defaultFlagValues[flagUpdateMonitor], _ = gogotypes.DurationFromProto(defaults.Service.Update.Monitor) - defaultFlagValues[flagUpdateFailureAction] = `"` + strings.ToLower(api.UpdateConfig_FailureAction_name[int32(defaults.Service.Update.FailureAction)]) + `"` - defaultFlagValues[flagUpdateMaxFailureRatio] = defaults.Service.Update.MaxFailureRatio - defaultFlagValues[flagUpdateOrder] = `"` + defaultOrder(defaults.Service.Update.Order) + `"` - - defaultFlagValues[flagRollbackParallelism] = defaults.Service.Rollback.Parallelism - defaultFlagValues[flagRollbackDelay] = defaults.Service.Rollback.Delay - defaultFlagValues[flagRollbackMonitor], _ = gogotypes.DurationFromProto(defaults.Service.Rollback.Monitor) - defaultFlagValues[flagRollbackFailureAction] = `"` + strings.ToLower(api.UpdateConfig_FailureAction_name[int32(defaults.Service.Rollback.FailureAction)]) + `"` - defaultFlagValues[flagRollbackMaxFailureRatio] = defaults.Service.Rollback.MaxFailureRatio - defaultFlagValues[flagRollbackOrder] = `"` + defaultOrder(defaults.Service.Rollback.Order) + `"` - - defaultFlagValues[flagEndpointMode] = "vip" - - return defaultFlagValues -} - -// addServiceFlags adds all flags that are common to both `create` and `update`. -// Any flags that are not common are added separately in the individual command -func addServiceFlags(flags *pflag.FlagSet, opts *serviceOptions, defaultFlagValues flagDefaults) { - flagDesc := func(flagName string, desc string) string { - if defaultValue, ok := defaultFlagValues[flagName]; ok { - return fmt.Sprintf("%s (default %v)", desc, defaultValue) - } - return desc - } - - flags.BoolVarP(&opts.detach, "detach", "d", true, "Exit immediately instead of waiting for the service to converge") - flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress progress output") - - flags.StringVarP(&opts.workdir, flagWorkdir, "w", "", "Working directory inside the container") - flags.StringVarP(&opts.user, flagUser, "u", "", "Username or UID (format: [:])") - flags.Var(&opts.credentialSpec, flagCredentialSpec, "Credential spec for managed service account (Windows only)") - flags.SetAnnotation(flagCredentialSpec, "version", []string{"1.29"}) - flags.StringVar(&opts.hostname, flagHostname, "", "Container hostname") - flags.SetAnnotation(flagHostname, "version", []string{"1.25"}) - flags.Var(&opts.entrypoint, flagEntrypoint, "Overwrite the default ENTRYPOINT of the image") - - flags.Var(&opts.resources.limitCPU, flagLimitCPU, "Limit CPUs") - flags.Var(&opts.resources.limitMemBytes, flagLimitMemory, "Limit Memory") - flags.Var(&opts.resources.resCPU, flagReserveCPU, "Reserve CPUs") - flags.Var(&opts.resources.resMemBytes, flagReserveMemory, "Reserve Memory") - - flags.Var(&opts.stopGrace, flagStopGracePeriod, flagDesc(flagStopGracePeriod, "Time to wait before force killing a container (ns|us|ms|s|m|h)")) - flags.Var(&opts.replicas, flagReplicas, "Number of tasks") - - flags.StringVar(&opts.restartPolicy.condition, flagRestartCondition, "", flagDesc(flagRestartCondition, `Restart when condition is met ("none"|"on-failure"|"any")`)) - flags.Var(&opts.restartPolicy.delay, flagRestartDelay, flagDesc(flagRestartDelay, "Delay between restart attempts (ns|us|ms|s|m|h)")) - flags.Var(&opts.restartPolicy.maxAttempts, flagRestartMaxAttempts, flagDesc(flagRestartMaxAttempts, "Maximum number of restarts before giving up")) - - flags.Var(&opts.restartPolicy.window, flagRestartWindow, flagDesc(flagRestartWindow, "Window used to evaluate the restart policy (ns|us|ms|s|m|h)")) - - flags.Uint64Var(&opts.update.parallelism, flagUpdateParallelism, defaultFlagValues.getUint64(flagUpdateParallelism), "Maximum number of tasks updated simultaneously (0 to update all at once)") - flags.DurationVar(&opts.update.delay, flagUpdateDelay, 0, flagDesc(flagUpdateDelay, "Delay between updates (ns|us|ms|s|m|h)")) - flags.DurationVar(&opts.update.monitor, flagUpdateMonitor, 0, flagDesc(flagUpdateMonitor, "Duration after each task update to monitor for failure (ns|us|ms|s|m|h)")) - flags.SetAnnotation(flagUpdateMonitor, "version", []string{"1.25"}) - flags.StringVar(&opts.update.onFailure, flagUpdateFailureAction, "", flagDesc(flagUpdateFailureAction, `Action on update failure ("pause"|"continue"|"rollback")`)) - flags.Var(&opts.update.maxFailureRatio, flagUpdateMaxFailureRatio, flagDesc(flagUpdateMaxFailureRatio, "Failure rate to tolerate during an update")) - flags.SetAnnotation(flagUpdateMaxFailureRatio, "version", []string{"1.25"}) - flags.StringVar(&opts.update.order, flagUpdateOrder, "", flagDesc(flagUpdateOrder, `Update order ("start-first"|"stop-first")`)) - flags.SetAnnotation(flagUpdateOrder, "version", []string{"1.29"}) - - flags.Uint64Var(&opts.rollback.parallelism, flagRollbackParallelism, defaultFlagValues.getUint64(flagRollbackParallelism), - "Maximum number of tasks rolled back simultaneously (0 to roll back all at once)") - flags.SetAnnotation(flagRollbackParallelism, "version", []string{"1.28"}) - flags.DurationVar(&opts.rollback.delay, flagRollbackDelay, 0, flagDesc(flagRollbackDelay, "Delay between task rollbacks (ns|us|ms|s|m|h)")) - flags.SetAnnotation(flagRollbackDelay, "version", []string{"1.28"}) - flags.DurationVar(&opts.rollback.monitor, flagRollbackMonitor, 0, flagDesc(flagRollbackMonitor, "Duration after each task rollback to monitor for failure (ns|us|ms|s|m|h)")) - flags.SetAnnotation(flagRollbackMonitor, "version", []string{"1.28"}) - flags.StringVar(&opts.rollback.onFailure, flagRollbackFailureAction, "", flagDesc(flagRollbackFailureAction, `Action on rollback failure ("pause"|"continue")`)) - flags.SetAnnotation(flagRollbackFailureAction, "version", []string{"1.28"}) - flags.Var(&opts.rollback.maxFailureRatio, flagRollbackMaxFailureRatio, flagDesc(flagRollbackMaxFailureRatio, "Failure rate to tolerate during a rollback")) - flags.SetAnnotation(flagRollbackMaxFailureRatio, "version", []string{"1.28"}) - flags.StringVar(&opts.rollback.order, flagRollbackOrder, "", flagDesc(flagRollbackOrder, `Rollback order ("start-first"|"stop-first")`)) - flags.SetAnnotation(flagRollbackOrder, "version", []string{"1.29"}) - - flags.StringVar(&opts.endpoint.mode, flagEndpointMode, defaultFlagValues.getString(flagEndpointMode), "Endpoint mode (vip or dnsrr)") - - flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to swarm agents") - flags.BoolVar(&opts.noResolveImage, flagNoResolveImage, false, "Do not query the registry to resolve image digest and supported platforms") - flags.SetAnnotation(flagNoResolveImage, "version", []string{"1.30"}) - - flags.StringVar(&opts.logDriver.name, flagLogDriver, "", "Logging driver for service") - flags.Var(&opts.logDriver.opts, flagLogOpt, "Logging driver options") - - flags.StringVar(&opts.healthcheck.cmd, flagHealthCmd, "", "Command to run to check health") - flags.SetAnnotation(flagHealthCmd, "version", []string{"1.25"}) - flags.Var(&opts.healthcheck.interval, flagHealthInterval, "Time between running the check (ms|s|m|h)") - flags.SetAnnotation(flagHealthInterval, "version", []string{"1.25"}) - flags.Var(&opts.healthcheck.timeout, flagHealthTimeout, "Maximum time to allow one check to run (ms|s|m|h)") - flags.SetAnnotation(flagHealthTimeout, "version", []string{"1.25"}) - flags.IntVar(&opts.healthcheck.retries, flagHealthRetries, 0, "Consecutive failures needed to report unhealthy") - flags.SetAnnotation(flagHealthRetries, "version", []string{"1.25"}) - flags.Var(&opts.healthcheck.startPeriod, flagHealthStartPeriod, "Start period for the container to initialize before counting retries towards unstable (ms|s|m|h)") - flags.SetAnnotation(flagHealthStartPeriod, "version", []string{"1.29"}) - flags.BoolVar(&opts.healthcheck.noHealthcheck, flagNoHealthcheck, false, "Disable any container-specified HEALTHCHECK") - flags.SetAnnotation(flagNoHealthcheck, "version", []string{"1.25"}) - - flags.BoolVarP(&opts.tty, flagTTY, "t", false, "Allocate a pseudo-TTY") - flags.SetAnnotation(flagTTY, "version", []string{"1.25"}) - - flags.BoolVar(&opts.readOnly, flagReadOnly, false, "Mount the container's root filesystem as read only") - flags.SetAnnotation(flagReadOnly, "version", []string{"1.28"}) - - flags.StringVar(&opts.stopSignal, flagStopSignal, "", "Signal to stop the container") - flags.SetAnnotation(flagStopSignal, "version", []string{"1.28"}) -} - -const ( - flagCredentialSpec = "credential-spec" - flagPlacementPref = "placement-pref" - flagPlacementPrefAdd = "placement-pref-add" - flagPlacementPrefRemove = "placement-pref-rm" - flagConstraint = "constraint" - flagConstraintRemove = "constraint-rm" - flagConstraintAdd = "constraint-add" - flagContainerLabel = "container-label" - flagContainerLabelRemove = "container-label-rm" - flagContainerLabelAdd = "container-label-add" - flagDNS = "dns" - flagDNSRemove = "dns-rm" - flagDNSAdd = "dns-add" - flagDNSOption = "dns-option" - flagDNSOptionRemove = "dns-option-rm" - flagDNSOptionAdd = "dns-option-add" - flagDNSSearch = "dns-search" - flagDNSSearchRemove = "dns-search-rm" - flagDNSSearchAdd = "dns-search-add" - flagEndpointMode = "endpoint-mode" - flagEntrypoint = "entrypoint" - flagHost = "host" - flagHostAdd = "host-add" - flagHostRemove = "host-rm" - flagHostname = "hostname" - flagEnv = "env" - flagEnvFile = "env-file" - flagEnvRemove = "env-rm" - flagEnvAdd = "env-add" - flagGroup = "group" - flagGroupAdd = "group-add" - flagGroupRemove = "group-rm" - flagLabel = "label" - flagLabelRemove = "label-rm" - flagLabelAdd = "label-add" - flagLimitCPU = "limit-cpu" - flagLimitMemory = "limit-memory" - flagMode = "mode" - flagMount = "mount" - flagMountRemove = "mount-rm" - flagMountAdd = "mount-add" - flagName = "name" - flagNetwork = "network" - flagNetworkAdd = "network-add" - flagNetworkRemove = "network-rm" - flagPublish = "publish" - flagPublishRemove = "publish-rm" - flagPublishAdd = "publish-add" - flagReadOnly = "read-only" - flagReplicas = "replicas" - flagReserveCPU = "reserve-cpu" - flagReserveMemory = "reserve-memory" - flagRestartCondition = "restart-condition" - flagRestartDelay = "restart-delay" - flagRestartMaxAttempts = "restart-max-attempts" - flagRestartWindow = "restart-window" - flagRollbackDelay = "rollback-delay" - flagRollbackFailureAction = "rollback-failure-action" - flagRollbackMaxFailureRatio = "rollback-max-failure-ratio" - flagRollbackMonitor = "rollback-monitor" - flagRollbackOrder = "rollback-order" - flagRollbackParallelism = "rollback-parallelism" - flagStopGracePeriod = "stop-grace-period" - flagStopSignal = "stop-signal" - flagTTY = "tty" - flagUpdateDelay = "update-delay" - flagUpdateFailureAction = "update-failure-action" - flagUpdateMaxFailureRatio = "update-max-failure-ratio" - flagUpdateMonitor = "update-monitor" - flagUpdateOrder = "update-order" - flagUpdateParallelism = "update-parallelism" - flagUser = "user" - flagWorkdir = "workdir" - flagRegistryAuth = "with-registry-auth" - flagNoResolveImage = "no-resolve-image" - flagLogDriver = "log-driver" - flagLogOpt = "log-opt" - flagHealthCmd = "health-cmd" - flagHealthInterval = "health-interval" - flagHealthRetries = "health-retries" - flagHealthTimeout = "health-timeout" - flagHealthStartPeriod = "health-start-period" - flagNoHealthcheck = "no-healthcheck" - flagSecret = "secret" - flagSecretAdd = "secret-add" - flagSecretRemove = "secret-rm" - flagConfig = "config" - flagConfigAdd = "config-add" - flagConfigRemove = "config-rm" -) diff --git a/vendor/github.com/docker/cli/cli/command/service/parse.go b/vendor/github.com/docker/cli/cli/command/service/parse.go deleted file mode 100644 index 6f69cbb47f..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/parse.go +++ /dev/null @@ -1,117 +0,0 @@ -package service - -import ( - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - swarmtypes "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -// ParseSecrets retrieves the secrets with the requested names and fills -// secret IDs into the secret references. -func ParseSecrets(client client.SecretAPIClient, requestedSecrets []*swarmtypes.SecretReference) ([]*swarmtypes.SecretReference, error) { - if len(requestedSecrets) == 0 { - return []*swarmtypes.SecretReference{}, nil - } - - secretRefs := make(map[string]*swarmtypes.SecretReference) - ctx := context.Background() - - for _, secret := range requestedSecrets { - if _, exists := secretRefs[secret.File.Name]; exists { - return nil, errors.Errorf("duplicate secret target for %s not allowed", secret.SecretName) - } - secretRef := new(swarmtypes.SecretReference) - *secretRef = *secret - secretRefs[secret.File.Name] = secretRef - } - - args := filters.NewArgs() - for _, s := range secretRefs { - args.Add("name", s.SecretName) - } - - secrets, err := client.SecretList(ctx, types.SecretListOptions{ - Filters: args, - }) - if err != nil { - return nil, err - } - - foundSecrets := make(map[string]string) - for _, secret := range secrets { - foundSecrets[secret.Spec.Annotations.Name] = secret.ID - } - - addedSecrets := []*swarmtypes.SecretReference{} - - for _, ref := range secretRefs { - id, ok := foundSecrets[ref.SecretName] - if !ok { - return nil, errors.Errorf("secret not found: %s", ref.SecretName) - } - - // set the id for the ref to properly assign in swarm - // since swarm needs the ID instead of the name - ref.SecretID = id - addedSecrets = append(addedSecrets, ref) - } - - return addedSecrets, nil -} - -// ParseConfigs retrieves the configs from the requested names and converts -// them to config references to use with the spec -func ParseConfigs(client client.ConfigAPIClient, requestedConfigs []*swarmtypes.ConfigReference) ([]*swarmtypes.ConfigReference, error) { - if len(requestedConfigs) == 0 { - return []*swarmtypes.ConfigReference{}, nil - } - - configRefs := make(map[string]*swarmtypes.ConfigReference) - ctx := context.Background() - - for _, config := range requestedConfigs { - if _, exists := configRefs[config.File.Name]; exists { - return nil, errors.Errorf("duplicate config target for %s not allowed", config.ConfigName) - } - - configRef := new(swarmtypes.ConfigReference) - *configRef = *config - configRefs[config.File.Name] = configRef - } - - args := filters.NewArgs() - for _, s := range configRefs { - args.Add("name", s.ConfigName) - } - - configs, err := client.ConfigList(ctx, types.ConfigListOptions{ - Filters: args, - }) - if err != nil { - return nil, err - } - - foundConfigs := make(map[string]string) - for _, config := range configs { - foundConfigs[config.Spec.Annotations.Name] = config.ID - } - - addedConfigs := []*swarmtypes.ConfigReference{} - - for _, ref := range configRefs { - id, ok := foundConfigs[ref.ConfigName] - if !ok { - return nil, errors.Errorf("config not found: %s", ref.ConfigName) - } - - // set the id for the ref to properly assign in swarm - // since swarm needs the ID instead of the name - ref.ConfigID = id - addedConfigs = append(addedConfigs, ref) - } - - return addedConfigs, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/progress/progress.go b/vendor/github.com/docker/cli/cli/command/service/progress/progress.go deleted file mode 100644 index 8e37489bdb..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/progress/progress.go +++ /dev/null @@ -1,411 +0,0 @@ -package progress - -import ( - "errors" - "fmt" - "io" - "os" - "os/signal" - "time" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/streamformatter" - "github.com/docker/docker/pkg/stringid" - "golang.org/x/net/context" -) - -var ( - numberedStates = map[swarm.TaskState]int64{ - swarm.TaskStateNew: 1, - swarm.TaskStateAllocated: 2, - swarm.TaskStatePending: 3, - swarm.TaskStateAssigned: 4, - swarm.TaskStateAccepted: 5, - swarm.TaskStatePreparing: 6, - swarm.TaskStateReady: 7, - swarm.TaskStateStarting: 8, - swarm.TaskStateRunning: 9, - } - - longestState int -) - -const ( - maxProgress = 9 - maxProgressBars = 20 -) - -type progressUpdater interface { - update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]swarm.Node, rollback bool) (bool, error) -} - -func init() { - for state := range numberedStates { - if len(state) > longestState { - longestState = len(state) - } - } -} - -func stateToProgress(state swarm.TaskState, rollback bool) int64 { - if !rollback { - return numberedStates[state] - } - return int64(len(numberedStates)) - numberedStates[state] -} - -// ServiceProgress outputs progress information for convergence of a service. -// nolint: gocyclo -func ServiceProgress(ctx context.Context, client client.APIClient, serviceID string, progressWriter io.WriteCloser) error { - defer progressWriter.Close() - - progressOut := streamformatter.NewJSONProgressOutput(progressWriter, false) - - sigint := make(chan os.Signal, 1) - signal.Notify(sigint, os.Interrupt) - defer signal.Stop(sigint) - - taskFilter := filters.NewArgs() - taskFilter.Add("service", serviceID) - taskFilter.Add("_up-to-date", "true") - - getUpToDateTasks := func() ([]swarm.Task, error) { - return client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter}) - } - - var ( - updater progressUpdater - converged bool - convergedAt time.Time - monitor = 5 * time.Second - rollback bool - ) - - for { - service, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) - if err != nil { - return err - } - - if service.Spec.UpdateConfig != nil && service.Spec.UpdateConfig.Monitor != 0 { - monitor = service.Spec.UpdateConfig.Monitor - } - - if updater == nil { - updater, err = initializeUpdater(service, progressOut) - if err != nil { - return err - } - } - - if service.UpdateStatus != nil { - switch service.UpdateStatus.State { - case swarm.UpdateStateUpdating: - rollback = false - case swarm.UpdateStateCompleted: - if !converged { - return nil - } - case swarm.UpdateStatePaused: - return fmt.Errorf("service update paused: %s", service.UpdateStatus.Message) - case swarm.UpdateStateRollbackStarted: - if !rollback && service.UpdateStatus.Message != "" { - progressOut.WriteProgress(progress.Progress{ - ID: "rollback", - Action: service.UpdateStatus.Message, - }) - } - rollback = true - case swarm.UpdateStateRollbackPaused: - return fmt.Errorf("service rollback paused: %s", service.UpdateStatus.Message) - case swarm.UpdateStateRollbackCompleted: - if !converged { - return fmt.Errorf("service rolled back: %s", service.UpdateStatus.Message) - } - } - } - if converged && time.Since(convergedAt) >= monitor { - return nil - } - - tasks, err := getUpToDateTasks() - if err != nil { - return err - } - - activeNodes, err := getActiveNodes(ctx, client) - if err != nil { - return err - } - - converged, err = updater.update(service, tasks, activeNodes, rollback) - if err != nil { - return err - } - if converged { - if convergedAt.IsZero() { - convergedAt = time.Now() - } - wait := monitor - time.Since(convergedAt) - if wait >= 0 { - progressOut.WriteProgress(progress.Progress{ - // Ideally this would have no ID, but - // the progress rendering code behaves - // poorly on an "action" with no ID. It - // returns the cursor to the beginning - // of the line, so the first character - // may be difficult to read. Then the - // output is overwritten by the shell - // prompt when the command finishes. - ID: "verify", - Action: fmt.Sprintf("Waiting %d seconds to verify that tasks are stable...", wait/time.Second+1), - }) - } - } else { - if !convergedAt.IsZero() { - progressOut.WriteProgress(progress.Progress{ - ID: "verify", - Action: "Detected task failure", - }) - } - convergedAt = time.Time{} - } - - select { - case <-time.After(200 * time.Millisecond): - case <-sigint: - if !converged { - progress.Message(progressOut, "", "Operation continuing in background.") - progress.Messagef(progressOut, "", "Use `docker service ps %s` to check progress.", serviceID) - } - return nil - } - } -} - -func getActiveNodes(ctx context.Context, client client.APIClient) (map[string]swarm.Node, error) { - nodes, err := client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return nil, err - } - - activeNodes := make(map[string]swarm.Node) - for _, n := range nodes { - if n.Status.State != swarm.NodeStateDown { - activeNodes[n.ID] = n - } - } - return activeNodes, nil -} - -func initializeUpdater(service swarm.Service, progressOut progress.Output) (progressUpdater, error) { - if service.Spec.Mode.Replicated != nil && service.Spec.Mode.Replicated.Replicas != nil { - return &replicatedProgressUpdater{ - progressOut: progressOut, - }, nil - } - if service.Spec.Mode.Global != nil { - return &globalProgressUpdater{ - progressOut: progressOut, - }, nil - } - return nil, errors.New("unrecognized service mode") -} - -func writeOverallProgress(progressOut progress.Output, numerator, denominator int, rollback bool) { - if rollback { - progressOut.WriteProgress(progress.Progress{ - ID: "overall progress", - Action: fmt.Sprintf("rolling back update: %d out of %d tasks", numerator, denominator), - }) - return - } - progressOut.WriteProgress(progress.Progress{ - ID: "overall progress", - Action: fmt.Sprintf("%d out of %d tasks", numerator, denominator), - }) -} - -type replicatedProgressUpdater struct { - progressOut progress.Output - - // used for mapping slots to a contiguous space - // this also causes progress bars to appear in order - slotMap map[int]int - - initialized bool - done bool -} - -// nolint: gocyclo -func (u *replicatedProgressUpdater) update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]swarm.Node, rollback bool) (bool, error) { - if service.Spec.Mode.Replicated == nil || service.Spec.Mode.Replicated.Replicas == nil { - return false, errors.New("no replica count") - } - replicas := *service.Spec.Mode.Replicated.Replicas - - if !u.initialized { - u.slotMap = make(map[int]int) - - // Draw progress bars in order - writeOverallProgress(u.progressOut, 0, int(replicas), rollback) - - if replicas <= maxProgressBars { - for i := uint64(1); i <= replicas; i++ { - progress.Update(u.progressOut, fmt.Sprintf("%d/%d", i, replicas), " ") - } - } - u.initialized = true - } - - // If there are multiple tasks with the same slot number, favor the one - // with the *lowest* desired state. This can happen in restart - // scenarios. - tasksBySlot := make(map[int]swarm.Task) - for _, task := range tasks { - if numberedStates[task.DesiredState] == 0 { - continue - } - if existingTask, ok := tasksBySlot[task.Slot]; ok { - if numberedStates[existingTask.DesiredState] <= numberedStates[task.DesiredState] { - continue - } - } - if _, nodeActive := activeNodes[task.NodeID]; nodeActive { - tasksBySlot[task.Slot] = task - } - } - - // If we had reached a converged state, check if we are still converged. - if u.done { - for _, task := range tasksBySlot { - if task.Status.State != swarm.TaskStateRunning { - u.done = false - break - } - } - } - - running := uint64(0) - - for _, task := range tasksBySlot { - mappedSlot := u.slotMap[task.Slot] - if mappedSlot == 0 { - mappedSlot = len(u.slotMap) + 1 - u.slotMap[task.Slot] = mappedSlot - } - - if !u.done && replicas <= maxProgressBars && uint64(mappedSlot) <= replicas { - u.progressOut.WriteProgress(progress.Progress{ - ID: fmt.Sprintf("%d/%d", mappedSlot, replicas), - Action: fmt.Sprintf("%-[1]*s", longestState, task.Status.State), - Current: stateToProgress(task.Status.State, rollback), - Total: maxProgress, - HideCounts: true, - }) - } - if task.Status.State == swarm.TaskStateRunning { - running++ - } - } - - if !u.done { - writeOverallProgress(u.progressOut, int(running), int(replicas), rollback) - - if running == replicas { - u.done = true - } - } - - return running == replicas, nil -} - -type globalProgressUpdater struct { - progressOut progress.Output - - initialized bool - done bool -} - -func (u *globalProgressUpdater) update(service swarm.Service, tasks []swarm.Task, activeNodes map[string]swarm.Node, rollback bool) (bool, error) { - // If there are multiple tasks with the same node ID, favor the one - // with the *lowest* desired state. This can happen in restart - // scenarios. - tasksByNode := make(map[string]swarm.Task) - for _, task := range tasks { - if numberedStates[task.DesiredState] == 0 { - continue - } - if existingTask, ok := tasksByNode[task.NodeID]; ok { - if numberedStates[existingTask.DesiredState] <= numberedStates[task.DesiredState] { - continue - } - } - tasksByNode[task.NodeID] = task - } - - // We don't have perfect knowledge of how many nodes meet the - // constraints for this service. But the orchestrator creates tasks - // for all eligible nodes at the same time, so we should see all those - // nodes represented among the up-to-date tasks. - nodeCount := len(tasksByNode) - - if !u.initialized { - if nodeCount == 0 { - // Two possibilities: either the orchestrator hasn't created - // the tasks yet, or the service doesn't meet constraints for - // any node. Either way, we wait. - u.progressOut.WriteProgress(progress.Progress{ - ID: "overall progress", - Action: "waiting for new tasks", - }) - return false, nil - } - - writeOverallProgress(u.progressOut, 0, nodeCount, rollback) - u.initialized = true - } - - // If we had reached a converged state, check if we are still converged. - if u.done { - for _, task := range tasksByNode { - if task.Status.State != swarm.TaskStateRunning { - u.done = false - break - } - } - } - - running := 0 - - for _, task := range tasksByNode { - if node, nodeActive := activeNodes[task.NodeID]; nodeActive { - if !u.done && nodeCount <= maxProgressBars { - u.progressOut.WriteProgress(progress.Progress{ - ID: stringid.TruncateID(node.ID), - Action: fmt.Sprintf("%-[1]*s", longestState, task.Status.State), - Current: stateToProgress(task.Status.State, rollback), - Total: maxProgress, - HideCounts: true, - }) - } - if task.Status.State == swarm.TaskStateRunning { - running++ - } - } - } - - if !u.done { - writeOverallProgress(u.progressOut, running, nodeCount, rollback) - - if running == nodeCount { - u.done = true - } - } - - return running == nodeCount, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/ps.go b/vendor/github.com/docker/cli/cli/command/service/ps.go deleted file mode 100644 index 741f6b589f..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/ps.go +++ /dev/null @@ -1,150 +0,0 @@ -package service - -import ( - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/cli/command/node" - "github.com/docker/cli/cli/command/task" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type psOptions struct { - services []string - quiet bool - noResolve bool - noTrunc bool - format string - filter opts.FilterOpt -} - -func newPsCommand(dockerCli command.Cli) *cobra.Command { - options := psOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ps [OPTIONS] SERVICE [SERVICE...]", - Short: "List the tasks of one or more services", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.services = args - return runPS(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display task IDs") - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&options.noResolve, "no-resolve", false, "Do not map IDs to Names") - flags.StringVar(&options.format, "format", "", "Pretty-print tasks using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runPS(dockerCli command.Cli, options psOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - filter, notfound, err := createFilter(ctx, client, options) - if err != nil { - return err - } - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) - if err != nil { - return err - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().TasksFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().TasksFormat - } else { - format = formatter.TableFormatKey - } - } - if err := task.Print(ctx, dockerCli, tasks, idresolver.New(client, options.noResolve), !options.noTrunc, options.quiet, format); err != nil { - return err - } - if len(notfound) != 0 { - return errors.New(strings.Join(notfound, "\n")) - } - return nil -} - -func createFilter(ctx context.Context, client client.APIClient, options psOptions) (filters.Args, []string, error) { - filter := options.filter.Value() - - serviceIDFilter := filters.NewArgs() - serviceNameFilter := filters.NewArgs() - for _, service := range options.services { - serviceIDFilter.Add("id", service) - serviceNameFilter.Add("name", service) - } - serviceByIDList, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceIDFilter}) - if err != nil { - return filter, nil, err - } - serviceByNameList, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: serviceNameFilter}) - if err != nil { - return filter, nil, err - } - - var notfound []string - serviceCount := 0 -loop: - // Match services by 1. Full ID, 2. Full name, 3. ID prefix. An error is returned if the ID-prefix match is ambiguous - for _, service := range options.services { - for _, s := range serviceByIDList { - if s.ID == service { - filter.Add("service", s.ID) - serviceCount++ - continue loop - } - } - for _, s := range serviceByNameList { - if s.Spec.Annotations.Name == service { - filter.Add("service", s.ID) - serviceCount++ - continue loop - } - } - found := false - for _, s := range serviceByIDList { - if strings.HasPrefix(s.ID, service) { - if found { - return filter, nil, errors.New("multiple services found with provided prefix: " + service) - } - filter.Add("service", s.ID) - serviceCount++ - found = true - } - } - if !found { - notfound = append(notfound, "no such service: "+service) - } - } - if serviceCount == 0 { - return filter, nil, errors.New(strings.Join(notfound, "\n")) - } - if filter.Include("node") { - nodeFilters := filter.Get("node") - for _, nodeFilter := range nodeFilters { - nodeReference, err := node.Reference(ctx, client, nodeFilter) - if err != nil { - return filter, nil, err - } - filter.Del("node", nodeFilter) - filter.Add("node", nodeReference) - } - } - return filter, notfound, err -} diff --git a/vendor/github.com/docker/cli/cli/command/service/remove.go b/vendor/github.com/docker/cli/cli/command/service/remove.go deleted file mode 100644 index bc6a202f64..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/remove.go +++ /dev/null @@ -1,48 +0,0 @@ -package service - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command { - - cmd := &cobra.Command{ - Use: "rm SERVICE [SERVICE...]", - Aliases: []string{"remove"}, - Short: "Remove one or more services", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(dockerCli, args) - }, - } - cmd.Flags() - - return cmd -} - -func runRemove(dockerCli *command.DockerCli, sids []string) error { - client := dockerCli.Client() - - ctx := context.Background() - - var errs []string - for _, sid := range sids { - err := client.ServiceRemove(ctx, sid) - if err != nil { - errs = append(errs, err.Error()) - continue - } - fmt.Fprintf(dockerCli.Out(), "%s\n", sid) - } - if len(errs) > 0 { - return errors.Errorf(strings.Join(errs, "\n")) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/scale.go b/vendor/github.com/docker/cli/cli/command/service/scale.go deleted file mode 100644 index 397fe1800c..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/scale.go +++ /dev/null @@ -1,97 +0,0 @@ -package service - -import ( - "fmt" - "strconv" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func newScaleCommand(dockerCli *command.DockerCli) *cobra.Command { - return &cobra.Command{ - Use: "scale SERVICE=REPLICAS [SERVICE=REPLICAS...]", - Short: "Scale one or multiple replicated services", - Args: scaleArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runScale(dockerCli, args) - }, - } -} - -func scaleArgs(cmd *cobra.Command, args []string) error { - if err := cli.RequiresMinArgs(1)(cmd, args); err != nil { - return err - } - for _, arg := range args { - if parts := strings.SplitN(arg, "=", 2); len(parts) != 2 { - return errors.Errorf( - "Invalid scale specifier '%s'.\nSee '%s --help'.\n\nUsage: %s\n\n%s", - arg, - cmd.CommandPath(), - cmd.UseLine(), - cmd.Short, - ) - } - } - return nil -} - -func runScale(dockerCli *command.DockerCli, args []string) error { - var errs []string - for _, arg := range args { - parts := strings.SplitN(arg, "=", 2) - serviceID, scaleStr := parts[0], parts[1] - - // validate input arg scale number - scale, err := strconv.ParseUint(scaleStr, 10, 64) - if err != nil { - errs = append(errs, fmt.Sprintf("%s: invalid replicas value %s: %v", serviceID, scaleStr, err)) - continue - } - - if err := runServiceScale(dockerCli, serviceID, scale); err != nil { - errs = append(errs, fmt.Sprintf("%s: %v", serviceID, err)) - } - } - - if len(errs) == 0 { - return nil - } - return errors.Errorf(strings.Join(errs, "\n")) -} - -func runServiceScale(dockerCli *command.DockerCli, serviceID string, scale uint64) error { - client := dockerCli.Client() - ctx := context.Background() - - service, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) - if err != nil { - return err - } - - serviceMode := &service.Spec.Mode - if serviceMode.Replicated == nil { - return errors.Errorf("scale can only be used with replicated mode") - } - - serviceMode.Replicated.Replicas = &scale - - response, err := client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, types.ServiceUpdateOptions{}) - if err != nil { - return err - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - - fmt.Fprintf(dockerCli.Out(), "%s scaled to %d\n", serviceID, scale) - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/service/trust.go b/vendor/github.com/docker/cli/cli/command/service/trust.go deleted file mode 100644 index ec199a770a..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/trust.go +++ /dev/null @@ -1,87 +0,0 @@ -package service - -import ( - "encoding/hex" - - "github.com/Sirupsen/logrus" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/trust" - "github.com/docker/distribution/reference" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/registry" - "github.com/docker/notary/tuf/data" - "github.com/opencontainers/go-digest" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -func resolveServiceImageDigestContentTrust(dockerCli command.Cli, service *swarm.ServiceSpec) error { - if !command.IsTrusted() { - // When not using content trust, digest resolution happens later when - // contacting the registry to retrieve image information. - return nil - } - - ref, err := reference.ParseAnyReference(service.TaskTemplate.ContainerSpec.Image) - if err != nil { - return errors.Wrapf(err, "invalid reference %s", service.TaskTemplate.ContainerSpec.Image) - } - - // If reference does not have digest (is not canonical nor image id) - if _, ok := ref.(reference.Digested); !ok { - namedRef, ok := ref.(reference.Named) - if !ok { - return errors.New("failed to resolve image digest using content trust: reference is not named") - } - namedRef = reference.TagNameOnly(namedRef) - taggedRef, ok := namedRef.(reference.NamedTagged) - if !ok { - return errors.New("failed to resolve image digest using content trust: reference is not tagged") - } - - resolvedImage, err := trustedResolveDigest(context.Background(), dockerCli, taggedRef) - if err != nil { - return errors.Wrap(err, "failed to resolve image digest using content trust") - } - resolvedFamiliar := reference.FamiliarString(resolvedImage) - logrus.Debugf("resolved image tag to %s using content trust", resolvedFamiliar) - service.TaskTemplate.ContainerSpec.Image = resolvedFamiliar - } - - return nil -} - -func trustedResolveDigest(ctx context.Context, cli command.Cli, ref reference.NamedTagged) (reference.Canonical, error) { - repoInfo, err := registry.ParseRepositoryInfo(ref) - if err != nil { - return nil, err - } - - authConfig := command.ResolveAuthConfig(ctx, cli, repoInfo.Index) - - notaryRepo, err := trust.GetNotaryRepository(cli, repoInfo, authConfig, "pull") - if err != nil { - return nil, errors.Wrap(err, "error establishing connection to trust repository") - } - - t, err := notaryRepo.GetTargetByName(ref.Tag(), trust.ReleasesRole, data.CanonicalTargetsRole) - if err != nil { - return nil, trust.NotaryError(repoInfo.Name.Name(), err) - } - // Only get the tag if it's in the top level targets role or the releases delegation role - // ignore it if it's in any other delegation roles - if t.Role != trust.ReleasesRole && t.Role != data.CanonicalTargetsRole { - return nil, trust.NotaryError(repoInfo.Name.Name(), errors.Errorf("No trust data for %s", reference.FamiliarString(ref))) - } - - logrus.Debugf("retrieving target for %s role\n", t.Role) - h, ok := t.Hashes["sha256"] - if !ok { - return nil, errors.New("no valid hash, expecting sha256") - } - - dgst := digest.NewDigestFromHex("sha256", hex.EncodeToString(h)) - - // Allow returning canonical reference with tag - return reference.WithDigest(ref, dgst) -} diff --git a/vendor/github.com/docker/cli/cli/command/service/update.go b/vendor/github.com/docker/cli/cli/command/service/update.go deleted file mode 100644 index a80bf01ef1..0000000000 --- a/vendor/github.com/docker/cli/cli/command/service/update.go +++ /dev/null @@ -1,1047 +0,0 @@ -package service - -import ( - "fmt" - "sort" - "strings" - "time" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - mounttypes "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/client" - "github.com/docker/swarmkit/api/defaults" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "golang.org/x/net/context" -) - -func newUpdateCommand(dockerCli *command.DockerCli) *cobra.Command { - options := newServiceOptions() - - cmd := &cobra.Command{ - Use: "update [OPTIONS] SERVICE", - Short: "Update a service", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - return runUpdate(dockerCli, cmd.Flags(), options, args[0]) - }, - } - - flags := cmd.Flags() - flags.String("image", "", "Service image tag") - flags.Var(&ShlexOpt{}, "args", "Service command args") - flags.Bool("rollback", false, "Rollback to previous specification") - flags.SetAnnotation("rollback", "version", []string{"1.25"}) - flags.Bool("force", false, "Force update even if no changes require it") - flags.SetAnnotation("force", "version", []string{"1.25"}) - addServiceFlags(flags, options, nil) - - flags.Var(newListOptsVar(), flagEnvRemove, "Remove an environment variable") - flags.Var(newListOptsVar(), flagGroupRemove, "Remove a previously added supplementary user group from the container") - flags.SetAnnotation(flagGroupRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagLabelRemove, "Remove a label by its key") - flags.Var(newListOptsVar(), flagContainerLabelRemove, "Remove a container label by its key") - flags.Var(newListOptsVar(), flagMountRemove, "Remove a mount by its target path") - // flags.Var(newListOptsVar().WithValidator(validatePublishRemove), flagPublishRemove, "Remove a published port by its target port") - flags.Var(&opts.PortOpt{}, flagPublishRemove, "Remove a published port by its target port") - flags.Var(newListOptsVar(), flagConstraintRemove, "Remove a constraint") - flags.Var(newListOptsVar(), flagDNSRemove, "Remove a custom DNS server") - flags.SetAnnotation(flagDNSRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagDNSOptionRemove, "Remove a DNS option") - flags.SetAnnotation(flagDNSOptionRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagDNSSearchRemove, "Remove a DNS search domain") - flags.SetAnnotation(flagDNSSearchRemove, "version", []string{"1.25"}) - flags.Var(newListOptsVar(), flagHostRemove, "Remove a custom host-to-IP mapping (host:ip)") - flags.SetAnnotation(flagHostRemove, "version", []string{"1.25"}) - flags.Var(&options.labels, flagLabelAdd, "Add or update a service label") - flags.Var(&options.containerLabels, flagContainerLabelAdd, "Add or update a container label") - flags.Var(&options.env, flagEnvAdd, "Add or update an environment variable") - flags.Var(newListOptsVar(), flagSecretRemove, "Remove a secret") - flags.SetAnnotation(flagSecretRemove, "version", []string{"1.25"}) - flags.Var(&options.secrets, flagSecretAdd, "Add or update a secret on a service") - flags.SetAnnotation(flagSecretAdd, "version", []string{"1.25"}) - - flags.Var(newListOptsVar(), flagConfigRemove, "Remove a configuration file") - flags.SetAnnotation(flagConfigRemove, "version", []string{"1.30"}) - flags.Var(&options.configs, flagConfigAdd, "Add or update a config file on a service") - flags.SetAnnotation(flagConfigAdd, "version", []string{"1.30"}) - - flags.Var(&options.mounts, flagMountAdd, "Add or update a mount on a service") - flags.Var(&options.constraints, flagConstraintAdd, "Add or update a placement constraint") - flags.Var(&options.placementPrefs, flagPlacementPrefAdd, "Add a placement preference") - flags.SetAnnotation(flagPlacementPrefAdd, "version", []string{"1.28"}) - flags.Var(&placementPrefOpts{}, flagPlacementPrefRemove, "Remove a placement preference") - flags.SetAnnotation(flagPlacementPrefRemove, "version", []string{"1.28"}) - flags.Var(&options.networks, flagNetworkAdd, "Add a network") - flags.SetAnnotation(flagNetworkAdd, "version", []string{"1.29"}) - flags.Var(newListOptsVar(), flagNetworkRemove, "Remove a network") - flags.SetAnnotation(flagNetworkRemove, "version", []string{"1.29"}) - flags.Var(&options.endpoint.publishPorts, flagPublishAdd, "Add or update a published port") - flags.Var(&options.groups, flagGroupAdd, "Add an additional supplementary user group to the container") - flags.SetAnnotation(flagGroupAdd, "version", []string{"1.25"}) - flags.Var(&options.dns, flagDNSAdd, "Add or update a custom DNS server") - flags.SetAnnotation(flagDNSAdd, "version", []string{"1.25"}) - flags.Var(&options.dnsOption, flagDNSOptionAdd, "Add or update a DNS option") - flags.SetAnnotation(flagDNSOptionAdd, "version", []string{"1.25"}) - flags.Var(&options.dnsSearch, flagDNSSearchAdd, "Add or update a custom DNS search domain") - flags.SetAnnotation(flagDNSSearchAdd, "version", []string{"1.25"}) - flags.Var(&options.hosts, flagHostAdd, "Add or update a custom host-to-IP mapping (host:ip)") - flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"}) - - return cmd -} - -func newListOptsVar() *opts.ListOpts { - return opts.NewListOptsRef(&[]string{}, nil) -} - -// nolint: gocyclo -func runUpdate(dockerCli *command.DockerCli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error { - apiClient := dockerCli.Client() - ctx := context.Background() - - service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{}) - if err != nil { - return err - } - - rollback, err := flags.GetBool("rollback") - if err != nil { - return err - } - - // There are two ways to do user-requested rollback. The old way is - // client-side, but with a sufficiently recent daemon we prefer - // server-side, because it will honor the rollback parameters. - var ( - clientSideRollback bool - serverSideRollback bool - ) - - spec := &service.Spec - if rollback { - // Rollback can't be combined with other flags. - otherFlagsPassed := false - flags.VisitAll(func(f *pflag.Flag) { - if f.Name == "rollback" || f.Name == "detach" || f.Name == "quiet" { - return - } - if flags.Changed(f.Name) { - otherFlagsPassed = true - } - }) - if otherFlagsPassed { - return errors.New("other flags may not be combined with --rollback") - } - - if versions.LessThan(dockerCli.Client().ClientVersion(), "1.28") { - clientSideRollback = true - spec = service.PreviousSpec - if spec == nil { - return errors.Errorf("service does not have a previous specification to roll back to") - } - } else { - serverSideRollback = true - } - } - - updateOpts := types.ServiceUpdateOptions{} - if serverSideRollback { - updateOpts.Rollback = "previous" - } - - err = updateService(ctx, apiClient, flags, spec) - if err != nil { - return err - } - - if flags.Changed("image") { - if err := resolveServiceImageDigestContentTrust(dockerCli, spec); err != nil { - return err - } - if !options.noResolveImage && versions.GreaterThanOrEqualTo(apiClient.ClientVersion(), "1.30") { - updateOpts.QueryRegistry = true - } - } - - updatedSecrets, err := getUpdatedSecrets(apiClient, flags, spec.TaskTemplate.ContainerSpec.Secrets) - if err != nil { - return err - } - - spec.TaskTemplate.ContainerSpec.Secrets = updatedSecrets - - updatedConfigs, err := getUpdatedConfigs(apiClient, flags, spec.TaskTemplate.ContainerSpec.Configs) - if err != nil { - return err - } - - spec.TaskTemplate.ContainerSpec.Configs = updatedConfigs - - // only send auth if flag was set - sendAuth, err := flags.GetBool(flagRegistryAuth) - if err != nil { - return err - } - if sendAuth { - // Retrieve encoded auth token from the image reference - // This would be the old image if it didn't change in this update - image := spec.TaskTemplate.ContainerSpec.Image - encodedAuth, err := command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) - if err != nil { - return err - } - updateOpts.EncodedRegistryAuth = encodedAuth - } else if clientSideRollback { - updateOpts.RegistryAuthFrom = types.RegistryAuthFromPreviousSpec - } else { - updateOpts.RegistryAuthFrom = types.RegistryAuthFromSpec - } - - response, err := apiClient.ServiceUpdate(ctx, service.ID, service.Version, *spec, updateOpts) - if err != nil { - return err - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - - fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID) - - if options.detach { - if !flags.Changed("detach") { - fmt.Fprintln(dockerCli.Err(), "Since --detach=false was not specified, tasks will be updated in the background.\n"+ - "In a future release, --detach=false will become the default.") - } - return nil - } - - return waitOnService(ctx, dockerCli, serviceID, options) -} - -// nolint: gocyclo -func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { - updateString := func(flag string, field *string) { - if flags.Changed(flag) { - *field, _ = flags.GetString(flag) - } - } - - updateInt64Value := func(flag string, field *int64) { - if flags.Changed(flag) { - *field = flags.Lookup(flag).Value.(int64Value).Value() - } - } - - updateFloatValue := func(flag string, field *float32) { - if flags.Changed(flag) { - *field = flags.Lookup(flag).Value.(*floatValue).Value() - } - } - - updateDuration := func(flag string, field *time.Duration) { - if flags.Changed(flag) { - *field, _ = flags.GetDuration(flag) - } - } - - updateDurationOpt := func(flag string, field **time.Duration) { - if flags.Changed(flag) { - val := *flags.Lookup(flag).Value.(*opts.DurationOpt).Value() - *field = &val - } - } - - updateUint64 := func(flag string, field *uint64) { - if flags.Changed(flag) { - *field, _ = flags.GetUint64(flag) - } - } - - updateUint64Opt := func(flag string, field **uint64) { - if flags.Changed(flag) { - val := *flags.Lookup(flag).Value.(*Uint64Opt).Value() - *field = &val - } - } - - cspec := &spec.TaskTemplate.ContainerSpec - task := &spec.TaskTemplate - - taskResources := func() *swarm.ResourceRequirements { - if task.Resources == nil { - task.Resources = &swarm.ResourceRequirements{} - } - return task.Resources - } - - updateLabels(flags, &spec.Labels) - updateContainerLabels(flags, &cspec.Labels) - updateString("image", &cspec.Image) - updateStringToSlice(flags, "args", &cspec.Args) - updateStringToSlice(flags, flagEntrypoint, &cspec.Command) - updateEnvironment(flags, &cspec.Env) - updateString(flagWorkdir, &cspec.Dir) - updateString(flagUser, &cspec.User) - updateString(flagHostname, &cspec.Hostname) - if err := updateMounts(flags, &cspec.Mounts); err != nil { - return err - } - - if flags.Changed(flagLimitCPU) || flags.Changed(flagLimitMemory) { - taskResources().Limits = &swarm.Resources{} - updateInt64Value(flagLimitCPU, &task.Resources.Limits.NanoCPUs) - updateInt64Value(flagLimitMemory, &task.Resources.Limits.MemoryBytes) - } - if flags.Changed(flagReserveCPU) || flags.Changed(flagReserveMemory) { - taskResources().Reservations = &swarm.Resources{} - updateInt64Value(flagReserveCPU, &task.Resources.Reservations.NanoCPUs) - updateInt64Value(flagReserveMemory, &task.Resources.Reservations.MemoryBytes) - } - - updateDurationOpt(flagStopGracePeriod, &cspec.StopGracePeriod) - - if anyChanged(flags, flagRestartCondition, flagRestartDelay, flagRestartMaxAttempts, flagRestartWindow) { - if task.RestartPolicy == nil { - task.RestartPolicy = defaultRestartPolicy() - } - if flags.Changed(flagRestartCondition) { - value, _ := flags.GetString(flagRestartCondition) - task.RestartPolicy.Condition = swarm.RestartPolicyCondition(value) - } - updateDurationOpt(flagRestartDelay, &task.RestartPolicy.Delay) - updateUint64Opt(flagRestartMaxAttempts, &task.RestartPolicy.MaxAttempts) - updateDurationOpt(flagRestartWindow, &task.RestartPolicy.Window) - } - - if anyChanged(flags, flagConstraintAdd, flagConstraintRemove) { - if task.Placement == nil { - task.Placement = &swarm.Placement{} - } - updatePlacementConstraints(flags, task.Placement) - } - - if anyChanged(flags, flagPlacementPrefAdd, flagPlacementPrefRemove) { - if task.Placement == nil { - task.Placement = &swarm.Placement{} - } - updatePlacementPreferences(flags, task.Placement) - } - - if anyChanged(flags, flagNetworkAdd, flagNetworkRemove) { - if err := updateNetworks(ctx, apiClient, flags, spec); err != nil { - return err - } - } - - if err := updateReplicas(flags, &spec.Mode); err != nil { - return err - } - - if anyChanged(flags, flagUpdateParallelism, flagUpdateDelay, flagUpdateMonitor, flagUpdateFailureAction, flagUpdateMaxFailureRatio, flagUpdateOrder) { - if spec.UpdateConfig == nil { - spec.UpdateConfig = updateConfigFromDefaults(defaults.Service.Update) - } - updateUint64(flagUpdateParallelism, &spec.UpdateConfig.Parallelism) - updateDuration(flagUpdateDelay, &spec.UpdateConfig.Delay) - updateDuration(flagUpdateMonitor, &spec.UpdateConfig.Monitor) - updateString(flagUpdateFailureAction, &spec.UpdateConfig.FailureAction) - updateFloatValue(flagUpdateMaxFailureRatio, &spec.UpdateConfig.MaxFailureRatio) - updateString(flagUpdateOrder, &spec.UpdateConfig.Order) - } - - if anyChanged(flags, flagRollbackParallelism, flagRollbackDelay, flagRollbackMonitor, flagRollbackFailureAction, flagRollbackMaxFailureRatio, flagRollbackOrder) { - if spec.RollbackConfig == nil { - spec.RollbackConfig = updateConfigFromDefaults(defaults.Service.Rollback) - } - updateUint64(flagRollbackParallelism, &spec.RollbackConfig.Parallelism) - updateDuration(flagRollbackDelay, &spec.RollbackConfig.Delay) - updateDuration(flagRollbackMonitor, &spec.RollbackConfig.Monitor) - updateString(flagRollbackFailureAction, &spec.RollbackConfig.FailureAction) - updateFloatValue(flagRollbackMaxFailureRatio, &spec.RollbackConfig.MaxFailureRatio) - updateString(flagRollbackOrder, &spec.RollbackConfig.Order) - } - - if flags.Changed(flagEndpointMode) { - value, _ := flags.GetString(flagEndpointMode) - if spec.EndpointSpec == nil { - spec.EndpointSpec = &swarm.EndpointSpec{} - } - spec.EndpointSpec.Mode = swarm.ResolutionMode(value) - } - - if anyChanged(flags, flagGroupAdd, flagGroupRemove) { - if err := updateGroups(flags, &cspec.Groups); err != nil { - return err - } - } - - if anyChanged(flags, flagPublishAdd, flagPublishRemove) { - if spec.EndpointSpec == nil { - spec.EndpointSpec = &swarm.EndpointSpec{} - } - if err := updatePorts(flags, &spec.EndpointSpec.Ports); err != nil { - return err - } - } - - if anyChanged(flags, flagDNSAdd, flagDNSRemove, flagDNSOptionAdd, flagDNSOptionRemove, flagDNSSearchAdd, flagDNSSearchRemove) { - if cspec.DNSConfig == nil { - cspec.DNSConfig = &swarm.DNSConfig{} - } - if err := updateDNSConfig(flags, &cspec.DNSConfig); err != nil { - return err - } - } - - if anyChanged(flags, flagHostAdd, flagHostRemove) { - if err := updateHosts(flags, &cspec.Hosts); err != nil { - return err - } - } - - if err := updateLogDriver(flags, &spec.TaskTemplate); err != nil { - return err - } - - force, err := flags.GetBool("force") - if err != nil { - return err - } - - if force { - spec.TaskTemplate.ForceUpdate++ - } - - if err := updateHealthcheck(flags, cspec); err != nil { - return err - } - - if flags.Changed(flagTTY) { - tty, err := flags.GetBool(flagTTY) - if err != nil { - return err - } - cspec.TTY = tty - } - - if flags.Changed(flagReadOnly) { - readOnly, err := flags.GetBool(flagReadOnly) - if err != nil { - return err - } - cspec.ReadOnly = readOnly - } - - updateString(flagStopSignal, &cspec.StopSignal) - - return nil -} - -func updateStringToSlice(flags *pflag.FlagSet, flag string, field *[]string) { - if !flags.Changed(flag) { - return - } - - *field = flags.Lookup(flag).Value.(*ShlexOpt).Value() -} - -func anyChanged(flags *pflag.FlagSet, fields ...string) bool { - for _, flag := range fields { - if flags.Changed(flag) { - return true - } - } - return false -} - -func updatePlacementConstraints(flags *pflag.FlagSet, placement *swarm.Placement) { - if flags.Changed(flagConstraintAdd) { - values := flags.Lookup(flagConstraintAdd).Value.(*opts.ListOpts).GetAll() - placement.Constraints = append(placement.Constraints, values...) - } - toRemove := buildToRemoveSet(flags, flagConstraintRemove) - - newConstraints := []string{} - for _, constraint := range placement.Constraints { - if _, exists := toRemove[constraint]; !exists { - newConstraints = append(newConstraints, constraint) - } - } - // Sort so that result is predictable. - sort.Strings(newConstraints) - - placement.Constraints = newConstraints -} - -func updatePlacementPreferences(flags *pflag.FlagSet, placement *swarm.Placement) { - var newPrefs []swarm.PlacementPreference - - if flags.Changed(flagPlacementPrefRemove) { - for _, existing := range placement.Preferences { - removed := false - for _, removal := range flags.Lookup(flagPlacementPrefRemove).Value.(*placementPrefOpts).prefs { - if removal.Spread != nil && existing.Spread != nil && removal.Spread.SpreadDescriptor == existing.Spread.SpreadDescriptor { - removed = true - break - } - } - if !removed { - newPrefs = append(newPrefs, existing) - } - } - } else { - newPrefs = placement.Preferences - } - - if flags.Changed(flagPlacementPrefAdd) { - newPrefs = append(newPrefs, - flags.Lookup(flagPlacementPrefAdd).Value.(*placementPrefOpts).prefs...) - } - - placement.Preferences = newPrefs -} - -func updateContainerLabels(flags *pflag.FlagSet, field *map[string]string) { - if flags.Changed(flagContainerLabelAdd) { - if *field == nil { - *field = map[string]string{} - } - - values := flags.Lookup(flagContainerLabelAdd).Value.(*opts.ListOpts).GetAll() - for key, value := range opts.ConvertKVStringsToMap(values) { - (*field)[key] = value - } - } - - if *field != nil && flags.Changed(flagContainerLabelRemove) { - toRemove := flags.Lookup(flagContainerLabelRemove).Value.(*opts.ListOpts).GetAll() - for _, label := range toRemove { - delete(*field, label) - } - } -} - -func updateLabels(flags *pflag.FlagSet, field *map[string]string) { - if flags.Changed(flagLabelAdd) { - if *field == nil { - *field = map[string]string{} - } - - values := flags.Lookup(flagLabelAdd).Value.(*opts.ListOpts).GetAll() - for key, value := range opts.ConvertKVStringsToMap(values) { - (*field)[key] = value - } - } - - if *field != nil && flags.Changed(flagLabelRemove) { - toRemove := flags.Lookup(flagLabelRemove).Value.(*opts.ListOpts).GetAll() - for _, label := range toRemove { - delete(*field, label) - } - } -} - -func updateEnvironment(flags *pflag.FlagSet, field *[]string) { - if flags.Changed(flagEnvAdd) { - envSet := map[string]string{} - for _, v := range *field { - envSet[envKey(v)] = v - } - - value := flags.Lookup(flagEnvAdd).Value.(*opts.ListOpts) - for _, v := range value.GetAll() { - envSet[envKey(v)] = v - } - - *field = []string{} - for _, v := range envSet { - *field = append(*field, v) - } - } - - toRemove := buildToRemoveSet(flags, flagEnvRemove) - *field = removeItems(*field, toRemove, envKey) -} - -func getUpdatedSecrets(apiClient client.SecretAPIClient, flags *pflag.FlagSet, secrets []*swarm.SecretReference) ([]*swarm.SecretReference, error) { - newSecrets := []*swarm.SecretReference{} - - toRemove := buildToRemoveSet(flags, flagSecretRemove) - for _, secret := range secrets { - if _, exists := toRemove[secret.SecretName]; !exists { - newSecrets = append(newSecrets, secret) - } - } - - if flags.Changed(flagSecretAdd) { - values := flags.Lookup(flagSecretAdd).Value.(*opts.SecretOpt).Value() - - addSecrets, err := ParseSecrets(apiClient, values) - if err != nil { - return nil, err - } - newSecrets = append(newSecrets, addSecrets...) - } - - return newSecrets, nil -} - -func getUpdatedConfigs(apiClient client.ConfigAPIClient, flags *pflag.FlagSet, configs []*swarm.ConfigReference) ([]*swarm.ConfigReference, error) { - newConfigs := []*swarm.ConfigReference{} - - toRemove := buildToRemoveSet(flags, flagConfigRemove) - for _, config := range configs { - if _, exists := toRemove[config.ConfigName]; !exists { - newConfigs = append(newConfigs, config) - } - } - - if flags.Changed(flagConfigAdd) { - values := flags.Lookup(flagConfigAdd).Value.(*opts.ConfigOpt).Value() - - addConfigs, err := ParseConfigs(apiClient, values) - if err != nil { - return nil, err - } - newConfigs = append(newConfigs, addConfigs...) - } - - return newConfigs, nil -} - -func envKey(value string) string { - kv := strings.SplitN(value, "=", 2) - return kv[0] -} - -func buildToRemoveSet(flags *pflag.FlagSet, flag string) map[string]struct{} { - var empty struct{} - toRemove := make(map[string]struct{}) - - if !flags.Changed(flag) { - return toRemove - } - - toRemoveSlice := flags.Lookup(flag).Value.(*opts.ListOpts).GetAll() - for _, key := range toRemoveSlice { - toRemove[key] = empty - } - return toRemove -} - -func removeItems( - seq []string, - toRemove map[string]struct{}, - keyFunc func(string) string, -) []string { - newSeq := []string{} - for _, item := range seq { - if _, exists := toRemove[keyFunc(item)]; !exists { - newSeq = append(newSeq, item) - } - } - return newSeq -} - -type byMountSource []mounttypes.Mount - -func (m byMountSource) Len() int { return len(m) } -func (m byMountSource) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m byMountSource) Less(i, j int) bool { - a, b := m[i], m[j] - - if a.Source == b.Source { - return a.Target < b.Target - } - - return a.Source < b.Source -} - -func updateMounts(flags *pflag.FlagSet, mounts *[]mounttypes.Mount) error { - mountsByTarget := map[string]mounttypes.Mount{} - - if flags.Changed(flagMountAdd) { - values := flags.Lookup(flagMountAdd).Value.(*opts.MountOpt).Value() - for _, mount := range values { - if _, ok := mountsByTarget[mount.Target]; ok { - return errors.Errorf("duplicate mount target") - } - mountsByTarget[mount.Target] = mount - } - } - - // Add old list of mount points minus updated one. - for _, mount := range *mounts { - if _, ok := mountsByTarget[mount.Target]; !ok { - mountsByTarget[mount.Target] = mount - } - } - - newMounts := []mounttypes.Mount{} - - toRemove := buildToRemoveSet(flags, flagMountRemove) - - for _, mount := range mountsByTarget { - if _, exists := toRemove[mount.Target]; !exists { - newMounts = append(newMounts, mount) - } - } - sort.Sort(byMountSource(newMounts)) - *mounts = newMounts - return nil -} - -func updateGroups(flags *pflag.FlagSet, groups *[]string) error { - if flags.Changed(flagGroupAdd) { - values := flags.Lookup(flagGroupAdd).Value.(*opts.ListOpts).GetAll() - *groups = append(*groups, values...) - } - toRemove := buildToRemoveSet(flags, flagGroupRemove) - - newGroups := []string{} - for _, group := range *groups { - if _, exists := toRemove[group]; !exists { - newGroups = append(newGroups, group) - } - } - // Sort so that result is predictable. - sort.Strings(newGroups) - - *groups = newGroups - return nil -} - -func removeDuplicates(entries []string) []string { - hit := map[string]bool{} - newEntries := []string{} - for _, v := range entries { - if !hit[v] { - newEntries = append(newEntries, v) - hit[v] = true - } - } - return newEntries -} - -func updateDNSConfig(flags *pflag.FlagSet, config **swarm.DNSConfig) error { - newConfig := &swarm.DNSConfig{} - - nameservers := (*config).Nameservers - if flags.Changed(flagDNSAdd) { - values := flags.Lookup(flagDNSAdd).Value.(*opts.ListOpts).GetAll() - nameservers = append(nameservers, values...) - } - nameservers = removeDuplicates(nameservers) - toRemove := buildToRemoveSet(flags, flagDNSRemove) - for _, nameserver := range nameservers { - if _, exists := toRemove[nameserver]; !exists { - newConfig.Nameservers = append(newConfig.Nameservers, nameserver) - - } - } - // Sort so that result is predictable. - sort.Strings(newConfig.Nameservers) - - search := (*config).Search - if flags.Changed(flagDNSSearchAdd) { - values := flags.Lookup(flagDNSSearchAdd).Value.(*opts.ListOpts).GetAll() - search = append(search, values...) - } - search = removeDuplicates(search) - toRemove = buildToRemoveSet(flags, flagDNSSearchRemove) - for _, entry := range search { - if _, exists := toRemove[entry]; !exists { - newConfig.Search = append(newConfig.Search, entry) - } - } - // Sort so that result is predictable. - sort.Strings(newConfig.Search) - - options := (*config).Options - if flags.Changed(flagDNSOptionAdd) { - values := flags.Lookup(flagDNSOptionAdd).Value.(*opts.ListOpts).GetAll() - options = append(options, values...) - } - options = removeDuplicates(options) - toRemove = buildToRemoveSet(flags, flagDNSOptionRemove) - for _, option := range options { - if _, exists := toRemove[option]; !exists { - newConfig.Options = append(newConfig.Options, option) - } - } - // Sort so that result is predictable. - sort.Strings(newConfig.Options) - - *config = newConfig - return nil -} - -type byPortConfig []swarm.PortConfig - -func (r byPortConfig) Len() int { return len(r) } -func (r byPortConfig) Swap(i, j int) { r[i], r[j] = r[j], r[i] } -func (r byPortConfig) Less(i, j int) bool { - // We convert PortConfig into `port/protocol`, e.g., `80/tcp` - // In updatePorts we already filter out with map so there is duplicate entries - return portConfigToString(&r[i]) < portConfigToString(&r[j]) -} - -func portConfigToString(portConfig *swarm.PortConfig) string { - protocol := portConfig.Protocol - mode := portConfig.PublishMode - return fmt.Sprintf("%v:%v/%s/%s", portConfig.PublishedPort, portConfig.TargetPort, protocol, mode) -} - -func updatePorts(flags *pflag.FlagSet, portConfig *[]swarm.PortConfig) error { - // The key of the map is `port/protocol`, e.g., `80/tcp` - portSet := map[string]swarm.PortConfig{} - - // Build the current list of portConfig - for _, entry := range *portConfig { - if _, ok := portSet[portConfigToString(&entry)]; !ok { - portSet[portConfigToString(&entry)] = entry - } - } - - newPorts := []swarm.PortConfig{} - - // Clean current ports - toRemove := flags.Lookup(flagPublishRemove).Value.(*opts.PortOpt).Value() -portLoop: - for _, port := range portSet { - for _, pConfig := range toRemove { - if equalProtocol(port.Protocol, pConfig.Protocol) && - port.TargetPort == pConfig.TargetPort && - equalPublishMode(port.PublishMode, pConfig.PublishMode) { - continue portLoop - } - } - - newPorts = append(newPorts, port) - } - - // Check to see if there are any conflict in flags. - if flags.Changed(flagPublishAdd) { - ports := flags.Lookup(flagPublishAdd).Value.(*opts.PortOpt).Value() - - for _, port := range ports { - if _, ok := portSet[portConfigToString(&port)]; ok { - continue - } - //portSet[portConfigToString(&port)] = port - newPorts = append(newPorts, port) - } - } - - // Sort the PortConfig to avoid unnecessary updates - sort.Sort(byPortConfig(newPorts)) - *portConfig = newPorts - return nil -} - -func equalProtocol(prot1, prot2 swarm.PortConfigProtocol) bool { - return prot1 == prot2 || - (prot1 == swarm.PortConfigProtocol("") && prot2 == swarm.PortConfigProtocolTCP) || - (prot2 == swarm.PortConfigProtocol("") && prot1 == swarm.PortConfigProtocolTCP) -} - -func equalPublishMode(mode1, mode2 swarm.PortConfigPublishMode) bool { - return mode1 == mode2 || - (mode1 == swarm.PortConfigPublishMode("") && mode2 == swarm.PortConfigPublishModeIngress) || - (mode2 == swarm.PortConfigPublishMode("") && mode1 == swarm.PortConfigPublishModeIngress) -} - -func updateReplicas(flags *pflag.FlagSet, serviceMode *swarm.ServiceMode) error { - if !flags.Changed(flagReplicas) { - return nil - } - - if serviceMode == nil || serviceMode.Replicated == nil { - return errors.Errorf("replicas can only be used with replicated mode") - } - serviceMode.Replicated.Replicas = flags.Lookup(flagReplicas).Value.(*Uint64Opt).Value() - return nil -} - -func updateHosts(flags *pflag.FlagSet, hosts *[]string) error { - // Combine existing Hosts (in swarmkit format) with the host to add (convert to swarmkit format) - if flags.Changed(flagHostAdd) { - values := convertExtraHostsToSwarmHosts(flags.Lookup(flagHostAdd).Value.(*opts.ListOpts).GetAll()) - *hosts = append(*hosts, values...) - } - // Remove duplicate - *hosts = removeDuplicates(*hosts) - - keysToRemove := make(map[string]struct{}) - if flags.Changed(flagHostRemove) { - var empty struct{} - extraHostsToRemove := flags.Lookup(flagHostRemove).Value.(*opts.ListOpts).GetAll() - for _, entry := range extraHostsToRemove { - key := strings.SplitN(entry, ":", 2)[0] - keysToRemove[key] = empty - } - } - - newHosts := []string{} - for _, entry := range *hosts { - // Since this is in swarmkit format, we need to find the key, which is canonical_hostname of: - // IP_address canonical_hostname [aliases...] - parts := strings.Fields(entry) - if len(parts) > 1 { - key := parts[1] - if _, exists := keysToRemove[key]; !exists { - newHosts = append(newHosts, entry) - } - } else { - newHosts = append(newHosts, entry) - } - } - - // Sort so that result is predictable. - sort.Strings(newHosts) - - *hosts = newHosts - return nil -} - -// updateLogDriver updates the log driver only if the log driver flag is set. -// All options will be replaced with those provided on the command line. -func updateLogDriver(flags *pflag.FlagSet, taskTemplate *swarm.TaskSpec) error { - if !flags.Changed(flagLogDriver) { - return nil - } - - name, err := flags.GetString(flagLogDriver) - if err != nil { - return err - } - - if name == "" { - return nil - } - - taskTemplate.LogDriver = &swarm.Driver{ - Name: name, - Options: opts.ConvertKVStringsToMap(flags.Lookup(flagLogOpt).Value.(*opts.ListOpts).GetAll()), - } - - return nil -} - -func updateHealthcheck(flags *pflag.FlagSet, containerSpec *swarm.ContainerSpec) error { - if !anyChanged(flags, flagNoHealthcheck, flagHealthCmd, flagHealthInterval, flagHealthRetries, flagHealthTimeout, flagHealthStartPeriod) { - return nil - } - if containerSpec.Healthcheck == nil { - containerSpec.Healthcheck = &container.HealthConfig{} - } - noHealthcheck, err := flags.GetBool(flagNoHealthcheck) - if err != nil { - return err - } - if noHealthcheck { - if !anyChanged(flags, flagHealthCmd, flagHealthInterval, flagHealthRetries, flagHealthTimeout, flagHealthStartPeriod) { - containerSpec.Healthcheck = &container.HealthConfig{ - Test: []string{"NONE"}, - } - return nil - } - return errors.Errorf("--%s conflicts with --health-* options", flagNoHealthcheck) - } - if len(containerSpec.Healthcheck.Test) > 0 && containerSpec.Healthcheck.Test[0] == "NONE" { - containerSpec.Healthcheck.Test = nil - } - if flags.Changed(flagHealthInterval) { - val := *flags.Lookup(flagHealthInterval).Value.(*opts.PositiveDurationOpt).Value() - containerSpec.Healthcheck.Interval = val - } - if flags.Changed(flagHealthTimeout) { - val := *flags.Lookup(flagHealthTimeout).Value.(*opts.PositiveDurationOpt).Value() - containerSpec.Healthcheck.Timeout = val - } - if flags.Changed(flagHealthStartPeriod) { - val := *flags.Lookup(flagHealthStartPeriod).Value.(*opts.PositiveDurationOpt).Value() - containerSpec.Healthcheck.StartPeriod = val - } - if flags.Changed(flagHealthRetries) { - containerSpec.Healthcheck.Retries, _ = flags.GetInt(flagHealthRetries) - } - if flags.Changed(flagHealthCmd) { - cmd, _ := flags.GetString(flagHealthCmd) - if cmd != "" { - containerSpec.Healthcheck.Test = []string{"CMD-SHELL", cmd} - } else { - containerSpec.Healthcheck.Test = nil - } - } - return nil -} - -type byNetworkTarget []swarm.NetworkAttachmentConfig - -func (m byNetworkTarget) Len() int { return len(m) } -func (m byNetworkTarget) Swap(i, j int) { m[i], m[j] = m[j], m[i] } -func (m byNetworkTarget) Less(i, j int) bool { - return m[i].Target < m[j].Target -} - -func updateNetworks(ctx context.Context, apiClient client.NetworkAPIClient, flags *pflag.FlagSet, spec *swarm.ServiceSpec) error { - // spec.TaskTemplate.Networks takes precedence over the deprecated - // spec.Networks field. If spec.Network is in use, we'll migrate those - // values to spec.TaskTemplate.Networks. - specNetworks := spec.TaskTemplate.Networks - if len(specNetworks) == 0 { - specNetworks = spec.Networks - } - spec.Networks = nil - - toRemove := buildToRemoveSet(flags, flagNetworkRemove) - idsToRemove := make(map[string]struct{}) - for networkIDOrName := range toRemove { - network, err := apiClient.NetworkInspect(ctx, networkIDOrName, types.NetworkInspectOptions{Scope: "swarm"}) - if err != nil { - return err - } - idsToRemove[network.ID] = struct{}{} - } - - existingNetworks := make(map[string]struct{}) - var newNetworks []swarm.NetworkAttachmentConfig - for _, network := range specNetworks { - if _, exists := idsToRemove[network.Target]; exists { - continue - } - - newNetworks = append(newNetworks, network) - existingNetworks[network.Target] = struct{}{} - } - - if flags.Changed(flagNetworkAdd) { - values := flags.Lookup(flagNetworkAdd).Value.(*opts.NetworkOpt) - networks, err := convertNetworks(ctx, apiClient, *values) - if err != nil { - return err - } - for _, network := range networks { - if _, exists := existingNetworks[network.Target]; exists { - return errors.Errorf("service is already attached to network %s", network.Target) - } - newNetworks = append(newNetworks, network) - existingNetworks[network.Target] = struct{}{} - } - } - - sort.Sort(byNetworkTarget(newNetworks)) - - spec.TaskTemplate.Networks = newNetworks - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/cmd.go b/vendor/github.com/docker/cli/cli/command/stack/cmd.go deleted file mode 100644 index 8d4281cfc6..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/cmd.go +++ /dev/null @@ -1,36 +0,0 @@ -package stack - -import ( - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -// NewStackCommand returns a cobra command for `stack` subcommands -// nolint: interfacer -func NewStackCommand(dockerCli *command.DockerCli) *cobra.Command { - cmd := &cobra.Command{ - Use: "stack", - Short: "Manage Docker stacks", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.25"}, - } - cmd.AddCommand( - newDeployCommand(dockerCli), - newListCommand(dockerCli), - newRemoveCommand(dockerCli), - newServicesCommand(dockerCli), - newPsCommand(dockerCli), - ) - return cmd -} - -// NewTopLevelDeployCommand returns a command for `docker deploy` -func NewTopLevelDeployCommand(dockerCli command.Cli) *cobra.Command { - cmd := newDeployCommand(dockerCli) - // Remove the aliases at the top level - cmd.Aliases = []string{} - cmd.Tags = map[string]string{"experimental": "", "version": "1.25"} - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/common.go b/vendor/github.com/docker/cli/cli/command/stack/common.go deleted file mode 100644 index d9f921af56..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/common.go +++ /dev/null @@ -1,73 +0,0 @@ -package stack - -import ( - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "golang.org/x/net/context" -) - -func getStackFilter(namespace string) filters.Args { - filter := filters.NewArgs() - filter.Add("label", convert.LabelNamespace+"="+namespace) - return filter -} - -func getServiceFilter(namespace string) filters.Args { - return getStackFilter(namespace) -} - -func getStackFilterFromOpt(namespace string, opt opts.FilterOpt) filters.Args { - filter := opt.Value() - filter.Add("label", convert.LabelNamespace+"="+namespace) - return filter -} - -func getAllStacksFilter() filters.Args { - filter := filters.NewArgs() - filter.Add("label", convert.LabelNamespace) - return filter -} - -func getServices( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]swarm.Service, error) { - return apiclient.ServiceList( - ctx, - types.ServiceListOptions{Filters: getServiceFilter(namespace)}) -} - -func getStackNetworks( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]types.NetworkResource, error) { - return apiclient.NetworkList( - ctx, - types.NetworkListOptions{Filters: getStackFilter(namespace)}) -} - -func getStackSecrets( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]swarm.Secret, error) { - return apiclient.SecretList( - ctx, - types.SecretListOptions{Filters: getStackFilter(namespace)}) -} - -func getStackConfigs( - ctx context.Context, - apiclient client.APIClient, - namespace string, -) ([]swarm.Config, error) { - return apiclient.ConfigList( - ctx, - types.ConfigListOptions{Filters: getStackFilter(namespace)}) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy.go b/vendor/github.com/docker/cli/cli/command/stack/deploy.go deleted file mode 100644 index 8e14b70d2f..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy.go +++ /dev/null @@ -1,123 +0,0 @@ -package stack - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/versions" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -const ( - defaultNetworkDriver = "overlay" - resolveImageAlways = "always" - resolveImageChanged = "changed" - resolveImageNever = "never" -) - -type deployOptions struct { - bundlefile string - composefile string - namespace string - resolveImage string - sendRegistryAuth bool - prune bool -} - -func newDeployCommand(dockerCli command.Cli) *cobra.Command { - var opts deployOptions - - cmd := &cobra.Command{ - Use: "deploy [OPTIONS] STACK", - Aliases: []string{"up"}, - Short: "Deploy a new stack or update an existing stack", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.namespace = args[0] - return runDeploy(dockerCli, opts) - }, - } - - flags := cmd.Flags() - addBundlefileFlag(&opts.bundlefile, flags) - addComposefileFlag(&opts.composefile, flags) - addRegistryAuthFlag(&opts.sendRegistryAuth, flags) - flags.BoolVar(&opts.prune, "prune", false, "Prune services that are no longer referenced") - flags.SetAnnotation("prune", "version", []string{"1.27"}) - flags.StringVar(&opts.resolveImage, "resolve-image", resolveImageAlways, - `Query the registry to resolve image digest and supported platforms ("`+resolveImageAlways+`"|"`+resolveImageChanged+`"|"`+resolveImageNever+`")`) - flags.SetAnnotation("resolve-image", "version", []string{"1.30"}) - return cmd -} - -func runDeploy(dockerCli command.Cli, opts deployOptions) error { - ctx := context.Background() - - if err := validateResolveImageFlag(dockerCli, &opts); err != nil { - return err - } - - switch { - case opts.bundlefile == "" && opts.composefile == "": - return errors.Errorf("Please specify either a bundle file (with --bundle-file) or a Compose file (with --compose-file).") - case opts.bundlefile != "" && opts.composefile != "": - return errors.Errorf("You cannot specify both a bundle file and a Compose file.") - case opts.bundlefile != "": - return deployBundle(ctx, dockerCli, opts) - default: - return deployCompose(ctx, dockerCli, opts) - } -} - -// validateResolveImageFlag validates the opts.resolveImage command line option -// and also turns image resolution off if the version is older than 1.30 -func validateResolveImageFlag(dockerCli command.Cli, opts *deployOptions) error { - if opts.resolveImage != resolveImageAlways && opts.resolveImage != resolveImageChanged && opts.resolveImage != resolveImageNever { - return errors.Errorf("Invalid option %s for flag --resolve-image", opts.resolveImage) - } - // client side image resolution should not be done when the supported - // server version is older than 1.30 - if versions.LessThan(dockerCli.Client().ClientVersion(), "1.30") { - opts.resolveImage = resolveImageNever - } - return nil -} - -// checkDaemonIsSwarmManager does an Info API call to verify that the daemon is -// a swarm manager. This is necessary because we must create networks before we -// create services, but the API call for creating a network does not return a -// proper status code when it can't create a network in the "global" scope. -func checkDaemonIsSwarmManager(ctx context.Context, dockerCli command.Cli) error { - info, err := dockerCli.Client().Info(ctx) - if err != nil { - return err - } - if !info.Swarm.ControlAvailable { - return errors.New("this node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join\" to connect this node to swarm and try again") - } - return nil -} - -// pruneServices removes services that are no longer referenced in the source -func pruneServices(ctx context.Context, dockerCli command.Cli, namespace convert.Namespace, services map[string]struct{}) bool { - client := dockerCli.Client() - - oldServices, err := getServices(ctx, client, namespace.Name()) - if err != nil { - fmt.Fprintf(dockerCli.Err(), "Failed to list services: %s", err) - return true - } - - pruneServices := []swarm.Service{} - for _, service := range oldServices { - if _, exists := services[namespace.Descope(service.Spec.Name)]; !exists { - pruneServices = append(pruneServices, service) - } - } - return removeServices(ctx, dockerCli, pruneServices) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go b/vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go deleted file mode 100644 index 1074210e97..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy_bundlefile.go +++ /dev/null @@ -1,91 +0,0 @@ -package stack - -import ( - "golang.org/x/net/context" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" -) - -func deployBundle(ctx context.Context, dockerCli command.Cli, opts deployOptions) error { - bundle, err := loadBundlefile(dockerCli.Err(), opts.namespace, opts.bundlefile) - if err != nil { - return err - } - - if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil { - return err - } - - namespace := convert.NewNamespace(opts.namespace) - - if opts.prune { - services := map[string]struct{}{} - for service := range bundle.Services { - services[service] = struct{}{} - } - pruneServices(ctx, dockerCli, namespace, services) - } - - networks := make(map[string]types.NetworkCreate) - for _, service := range bundle.Services { - for _, networkName := range service.Networks { - networks[networkName] = types.NetworkCreate{ - Labels: convert.AddStackLabel(namespace, nil), - } - } - } - - services := make(map[string]swarm.ServiceSpec) - for internalName, service := range bundle.Services { - name := namespace.Scope(internalName) - - var ports []swarm.PortConfig - for _, portSpec := range service.Ports { - ports = append(ports, swarm.PortConfig{ - Protocol: swarm.PortConfigProtocol(portSpec.Protocol), - TargetPort: portSpec.Port, - }) - } - - nets := []swarm.NetworkAttachmentConfig{} - for _, networkName := range service.Networks { - nets = append(nets, swarm.NetworkAttachmentConfig{ - Target: namespace.Scope(networkName), - Aliases: []string{internalName}, - }) - } - - serviceSpec := swarm.ServiceSpec{ - Annotations: swarm.Annotations{ - Name: name, - Labels: convert.AddStackLabel(namespace, service.Labels), - }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: swarm.ContainerSpec{ - Image: service.Image, - Command: service.Command, - Args: service.Args, - Env: service.Env, - // Service Labels will not be copied to Containers - // automatically during the deployment so we apply - // it here. - Labels: convert.AddStackLabel(namespace, nil), - }, - }, - EndpointSpec: &swarm.EndpointSpec{ - Ports: ports, - }, - Networks: nets, - } - - services[internalName] = serviceSpec - } - - if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil { - return err - } - return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.resolveImage) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile.go b/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile.go deleted file mode 100644 index 8e5dfed4d5..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/deploy_composefile.go +++ /dev/null @@ -1,350 +0,0 @@ -package stack - -import ( - "fmt" - "io/ioutil" - "os" - "path/filepath" - "sort" - "strings" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/cli/cli/compose/loader" - composetypes "github.com/docker/cli/cli/compose/types" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/swarm" - apiclient "github.com/docker/docker/client" - dockerclient "github.com/docker/docker/client" - "github.com/pkg/errors" - "golang.org/x/net/context" -) - -func deployCompose(ctx context.Context, dockerCli command.Cli, opts deployOptions) error { - configDetails, err := getConfigDetails(opts.composefile) - if err != nil { - return err - } - - config, err := loader.Load(configDetails) - if err != nil { - if fpe, ok := err.(*loader.ForbiddenPropertiesError); ok { - return errors.Errorf("Compose file contains unsupported options:\n\n%s\n", - propertyWarnings(fpe.Properties)) - } - - return err - } - - unsupportedProperties := loader.GetUnsupportedProperties(configDetails) - if len(unsupportedProperties) > 0 { - fmt.Fprintf(dockerCli.Err(), "Ignoring unsupported options: %s\n\n", - strings.Join(unsupportedProperties, ", ")) - } - - deprecatedProperties := loader.GetDeprecatedProperties(configDetails) - if len(deprecatedProperties) > 0 { - fmt.Fprintf(dockerCli.Err(), "Ignoring deprecated options:\n\n%s\n\n", - propertyWarnings(deprecatedProperties)) - } - - if err := checkDaemonIsSwarmManager(ctx, dockerCli); err != nil { - return err - } - - namespace := convert.NewNamespace(opts.namespace) - - if opts.prune { - services := map[string]struct{}{} - for _, service := range config.Services { - services[service.Name] = struct{}{} - } - pruneServices(ctx, dockerCli, namespace, services) - } - - serviceNetworks := getServicesDeclaredNetworks(config.Services) - networks, externalNetworks := convert.Networks(namespace, config.Networks, serviceNetworks) - if err := validateExternalNetworks(ctx, dockerCli.Client(), externalNetworks); err != nil { - return err - } - if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil { - return err - } - - secrets, err := convert.Secrets(namespace, config.Secrets) - if err != nil { - return err - } - if err := createSecrets(ctx, dockerCli, secrets); err != nil { - return err - } - - configs, err := convert.Configs(namespace, config.Configs) - if err != nil { - return err - } - if err := createConfigs(ctx, dockerCli, configs); err != nil { - return err - } - - services, err := convert.Services(namespace, config, dockerCli.Client()) - if err != nil { - return err - } - return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.resolveImage) -} - -func getServicesDeclaredNetworks(serviceConfigs []composetypes.ServiceConfig) map[string]struct{} { - serviceNetworks := map[string]struct{}{} - for _, serviceConfig := range serviceConfigs { - if len(serviceConfig.Networks) == 0 { - serviceNetworks["default"] = struct{}{} - continue - } - for network := range serviceConfig.Networks { - serviceNetworks[network] = struct{}{} - } - } - return serviceNetworks -} - -func propertyWarnings(properties map[string]string) string { - var msgs []string - for name, description := range properties { - msgs = append(msgs, fmt.Sprintf("%s: %s", name, description)) - } - sort.Strings(msgs) - return strings.Join(msgs, "\n\n") -} - -func getConfigDetails(composefile string) (composetypes.ConfigDetails, error) { - var details composetypes.ConfigDetails - - absPath, err := filepath.Abs(composefile) - if err != nil { - return details, err - } - details.WorkingDir = filepath.Dir(absPath) - - configFile, err := getConfigFile(composefile) - if err != nil { - return details, err - } - // TODO: support multiple files - details.ConfigFiles = []composetypes.ConfigFile{*configFile} - details.Environment, err = buildEnvironment(os.Environ()) - return details, err -} - -func buildEnvironment(env []string) (map[string]string, error) { - result := make(map[string]string, len(env)) - for _, s := range env { - // if value is empty, s is like "K=", not "K". - if !strings.Contains(s, "=") { - return result, errors.Errorf("unexpected environment %q", s) - } - kv := strings.SplitN(s, "=", 2) - result[kv[0]] = kv[1] - } - return result, nil -} - -func getConfigFile(filename string) (*composetypes.ConfigFile, error) { - bytes, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - config, err := loader.ParseYAML(bytes) - if err != nil { - return nil, err - } - return &composetypes.ConfigFile{ - Filename: filename, - Config: config, - }, nil -} - -func validateExternalNetworks( - ctx context.Context, - client dockerclient.NetworkAPIClient, - externalNetworks []string, -) error { - for _, networkName := range externalNetworks { - network, err := client.NetworkInspect(ctx, networkName, types.NetworkInspectOptions{}) - switch { - case dockerclient.IsErrNotFound(err): - return errors.Errorf("network %q is declared as external, but could not be found. You need to create a swarm-scoped network before the stack is deployed", networkName) - case err != nil: - return err - case container.NetworkMode(networkName).IsUserDefined() && network.Scope != "swarm": - return errors.Errorf("network %q is declared as external, but it is not in the right scope: %q instead of \"swarm\"", networkName, network.Scope) - } - } - return nil -} - -func createSecrets( - ctx context.Context, - dockerCli command.Cli, - secrets []swarm.SecretSpec, -) error { - client := dockerCli.Client() - - for _, secretSpec := range secrets { - secret, _, err := client.SecretInspectWithRaw(ctx, secretSpec.Name) - switch { - case err == nil: - // secret already exists, then we update that - if err := client.SecretUpdate(ctx, secret.ID, secret.Meta.Version, secretSpec); err != nil { - return errors.Wrapf(err, "failed to update secret %s", secretSpec.Name) - } - case apiclient.IsErrSecretNotFound(err): - // secret does not exist, then we create a new one. - if _, err := client.SecretCreate(ctx, secretSpec); err != nil { - return errors.Wrapf(err, "failed to create secret %s", secretSpec.Name) - } - default: - return err - } - } - return nil -} - -func createConfigs( - ctx context.Context, - dockerCli command.Cli, - configs []swarm.ConfigSpec, -) error { - client := dockerCli.Client() - - for _, configSpec := range configs { - config, _, err := client.ConfigInspectWithRaw(ctx, configSpec.Name) - switch { - case err == nil: - // config already exists, then we update that - if err := client.ConfigUpdate(ctx, config.ID, config.Meta.Version, configSpec); err != nil { - errors.Wrapf(err, "failed to update config %s", configSpec.Name) - } - case apiclient.IsErrConfigNotFound(err): - // config does not exist, then we create a new one. - if _, err := client.ConfigCreate(ctx, configSpec); err != nil { - errors.Wrapf(err, "failed to create config %s", configSpec.Name) - } - default: - return err - } - } - return nil -} - -func createNetworks( - ctx context.Context, - dockerCli command.Cli, - namespace convert.Namespace, - networks map[string]types.NetworkCreate, -) error { - client := dockerCli.Client() - - existingNetworks, err := getStackNetworks(ctx, client, namespace.Name()) - if err != nil { - return err - } - - existingNetworkMap := make(map[string]types.NetworkResource) - for _, network := range existingNetworks { - existingNetworkMap[network.Name] = network - } - - for internalName, createOpts := range networks { - name := namespace.Scope(internalName) - if _, exists := existingNetworkMap[name]; exists { - continue - } - - if createOpts.Driver == "" { - createOpts.Driver = defaultNetworkDriver - } - - fmt.Fprintf(dockerCli.Out(), "Creating network %s\n", name) - if _, err := client.NetworkCreate(ctx, name, createOpts); err != nil { - return errors.Wrapf(err, "failed to create network %s", internalName) - } - } - return nil -} - -func deployServices( - ctx context.Context, - dockerCli command.Cli, - services map[string]swarm.ServiceSpec, - namespace convert.Namespace, - sendAuth bool, - resolveImage string, -) error { - apiClient := dockerCli.Client() - out := dockerCli.Out() - - existingServices, err := getServices(ctx, apiClient, namespace.Name()) - if err != nil { - return err - } - - existingServiceMap := make(map[string]swarm.Service) - for _, service := range existingServices { - existingServiceMap[service.Spec.Name] = service - } - - for internalName, serviceSpec := range services { - name := namespace.Scope(internalName) - - encodedAuth := "" - image := serviceSpec.TaskTemplate.ContainerSpec.Image - if sendAuth { - // Retrieve encoded auth token from the image reference - encodedAuth, err = command.RetrieveAuthTokenFromImage(ctx, dockerCli, image) - if err != nil { - return err - } - } - - if service, exists := existingServiceMap[name]; exists { - fmt.Fprintf(out, "Updating service %s (id: %s)\n", name, service.ID) - - updateOpts := types.ServiceUpdateOptions{EncodedRegistryAuth: encodedAuth} - - if resolveImage == resolveImageAlways || (resolveImage == resolveImageChanged && image != service.Spec.Labels[convert.LabelImage]) { - updateOpts.QueryRegistry = true - } - - response, err := apiClient.ServiceUpdate( - ctx, - service.ID, - service.Version, - serviceSpec, - updateOpts, - ) - if err != nil { - return errors.Wrapf(err, "failed to update service %s", name) - } - - for _, warning := range response.Warnings { - fmt.Fprintln(dockerCli.Err(), warning) - } - } else { - fmt.Fprintf(out, "Creating service %s\n", name) - - createOpts := types.ServiceCreateOptions{EncodedRegistryAuth: encodedAuth} - - // query registry if flag disabling it was not set - if resolveImage == resolveImageAlways || resolveImage == resolveImageChanged { - createOpts.QueryRegistry = true - } - - if _, err := apiClient.ServiceCreate(ctx, serviceSpec, createOpts); err != nil { - return errors.Wrapf(err, "failed to create service %s", name) - } - } - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/list.go b/vendor/github.com/docker/cli/cli/command/stack/list.go deleted file mode 100644 index f3781d260c..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/list.go +++ /dev/null @@ -1,95 +0,0 @@ -package stack - -import ( - "sort" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/compose/convert" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type listOptions struct { - format string -} - -func newListCommand(dockerCli command.Cli) *cobra.Command { - opts := listOptions{} - - cmd := &cobra.Command{ - Use: "ls", - Aliases: []string{"list"}, - Short: "List stacks", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runList(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.StringVar(&opts.format, "format", "", "Pretty-print stacks using a Go template") - return cmd -} - -func runList(dockerCli command.Cli, opts listOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - stacks, err := getStacks(ctx, client) - if err != nil { - return err - } - format := opts.format - if len(format) == 0 { - format = formatter.TableFormatKey - } - stackCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewStackFormat(format), - } - sort.Sort(byName(stacks)) - return formatter.StackWrite(stackCtx, stacks) -} - -type byName []*formatter.Stack - -func (n byName) Len() int { return len(n) } -func (n byName) Swap(i, j int) { n[i], n[j] = n[j], n[i] } -func (n byName) Less(i, j int) bool { return n[i].Name < n[j].Name } - -func getStacks(ctx context.Context, apiclient client.APIClient) ([]*formatter.Stack, error) { - services, err := apiclient.ServiceList( - ctx, - types.ServiceListOptions{Filters: getAllStacksFilter()}) - if err != nil { - return nil, err - } - m := make(map[string]*formatter.Stack) - for _, service := range services { - labels := service.Spec.Labels - name, ok := labels[convert.LabelNamespace] - if !ok { - return nil, errors.Errorf("cannot get label %s for service %s", - convert.LabelNamespace, service.ID) - } - ztack, ok := m[name] - if !ok { - m[name] = &formatter.Stack{ - Name: name, - Services: 1, - } - } else { - ztack.Services++ - } - } - var stacks []*formatter.Stack - for _, stack := range m { - stacks = append(stacks, stack) - } - return stacks, nil -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/opts.go b/vendor/github.com/docker/cli/cli/command/stack/opts.go deleted file mode 100644 index c1634e26be..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/opts.go +++ /dev/null @@ -1,51 +0,0 @@ -package stack - -import ( - "fmt" - "io" - "os" - - "github.com/docker/cli/cli/command/bundlefile" - "github.com/pkg/errors" - "github.com/spf13/pflag" -) - -func addComposefileFlag(opt *string, flags *pflag.FlagSet) { - flags.StringVarP(opt, "compose-file", "c", "", "Path to a Compose file") - flags.SetAnnotation("compose-file", "version", []string{"1.25"}) -} - -func addBundlefileFlag(opt *string, flags *pflag.FlagSet) { - flags.StringVar(opt, "bundle-file", "", "Path to a Distributed Application Bundle file") - flags.SetAnnotation("bundle-file", "experimental", nil) -} - -func addRegistryAuthFlag(opt *bool, flags *pflag.FlagSet) { - flags.BoolVar(opt, "with-registry-auth", false, "Send registry authentication details to Swarm agents") -} - -func loadBundlefile(stderr io.Writer, namespace string, path string) (*bundlefile.Bundlefile, error) { - defaultPath := fmt.Sprintf("%s.dab", namespace) - - if path == "" { - path = defaultPath - } - if _, err := os.Stat(path); err != nil { - return nil, errors.Errorf( - "Bundle %s not found. Specify the path with --file", - path) - } - - fmt.Fprintf(stderr, "Loading bundle from %s\n", path) - reader, err := os.Open(path) - if err != nil { - return nil, err - } - defer reader.Close() - - bundle, err := bundlefile.LoadFile(reader) - if err != nil { - return nil, errors.Errorf("Error reading %s: %v\n", path, err) - } - return bundle, err -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/ps.go b/vendor/github.com/docker/cli/cli/command/stack/ps.go deleted file mode 100644 index ae9ed0f70a..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/ps.go +++ /dev/null @@ -1,75 +0,0 @@ -package stack - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/cli/cli/command/task" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type psOptions struct { - filter opts.FilterOpt - noTrunc bool - namespace string - noResolve bool - quiet bool - format string -} - -func newPsCommand(dockerCli command.Cli) *cobra.Command { - options := psOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "ps [OPTIONS] STACK", - Short: "List the tasks in the stack", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.namespace = args[0] - return runPS(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVar(&options.noTrunc, "no-trunc", false, "Do not truncate output") - flags.BoolVar(&options.noResolve, "no-resolve", false, "Do not map IDs to Names") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display task IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print tasks using a Go template") - - return cmd -} - -func runPS(dockerCli command.Cli, options psOptions) error { - namespace := options.namespace - client := dockerCli.Client() - ctx := context.Background() - - filter := getStackFilterFromOpt(options.namespace, options.filter) - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: filter}) - if err != nil { - return err - } - - if len(tasks) == 0 { - fmt.Fprintf(dockerCli.Out(), "Nothing found in stack: %s\n", namespace) - return nil - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().TasksFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().TasksFormat - } else { - format = formatter.TableFormatKey - } - } - - return task.Print(ctx, dockerCli, tasks, idresolver.New(client, options.noResolve), !options.noTrunc, options.quiet, format) -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/remove.go b/vendor/github.com/docker/cli/cli/command/stack/remove.go deleted file mode 100644 index b63c385a7e..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/remove.go +++ /dev/null @@ -1,153 +0,0 @@ -package stack - -import ( - "fmt" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/versions" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type removeOptions struct { - namespaces []string -} - -func newRemoveCommand(dockerCli command.Cli) *cobra.Command { - var opts removeOptions - - cmd := &cobra.Command{ - Use: "rm STACK [STACK...]", - Aliases: []string{"remove", "down"}, - Short: "Remove one or more stacks", - Args: cli.RequiresMinArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.namespaces = args - return runRemove(dockerCli, opts) - }, - } - return cmd -} - -func runRemove(dockerCli command.Cli, opts removeOptions) error { - namespaces := opts.namespaces - client := dockerCli.Client() - ctx := context.Background() - - var errs []string - for _, namespace := range namespaces { - services, err := getServices(ctx, client, namespace) - if err != nil { - return err - } - - networks, err := getStackNetworks(ctx, client, namespace) - if err != nil { - return err - } - - secrets, err := getStackSecrets(ctx, client, namespace) - if err != nil { - return err - } - - var configs []swarm.Config - - version, err := client.ServerVersion(ctx) - if err != nil { - return err - } - if versions.LessThan(version.APIVersion, "1.30") { - fmt.Fprintf(dockerCli.Err(), `WARNING: ignoring "configs" (requires API version 1.30, but the Docker daemon API version is %s)`, version.APIVersion) - } else { - configs, err = getStackConfigs(ctx, client, namespace) - if err != nil { - return err - } - } - - if len(services)+len(networks)+len(secrets)+len(configs) == 0 { - fmt.Fprintf(dockerCli.Out(), "Nothing found in stack: %s\n", namespace) - continue - } - - hasError := removeServices(ctx, dockerCli, services) - hasError = removeSecrets(ctx, dockerCli, secrets) || hasError - hasError = removeConfigs(ctx, dockerCli, configs) || hasError - hasError = removeNetworks(ctx, dockerCli, networks) || hasError - - if hasError { - errs = append(errs, fmt.Sprintf("Failed to remove some resources from stack: %s", namespace)) - } - } - - if len(errs) > 0 { - return errors.Errorf(strings.Join(errs, "\n")) - } - return nil -} - -func removeServices( - ctx context.Context, - dockerCli command.Cli, - services []swarm.Service, -) bool { - var err error - for _, service := range services { - fmt.Fprintf(dockerCli.Err(), "Removing service %s\n", service.Spec.Name) - if err = dockerCli.Client().ServiceRemove(ctx, service.ID); err != nil { - fmt.Fprintf(dockerCli.Err(), "Failed to remove service %s: %s", service.ID, err) - } - } - return err != nil -} - -func removeNetworks( - ctx context.Context, - dockerCli command.Cli, - networks []types.NetworkResource, -) bool { - var err error - for _, network := range networks { - fmt.Fprintf(dockerCli.Err(), "Removing network %s\n", network.Name) - if err = dockerCli.Client().NetworkRemove(ctx, network.ID); err != nil { - fmt.Fprintf(dockerCli.Err(), "Failed to remove network %s: %s", network.ID, err) - } - } - return err != nil -} - -func removeSecrets( - ctx context.Context, - dockerCli command.Cli, - secrets []swarm.Secret, -) bool { - var err error - for _, secret := range secrets { - fmt.Fprintf(dockerCli.Err(), "Removing secret %s\n", secret.Spec.Name) - if err = dockerCli.Client().SecretRemove(ctx, secret.ID); err != nil { - fmt.Fprintf(dockerCli.Err(), "Failed to remove secret %s: %s", secret.ID, err) - } - } - return err != nil -} - -func removeConfigs( - ctx context.Context, - dockerCli command.Cli, - configs []swarm.Config, -) bool { - var err error - for _, config := range configs { - fmt.Fprintf(dockerCli.Err(), "Removing config %s\n", config.Spec.Name) - if err = dockerCli.Client().ConfigRemove(ctx, config.ID); err != nil { - fmt.Fprintf(dockerCli.Err(), "Failed to remove config %s: %s", config.ID, err) - } - } - return err != nil -} diff --git a/vendor/github.com/docker/cli/cli/command/stack/services.go b/vendor/github.com/docker/cli/cli/command/stack/services.go deleted file mode 100644 index 5b59c479c6..0000000000 --- a/vendor/github.com/docker/cli/cli/command/stack/services.go +++ /dev/null @@ -1,96 +0,0 @@ -package stack - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/service" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/filters" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type servicesOptions struct { - quiet bool - format string - filter opts.FilterOpt - namespace string -} - -func newServicesCommand(dockerCli command.Cli) *cobra.Command { - options := servicesOptions{filter: opts.NewFilterOpt()} - - cmd := &cobra.Command{ - Use: "services [OPTIONS] STACK", - Short: "List the services in the stack", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - options.namespace = args[0] - return runServices(dockerCli, options) - }, - } - flags := cmd.Flags() - flags.BoolVarP(&options.quiet, "quiet", "q", false, "Only display IDs") - flags.StringVar(&options.format, "format", "", "Pretty-print services using a Go template") - flags.VarP(&options.filter, "filter", "f", "Filter output based on conditions provided") - - return cmd -} - -func runServices(dockerCli command.Cli, options servicesOptions) error { - ctx := context.Background() - client := dockerCli.Client() - - filter := getStackFilterFromOpt(options.namespace, options.filter) - services, err := client.ServiceList(ctx, types.ServiceListOptions{Filters: filter}) - if err != nil { - return err - } - - out := dockerCli.Out() - - // if no services in this stack, print message and exit 0 - if len(services) == 0 { - fmt.Fprintf(out, "Nothing found in stack: %s\n", options.namespace) - return nil - } - - info := map[string]formatter.ServiceListInfo{} - if !options.quiet { - taskFilter := filters.NewArgs() - for _, service := range services { - taskFilter.Add("service", service.ID) - } - - tasks, err := client.TaskList(ctx, types.TaskListOptions{Filters: taskFilter}) - if err != nil { - return err - } - - nodes, err := client.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return err - } - - info = service.GetServicesStatus(services, nodes, tasks) - } - - format := options.format - if len(format) == 0 { - if len(dockerCli.ConfigFile().ServicesFormat) > 0 && !options.quiet { - format = dockerCli.ConfigFile().ServicesFormat - } else { - format = formatter.TableFormatKey - } - } - - servicesCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewServiceListFormat(format, options.quiet), - } - return formatter.ServiceListWrite(servicesCtx, services, info) -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/ca.go b/vendor/github.com/docker/cli/cli/command/swarm/ca.go deleted file mode 100644 index fab0929b64..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/ca.go +++ /dev/null @@ -1,128 +0,0 @@ -package swarm - -import ( - "fmt" - "io" - "strings" - - "golang.org/x/net/context" - - "io/ioutil" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/swarm/progress" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/pkg/jsonmessage" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -type caOptions struct { - swarmOptions - rootCACert PEMFile - rootCAKey PEMFile - rotate bool - detach bool - quiet bool -} - -func newRotateCACommand(dockerCli command.Cli) *cobra.Command { - opts := caOptions{} - - cmd := &cobra.Command{ - Use: "ca [OPTIONS]", - Short: "Manage root CA", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runRotateCA(dockerCli, cmd.Flags(), opts) - }, - Tags: map[string]string{"version": "1.30"}, - } - - flags := cmd.Flags() - addSwarmCAFlags(flags, &opts.swarmOptions) - flags.BoolVar(&opts.rotate, flagRotate, false, "Rotate the swarm CA - if no certificate or key are provided, new ones will be generated") - flags.Var(&opts.rootCACert, flagCACert, "Path to the PEM-formatted root CA certificate to use for the new cluster") - flags.Var(&opts.rootCAKey, flagCAKey, "Path to the PEM-formatted root CA key to use for the new cluster") - - flags.BoolVarP(&opts.detach, "detach", "d", false, "Exit immediately instead of waiting for the root rotation to converge") - flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress progress output") - return cmd -} - -func runRotateCA(dockerCli command.Cli, flags *pflag.FlagSet, opts caOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - swarmInspect, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if !opts.rotate { - if swarmInspect.ClusterInfo.TLSInfo.TrustRoot == "" { - fmt.Fprintln(dockerCli.Out(), "No CA information available") - } else { - fmt.Fprintln(dockerCli.Out(), strings.TrimSpace(swarmInspect.ClusterInfo.TLSInfo.TrustRoot)) - } - return nil - } - - genRootCA := true - spec := &swarmInspect.Spec - opts.mergeSwarmSpec(spec, flags) - if flags.Changed(flagCACert) { - spec.CAConfig.SigningCACert = opts.rootCACert.Contents() - genRootCA = false - } - if flags.Changed(flagCAKey) { - spec.CAConfig.SigningCAKey = opts.rootCAKey.Contents() - genRootCA = false - } - if genRootCA { - spec.CAConfig.ForceRotate++ - spec.CAConfig.SigningCACert = "" - spec.CAConfig.SigningCAKey = "" - } - - if err := client.SwarmUpdate(ctx, swarmInspect.Version, swarmInspect.Spec, swarm.UpdateFlags{}); err != nil { - return err - } - - if opts.detach { - return nil - } - - errChan := make(chan error, 1) - pipeReader, pipeWriter := io.Pipe() - - go func() { - errChan <- progress.RootRotationProgress(ctx, client, pipeWriter) - }() - - if opts.quiet { - go io.Copy(ioutil.Discard, pipeReader) - return <-errChan - } - - err = jsonmessage.DisplayJSONMessagesToStream(pipeReader, dockerCli.Out(), nil) - if err == nil { - err = <-errChan - } - if err != nil { - return err - } - - swarmInspect, err = client.SwarmInspect(ctx) - if err != nil { - return err - } - - if swarmInspect.ClusterInfo.TLSInfo.TrustRoot == "" { - fmt.Fprintln(dockerCli.Out(), "No CA information available") - } else { - fmt.Fprintln(dockerCli.Out(), strings.TrimSpace(swarmInspect.ClusterInfo.TLSInfo.TrustRoot)) - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/cmd.go b/vendor/github.com/docker/cli/cli/command/swarm/cmd.go deleted file mode 100644 index b7e6dcfda2..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/cmd.go +++ /dev/null @@ -1,31 +0,0 @@ -package swarm - -import ( - "github.com/spf13/cobra" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" -) - -// NewSwarmCommand returns a cobra command for `swarm` subcommands -// nolint: interfacer -func NewSwarmCommand(dockerCli command.Cli) *cobra.Command { - cmd := &cobra.Command{ - Use: "swarm", - Short: "Manage Swarm", - Args: cli.NoArgs, - RunE: command.ShowHelp(dockerCli.Err()), - Tags: map[string]string{"version": "1.24"}, - } - cmd.AddCommand( - newInitCommand(dockerCli), - newJoinCommand(dockerCli), - newJoinTokenCommand(dockerCli), - newUnlockKeyCommand(dockerCli), - newUpdateCommand(dockerCli), - newLeaveCommand(dockerCli), - newUnlockCommand(dockerCli), - newRotateCACommand(dockerCli), - ) - return cmd -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/init.go b/vendor/github.com/docker/cli/cli/command/swarm/init.go deleted file mode 100644 index 91b827eb97..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/init.go +++ /dev/null @@ -1,99 +0,0 @@ -package swarm - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -type initOptions struct { - swarmOptions - listenAddr NodeAddrOption - // Not a NodeAddrOption because it has no default port. - advertiseAddr string - dataPathAddr string - forceNewCluster bool - availability string -} - -func newInitCommand(dockerCli command.Cli) *cobra.Command { - opts := initOptions{ - listenAddr: NewListenAddrOption(), - } - - cmd := &cobra.Command{ - Use: "init [OPTIONS]", - Short: "Initialize a swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runInit(dockerCli, cmd.Flags(), opts) - }, - } - - flags := cmd.Flags() - flags.Var(&opts.listenAddr, flagListenAddr, "Listen address (format: [:port])") - flags.StringVar(&opts.advertiseAddr, flagAdvertiseAddr, "", "Advertised address (format: [:port])") - flags.StringVar(&opts.dataPathAddr, flagDataPathAddr, "", "Address or interface to use for data path traffic (format: )") - flags.BoolVar(&opts.forceNewCluster, "force-new-cluster", false, "Force create a new cluster from current state") - flags.BoolVar(&opts.autolock, flagAutolock, false, "Enable manager autolocking (requiring an unlock key to start a stopped manager)") - flags.StringVar(&opts.availability, flagAvailability, "active", `Availability of the node ("active"|"pause"|"drain")`) - addSwarmFlags(flags, &opts.swarmOptions) - return cmd -} - -func runInit(dockerCli command.Cli, flags *pflag.FlagSet, opts initOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - req := swarm.InitRequest{ - ListenAddr: opts.listenAddr.String(), - AdvertiseAddr: opts.advertiseAddr, - DataPathAddr: opts.dataPathAddr, - ForceNewCluster: opts.forceNewCluster, - Spec: opts.swarmOptions.ToSpec(flags), - AutoLockManagers: opts.swarmOptions.autolock, - } - if flags.Changed(flagAvailability) { - availability := swarm.NodeAvailability(strings.ToLower(opts.availability)) - switch availability { - case swarm.NodeAvailabilityActive, swarm.NodeAvailabilityPause, swarm.NodeAvailabilityDrain: - req.Availability = availability - default: - return errors.Errorf("invalid availability %q, only active, pause and drain are supported", opts.availability) - } - } - - nodeID, err := client.SwarmInit(ctx, req) - if err != nil { - if strings.Contains(err.Error(), "could not choose an IP address to advertise") || strings.Contains(err.Error(), "could not find the system's IP address") { - return errors.New(err.Error() + " - specify one with --advertise-addr") - } - return err - } - - fmt.Fprintf(dockerCli.Out(), "Swarm initialized: current node (%s) is now a manager.\n\n", nodeID) - - if err := printJoinCommand(ctx, dockerCli, nodeID, true, false); err != nil { - return err - } - - fmt.Fprint(dockerCli.Out(), "To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.\n\n") - - if req.AutoLockManagers { - unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) - if err != nil { - return errors.Wrap(err, "could not fetch unlock key") - } - printUnlockCommand(dockerCli.Out(), unlockKeyResp.UnlockKey) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/join.go b/vendor/github.com/docker/cli/cli/command/swarm/join.go deleted file mode 100644 index 0f09527d07..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/join.go +++ /dev/null @@ -1,88 +0,0 @@ -package swarm - -import ( - "fmt" - "strings" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -type joinOptions struct { - remote string - listenAddr NodeAddrOption - // Not a NodeAddrOption because it has no default port. - advertiseAddr string - dataPathAddr string - token string - availability string -} - -func newJoinCommand(dockerCli command.Cli) *cobra.Command { - opts := joinOptions{ - listenAddr: NewListenAddrOption(), - } - - cmd := &cobra.Command{ - Use: "join [OPTIONS] HOST:PORT", - Short: "Join a swarm as a node and/or manager", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.remote = args[0] - return runJoin(dockerCli, cmd.Flags(), opts) - }, - } - - flags := cmd.Flags() - flags.Var(&opts.listenAddr, flagListenAddr, "Listen address (format: [:port])") - flags.StringVar(&opts.advertiseAddr, flagAdvertiseAddr, "", "Advertised address (format: [:port])") - flags.StringVar(&opts.dataPathAddr, flagDataPathAddr, "", "Address or interface to use for data path traffic (format: )") - flags.StringVar(&opts.token, flagToken, "", "Token for entry into the swarm") - flags.StringVar(&opts.availability, flagAvailability, "active", `Availability of the node ("active"|"pause"|"drain")`) - return cmd -} - -func runJoin(dockerCli command.Cli, flags *pflag.FlagSet, opts joinOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - req := swarm.JoinRequest{ - JoinToken: opts.token, - ListenAddr: opts.listenAddr.String(), - AdvertiseAddr: opts.advertiseAddr, - DataPathAddr: opts.dataPathAddr, - RemoteAddrs: []string{opts.remote}, - } - if flags.Changed(flagAvailability) { - availability := swarm.NodeAvailability(strings.ToLower(opts.availability)) - switch availability { - case swarm.NodeAvailabilityActive, swarm.NodeAvailabilityPause, swarm.NodeAvailabilityDrain: - req.Availability = availability - default: - return errors.Errorf("invalid availability %q, only active, pause and drain are supported", opts.availability) - } - } - - err := client.SwarmJoin(ctx, req) - if err != nil { - return err - } - - info, err := client.Info(ctx) - if err != nil { - return err - } - - if info.Swarm.ControlAvailable { - fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a manager.") - } else { - fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a worker.") - } - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/join_token.go b/vendor/github.com/docker/cli/cli/command/swarm/join_token.go deleted file mode 100644 index b35efad8a9..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/join_token.go +++ /dev/null @@ -1,119 +0,0 @@ -package swarm - -import ( - "fmt" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type joinTokenOptions struct { - role string - rotate bool - quiet bool -} - -func newJoinTokenCommand(dockerCli command.Cli) *cobra.Command { - opts := joinTokenOptions{} - - cmd := &cobra.Command{ - Use: "join-token [OPTIONS] (worker|manager)", - Short: "Manage join tokens", - Args: cli.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - opts.role = args[0] - return runJoinToken(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVar(&opts.rotate, flagRotate, false, "Rotate join token") - flags.BoolVarP(&opts.quiet, flagQuiet, "q", false, "Only display token") - - return cmd -} - -func runJoinToken(dockerCli command.Cli, opts joinTokenOptions) error { - worker := opts.role == "worker" - manager := opts.role == "manager" - - if !worker && !manager { - return errors.New("unknown role " + opts.role) - } - - client := dockerCli.Client() - ctx := context.Background() - - if opts.rotate { - flags := swarm.UpdateFlags{ - RotateWorkerToken: worker, - RotateManagerToken: manager, - } - - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if err := client.SwarmUpdate(ctx, sw.Version, sw.Spec, flags); err != nil { - return err - } - - if !opts.quiet { - fmt.Fprintf(dockerCli.Out(), "Successfully rotated %s join token.\n\n", opts.role) - } - } - - // second SwarmInspect in this function, - // this is necessary since SwarmUpdate after first changes the join tokens - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if opts.quiet && worker { - fmt.Fprintln(dockerCli.Out(), sw.JoinTokens.Worker) - return nil - } - - if opts.quiet && manager { - fmt.Fprintln(dockerCli.Out(), sw.JoinTokens.Manager) - return nil - } - - info, err := client.Info(ctx) - if err != nil { - return err - } - - return printJoinCommand(ctx, dockerCli, info.Swarm.NodeID, worker, manager) -} - -func printJoinCommand(ctx context.Context, dockerCli command.Cli, nodeID string, worker bool, manager bool) error { - client := dockerCli.Client() - - node, _, err := client.NodeInspectWithRaw(ctx, nodeID) - if err != nil { - return err - } - - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if node.ManagerStatus != nil { - if worker { - fmt.Fprintf(dockerCli.Out(), "To add a worker to this swarm, run the following command:\n\n docker swarm join --token %s %s\n\n", sw.JoinTokens.Worker, node.ManagerStatus.Addr) - } - if manager { - fmt.Fprintf(dockerCli.Out(), "To add a manager to this swarm, run the following command:\n\n docker swarm join --token %s %s\n\n", sw.JoinTokens.Manager, node.ManagerStatus.Addr) - } - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/leave.go b/vendor/github.com/docker/cli/cli/command/swarm/leave.go deleted file mode 100644 index c9b33fd0de..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/leave.go +++ /dev/null @@ -1,44 +0,0 @@ -package swarm - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/spf13/cobra" -) - -type leaveOptions struct { - force bool -} - -func newLeaveCommand(dockerCli command.Cli) *cobra.Command { - opts := leaveOptions{} - - cmd := &cobra.Command{ - Use: "leave [OPTIONS]", - Short: "Leave the swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runLeave(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVarP(&opts.force, "force", "f", false, "Force this node to leave the swarm, ignoring warnings") - return cmd -} - -func runLeave(dockerCli command.Cli, opts leaveOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if err := client.SwarmLeave(ctx, opts.force); err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), "Node left the swarm.") - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/opts.go b/vendor/github.com/docker/cli/cli/command/swarm/opts.go deleted file mode 100644 index 0522f9fdfa..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/opts.go +++ /dev/null @@ -1,262 +0,0 @@ -package swarm - -import ( - "encoding/csv" - "encoding/pem" - "fmt" - "io/ioutil" - "strings" - "time" - - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/pflag" -) - -const ( - defaultListenAddr = "0.0.0.0:2377" - - flagCertExpiry = "cert-expiry" - flagDispatcherHeartbeat = "dispatcher-heartbeat" - flagListenAddr = "listen-addr" - flagAdvertiseAddr = "advertise-addr" - flagDataPathAddr = "data-path-addr" - flagQuiet = "quiet" - flagRotate = "rotate" - flagToken = "token" - flagTaskHistoryLimit = "task-history-limit" - flagExternalCA = "external-ca" - flagMaxSnapshots = "max-snapshots" - flagSnapshotInterval = "snapshot-interval" - flagAutolock = "autolock" - flagAvailability = "availability" - flagCACert = "ca-cert" - flagCAKey = "ca-key" -) - -type swarmOptions struct { - taskHistoryLimit int64 - dispatcherHeartbeat time.Duration - nodeCertExpiry time.Duration - externalCA ExternalCAOption - maxSnapshots uint64 - snapshotInterval uint64 - autolock bool -} - -// NodeAddrOption is a pflag.Value for listening addresses -type NodeAddrOption struct { - addr string -} - -// String prints the representation of this flag -func (a *NodeAddrOption) String() string { - return a.Value() -} - -// Set the value for this flag -func (a *NodeAddrOption) Set(value string) error { - addr, err := opts.ParseTCPAddr(value, a.addr) - if err != nil { - return err - } - a.addr = addr - return nil -} - -// Type returns the type of this flag -func (a *NodeAddrOption) Type() string { - return "node-addr" -} - -// Value returns the value of this option as addr:port -func (a *NodeAddrOption) Value() string { - return strings.TrimPrefix(a.addr, "tcp://") -} - -// NewNodeAddrOption returns a new node address option -func NewNodeAddrOption(addr string) NodeAddrOption { - return NodeAddrOption{addr} -} - -// NewListenAddrOption returns a NodeAddrOption with default values -func NewListenAddrOption() NodeAddrOption { - return NewNodeAddrOption(defaultListenAddr) -} - -// ExternalCAOption is a Value type for parsing external CA specifications. -type ExternalCAOption struct { - values []*swarm.ExternalCA -} - -// Set parses an external CA option. -func (m *ExternalCAOption) Set(value string) error { - parsed, err := parseExternalCA(value) - if err != nil { - return err - } - - m.values = append(m.values, parsed) - return nil -} - -// Type returns the type of this option. -func (m *ExternalCAOption) Type() string { - return "external-ca" -} - -// String returns a string repr of this option. -func (m *ExternalCAOption) String() string { - externalCAs := []string{} - for _, externalCA := range m.values { - repr := fmt.Sprintf("%s: %s", externalCA.Protocol, externalCA.URL) - externalCAs = append(externalCAs, repr) - } - return strings.Join(externalCAs, ", ") -} - -// Value returns the external CAs -func (m *ExternalCAOption) Value() []*swarm.ExternalCA { - return m.values -} - -// PEMFile represents the path to a pem-formatted file -type PEMFile struct { - path, contents string -} - -// Type returns the type of this option. -func (p *PEMFile) Type() string { - return "pem-file" -} - -// String returns the path to the pem file -func (p *PEMFile) String() string { - return p.path -} - -// Set parses a root rotation option -func (p *PEMFile) Set(value string) error { - contents, err := ioutil.ReadFile(value) - if err != nil { - return err - } - if pemBlock, _ := pem.Decode(contents); pemBlock == nil { - return errors.New("file contents must be in PEM format") - } - p.contents, p.path = string(contents), value - return nil -} - -// Contents returns the contents of the PEM file -func (p *PEMFile) Contents() string { - return p.contents -} - -// parseExternalCA parses an external CA specification from the command line, -// such as protocol=cfssl,url=https://example.com. -func parseExternalCA(caSpec string) (*swarm.ExternalCA, error) { - csvReader := csv.NewReader(strings.NewReader(caSpec)) - fields, err := csvReader.Read() - if err != nil { - return nil, err - } - - externalCA := swarm.ExternalCA{ - Options: make(map[string]string), - } - - var ( - hasProtocol bool - hasURL bool - ) - - for _, field := range fields { - parts := strings.SplitN(field, "=", 2) - - if len(parts) != 2 { - return nil, errors.Errorf("invalid field '%s' must be a key=value pair", field) - } - - key, value := parts[0], parts[1] - - switch strings.ToLower(key) { - case "protocol": - hasProtocol = true - if strings.ToLower(value) == string(swarm.ExternalCAProtocolCFSSL) { - externalCA.Protocol = swarm.ExternalCAProtocolCFSSL - } else { - return nil, errors.Errorf("unrecognized external CA protocol %s", value) - } - case "url": - hasURL = true - externalCA.URL = value - case "cacert": - cacontents, err := ioutil.ReadFile(value) - if err != nil { - return nil, errors.Wrap(err, "unable to read CA cert for external CA") - } - if pemBlock, _ := pem.Decode(cacontents); pemBlock == nil { - return nil, errors.New("CA cert for external CA must be in PEM format") - } - externalCA.CACert = string(cacontents) - default: - externalCA.Options[key] = value - } - } - - if !hasProtocol { - return nil, errors.New("the external-ca option needs a protocol= parameter") - } - if !hasURL { - return nil, errors.New("the external-ca option needs a url= parameter") - } - - return &externalCA, nil -} - -func addSwarmCAFlags(flags *pflag.FlagSet, opts *swarmOptions) { - flags.DurationVar(&opts.nodeCertExpiry, flagCertExpiry, 90*24*time.Hour, "Validity period for node certificates (ns|us|ms|s|m|h)") - flags.Var(&opts.externalCA, flagExternalCA, "Specifications of one or more certificate signing endpoints") -} - -func addSwarmFlags(flags *pflag.FlagSet, opts *swarmOptions) { - flags.Int64Var(&opts.taskHistoryLimit, flagTaskHistoryLimit, 5, "Task history retention limit") - flags.DurationVar(&opts.dispatcherHeartbeat, flagDispatcherHeartbeat, 5*time.Second, "Dispatcher heartbeat period (ns|us|ms|s|m|h)") - flags.Uint64Var(&opts.maxSnapshots, flagMaxSnapshots, 0, "Number of additional Raft snapshots to retain") - flags.SetAnnotation(flagMaxSnapshots, "version", []string{"1.25"}) - flags.Uint64Var(&opts.snapshotInterval, flagSnapshotInterval, 10000, "Number of log entries between Raft snapshots") - flags.SetAnnotation(flagSnapshotInterval, "version", []string{"1.25"}) - addSwarmCAFlags(flags, opts) -} - -func (opts *swarmOptions) mergeSwarmSpec(spec *swarm.Spec, flags *pflag.FlagSet) { - if flags.Changed(flagTaskHistoryLimit) { - spec.Orchestration.TaskHistoryRetentionLimit = &opts.taskHistoryLimit - } - if flags.Changed(flagDispatcherHeartbeat) { - spec.Dispatcher.HeartbeatPeriod = opts.dispatcherHeartbeat - } - if flags.Changed(flagCertExpiry) { - spec.CAConfig.NodeCertExpiry = opts.nodeCertExpiry - } - if flags.Changed(flagExternalCA) { - spec.CAConfig.ExternalCAs = opts.externalCA.Value() - } - if flags.Changed(flagMaxSnapshots) { - spec.Raft.KeepOldSnapshots = &opts.maxSnapshots - } - if flags.Changed(flagSnapshotInterval) { - spec.Raft.SnapshotInterval = opts.snapshotInterval - } - if flags.Changed(flagAutolock) { - spec.EncryptionConfig.AutoLockManagers = opts.autolock - } -} - -func (opts *swarmOptions) ToSpec(flags *pflag.FlagSet) swarm.Spec { - var spec swarm.Spec - opts.mergeSwarmSpec(&spec, flags) - return spec -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/progress/root_rotation.go b/vendor/github.com/docker/cli/cli/command/swarm/progress/root_rotation.go deleted file mode 100644 index 0b84d239e3..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/progress/root_rotation.go +++ /dev/null @@ -1,121 +0,0 @@ -package progress - -import ( - "bytes" - "io" - "os" - "os/signal" - "time" - - "golang.org/x/net/context" - - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/progress" - "github.com/docker/docker/pkg/streamformatter" - "github.com/opencontainers/go-digest" -) - -const ( - certsRotatedStr = " rotated TLS certificates" - rootsRotatedStr = " rotated CA certificates" - // rootsAction has a single space because rootsRotatedStr is one character shorter than certsRotatedStr. - // This makes sure the progress bar are aligned. - certsAction = "" - rootsAction = " " -) - -// RootRotationProgress outputs progress information for convergence of a root rotation. -func RootRotationProgress(ctx context.Context, dclient client.APIClient, progressWriter io.WriteCloser) error { - defer progressWriter.Close() - - progressOut := streamformatter.NewJSONProgressOutput(progressWriter, false) - - sigint := make(chan os.Signal, 1) - signal.Notify(sigint, os.Interrupt) - defer signal.Stop(sigint) - - // draw 2 progress bars, 1 for nodes with the correct cert, 1 for nodes with the correct trust root - progress.Update(progressOut, "desired root digest", "") - progress.Update(progressOut, certsRotatedStr, certsAction) - progress.Update(progressOut, rootsRotatedStr, rootsAction) - - var done bool - - for { - info, err := dclient.SwarmInspect(ctx) - if err != nil { - return err - } - - if done { - return nil - } - - nodes, err := dclient.NodeList(ctx, types.NodeListOptions{}) - if err != nil { - return err - } - - done = updateProgress(progressOut, info.ClusterInfo.TLSInfo, nodes, info.ClusterInfo.RootRotationInProgress) - - select { - case <-time.After(200 * time.Millisecond): - case <-sigint: - if !done { - progress.Message(progressOut, "", "Operation continuing in background.") - progress.Message(progressOut, "", "Use `swarmctl cluster inspect default` to check progress.") - } - return nil - } - } -} - -func updateProgress(progressOut progress.Output, desiredTLSInfo swarm.TLSInfo, nodes []swarm.Node, rootRotationInProgress bool) bool { - // write the current desired root cert's digest, because the desired root certs might be too long - progressOut.WriteProgress(progress.Progress{ - ID: "desired root digest", - Action: digest.FromBytes([]byte(desiredTLSInfo.TrustRoot)).String(), - }) - - // If we had reached a converged state, check if we are still converged. - var certsRight, trustRootsRight int64 - for _, n := range nodes { - if bytes.Equal(n.Description.TLSInfo.CertIssuerPublicKey, desiredTLSInfo.CertIssuerPublicKey) && - bytes.Equal(n.Description.TLSInfo.CertIssuerSubject, desiredTLSInfo.CertIssuerSubject) { - certsRight++ - } - - if n.Description.TLSInfo.TrustRoot == desiredTLSInfo.TrustRoot { - trustRootsRight++ - } - } - - total := int64(len(nodes)) - progressOut.WriteProgress(progress.Progress{ - ID: certsRotatedStr, - Action: certsAction, - Current: certsRight, - Total: total, - Units: "nodes", - }) - - rootsProgress := progress.Progress{ - ID: rootsRotatedStr, - Action: rootsAction, - Current: trustRootsRight, - Total: total, - Units: "nodes", - } - - if certsRight == total && !rootRotationInProgress { - progressOut.WriteProgress(rootsProgress) - return certsRight == total && trustRootsRight == total - } - - // we still have certs that need renewing, so display that there are zero roots rotated yet - rootsProgress.Current = 0 - progressOut.WriteProgress(rootsProgress) - return false -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/unlock.go b/vendor/github.com/docker/cli/cli/command/swarm/unlock.go deleted file mode 100644 index dd999a7f4b..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/unlock.go +++ /dev/null @@ -1,78 +0,0 @@ -package swarm - -import ( - "bufio" - "fmt" - "io" - "strings" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/crypto/ssh/terminal" - "golang.org/x/net/context" -) - -type unlockOptions struct{} - -func newUnlockCommand(dockerCli command.Cli) *cobra.Command { - opts := unlockOptions{} - - cmd := &cobra.Command{ - Use: "unlock", - Short: "Unlock swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runUnlock(dockerCli, opts) - }, - } - - return cmd -} - -func runUnlock(dockerCli command.Cli, opts unlockOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - // First see if the node is actually part of a swarm, and if it is actually locked first. - // If it's in any other state than locked, don't ask for the key. - info, err := client.Info(ctx) - if err != nil { - return err - } - - switch info.Swarm.LocalNodeState { - case swarm.LocalNodeStateInactive: - return errors.New("Error: This node is not part of a swarm") - case swarm.LocalNodeStateLocked: - break - default: - return errors.New("Error: swarm is not locked") - } - - key, err := readKey(dockerCli.In(), "Please enter unlock key: ") - if err != nil { - return err - } - req := swarm.UnlockRequest{ - UnlockKey: key, - } - - return client.SwarmUnlock(ctx, req) -} - -func readKey(in *command.InStream, prompt string) (string, error) { - if in.IsTerminal() { - fmt.Print(prompt) - dt, err := terminal.ReadPassword(int(in.FD())) - fmt.Println() - return string(dt), err - } - key, err := bufio.NewReader(in).ReadString('\n') - if err == io.EOF { - err = nil - } - return strings.TrimSpace(key), err -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/unlock_key.go b/vendor/github.com/docker/cli/cli/command/swarm/unlock_key.go deleted file mode 100644 index 4618de7dea..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/unlock_key.go +++ /dev/null @@ -1,89 +0,0 @@ -package swarm - -import ( - "fmt" - "io" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "golang.org/x/net/context" -) - -type unlockKeyOptions struct { - rotate bool - quiet bool -} - -func newUnlockKeyCommand(dockerCli command.Cli) *cobra.Command { - opts := unlockKeyOptions{} - - cmd := &cobra.Command{ - Use: "unlock-key [OPTIONS]", - Short: "Manage the unlock key", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runUnlockKey(dockerCli, opts) - }, - } - - flags := cmd.Flags() - flags.BoolVar(&opts.rotate, flagRotate, false, "Rotate unlock key") - flags.BoolVarP(&opts.quiet, flagQuiet, "q", false, "Only display token") - - return cmd -} - -func runUnlockKey(dockerCli command.Cli, opts unlockKeyOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - if opts.rotate { - flags := swarm.UpdateFlags{RotateManagerUnlockKey: true} - - sw, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - if !sw.Spec.EncryptionConfig.AutoLockManagers { - return errors.New("cannot rotate because autolock is not turned on") - } - - if err := client.SwarmUpdate(ctx, sw.Version, sw.Spec, flags); err != nil { - return err - } - - if !opts.quiet { - fmt.Fprintf(dockerCli.Out(), "Successfully rotated manager unlock key.\n\n") - } - } - - unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) - if err != nil { - return errors.Wrap(err, "could not fetch unlock key") - } - - if unlockKeyResp.UnlockKey == "" { - return errors.New("no unlock key is set") - } - - if opts.quiet { - fmt.Fprintln(dockerCli.Out(), unlockKeyResp.UnlockKey) - return nil - } - - printUnlockCommand(dockerCli.Out(), unlockKeyResp.UnlockKey) - return nil -} - -func printUnlockCommand(out io.Writer, unlockKey string) { - if len(unlockKey) > 0 { - fmt.Fprintf(out, "To unlock a swarm manager after it restarts, "+ - "run the `docker swarm unlock`\ncommand and provide the following key:\n\n %s\n\n"+ - "Please remember to store this key in a password manager, since without it you\n"+ - "will not be able to restart the manager.\n", unlockKey) - } -} diff --git a/vendor/github.com/docker/cli/cli/command/swarm/update.go b/vendor/github.com/docker/cli/cli/command/swarm/update.go deleted file mode 100644 index 4d751bbd4e..0000000000 --- a/vendor/github.com/docker/cli/cli/command/swarm/update.go +++ /dev/null @@ -1,72 +0,0 @@ -package swarm - -import ( - "fmt" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli" - "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/swarm" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func newUpdateCommand(dockerCli command.Cli) *cobra.Command { - opts := swarmOptions{} - - cmd := &cobra.Command{ - Use: "update [OPTIONS]", - Short: "Update the swarm", - Args: cli.NoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return runUpdate(dockerCli, cmd.Flags(), opts) - }, - PreRunE: func(cmd *cobra.Command, args []string) error { - if cmd.Flags().NFlag() == 0 { - return pflag.ErrHelp - } - return nil - }, - } - - cmd.Flags().BoolVar(&opts.autolock, flagAutolock, false, "Change manager autolocking setting (true|false)") - addSwarmFlags(cmd.Flags(), &opts) - return cmd -} - -func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, opts swarmOptions) error { - client := dockerCli.Client() - ctx := context.Background() - - var updateFlags swarm.UpdateFlags - - swarmInspect, err := client.SwarmInspect(ctx) - if err != nil { - return err - } - - prevAutoLock := swarmInspect.Spec.EncryptionConfig.AutoLockManagers - - opts.mergeSwarmSpec(&swarmInspect.Spec, flags) - - curAutoLock := swarmInspect.Spec.EncryptionConfig.AutoLockManagers - - err = client.SwarmUpdate(ctx, swarmInspect.Version, swarmInspect.Spec, updateFlags) - if err != nil { - return err - } - - fmt.Fprintln(dockerCli.Out(), "Swarm updated.") - - if curAutoLock && !prevAutoLock { - unlockKeyResp, err := client.SwarmGetUnlockKey(ctx) - if err != nil { - return errors.Wrap(err, "could not fetch unlock key") - } - printUnlockCommand(dockerCli.Out(), unlockKeyResp.UnlockKey) - } - - return nil -} diff --git a/vendor/github.com/docker/cli/cli/command/task/print.go b/vendor/github.com/docker/cli/cli/command/task/print.go deleted file mode 100644 index 2376ecf803..0000000000 --- a/vendor/github.com/docker/cli/cli/command/task/print.go +++ /dev/null @@ -1,84 +0,0 @@ -package task - -import ( - "fmt" - "sort" - - "golang.org/x/net/context" - - "github.com/docker/cli/cli/command" - "github.com/docker/cli/cli/command/formatter" - "github.com/docker/cli/cli/command/idresolver" - "github.com/docker/docker/api/types/swarm" -) - -type tasksBySlot []swarm.Task - -func (t tasksBySlot) Len() int { - return len(t) -} - -func (t tasksBySlot) Swap(i, j int) { - t[i], t[j] = t[j], t[i] -} - -func (t tasksBySlot) Less(i, j int) bool { - // Sort by slot. - if t[i].Slot != t[j].Slot { - return t[i].Slot < t[j].Slot - } - - // If same slot, sort by most recent. - return t[j].Meta.CreatedAt.Before(t[i].CreatedAt) -} - -// Print task information in a format. -// Besides this, command `docker node ps ` -// and `docker stack ps` will call this, too. -func Print(ctx context.Context, dockerCli command.Cli, tasks []swarm.Task, resolver *idresolver.IDResolver, trunc, quiet bool, format string) error { - sort.Stable(tasksBySlot(tasks)) - - names := map[string]string{} - nodes := map[string]string{} - - tasksCtx := formatter.Context{ - Output: dockerCli.Out(), - Format: formatter.NewTaskFormat(format, quiet), - Trunc: trunc, - } - - prevName := "" - for _, task := range tasks { - serviceName, err := resolver.Resolve(ctx, swarm.Service{}, task.ServiceID) - if err != nil { - return err - } - - nodeValue, err := resolver.Resolve(ctx, swarm.Node{}, task.NodeID) - if err != nil { - return err - } - - var name string - if task.Slot != 0 { - name = fmt.Sprintf("%v.%v", serviceName, task.Slot) - } else { - name = fmt.Sprintf("%v.%v", serviceName, task.NodeID) - } - - // Indent the name if necessary - indentedName := name - if name == prevName { - indentedName = fmt.Sprintf(" \\_ %s", indentedName) - } - prevName = name - - names[task.ID] = name - if tasksCtx.Format.IsTable() { - names[task.ID] = indentedName - } - nodes[task.ID] = nodeValue - } - - return formatter.TaskWrite(tasksCtx, tasks, names, nodes) -} diff --git a/vendor/github.com/docker/cli/cli/compose/convert/compose.go b/vendor/github.com/docker/cli/cli/compose/convert/compose.go deleted file mode 100644 index 02b1dccb6a..0000000000 --- a/vendor/github.com/docker/cli/cli/compose/convert/compose.go +++ /dev/null @@ -1,142 +0,0 @@ -package convert - -import ( - "io/ioutil" - "strings" - - composetypes "github.com/docker/cli/cli/compose/types" - "github.com/docker/docker/api/types" - networktypes "github.com/docker/docker/api/types/network" - "github.com/docker/docker/api/types/swarm" -) - -const ( - // LabelNamespace is the label used to track stack resources - LabelNamespace = "com.docker.stack.namespace" -) - -// Namespace mangles names by prepending the name -type Namespace struct { - name string -} - -// Scope prepends the namespace to a name -func (n Namespace) Scope(name string) string { - return n.name + "_" + name -} - -// Descope returns the name without the namespace prefix -func (n Namespace) Descope(name string) string { - return strings.TrimPrefix(name, n.name+"_") -} - -// Name returns the name of the namespace -func (n Namespace) Name() string { - return n.name -} - -// NewNamespace returns a new Namespace for scoping of names -func NewNamespace(name string) Namespace { - return Namespace{name: name} -} - -// AddStackLabel returns labels with the namespace label added -func AddStackLabel(namespace Namespace, labels map[string]string) map[string]string { - if labels == nil { - labels = make(map[string]string) - } - labels[LabelNamespace] = namespace.name - return labels -} - -type networkMap map[string]composetypes.NetworkConfig - -// Networks from the compose-file type to the engine API type -func Networks(namespace Namespace, networks networkMap, servicesNetworks map[string]struct{}) (map[string]types.NetworkCreate, []string) { - if networks == nil { - networks = make(map[string]composetypes.NetworkConfig) - } - - externalNetworks := []string{} - result := make(map[string]types.NetworkCreate) - for internalName := range servicesNetworks { - network := networks[internalName] - if network.External.External { - externalNetworks = append(externalNetworks, network.External.Name) - continue - } - - createOpts := types.NetworkCreate{ - Labels: AddStackLabel(namespace, network.Labels), - Driver: network.Driver, - Options: network.DriverOpts, - Internal: network.Internal, - Attachable: network.Attachable, - } - - if network.Ipam.Driver != "" || len(network.Ipam.Config) > 0 { - createOpts.IPAM = &networktypes.IPAM{} - } - - if network.Ipam.Driver != "" { - createOpts.IPAM.Driver = network.Ipam.Driver - } - for _, ipamConfig := range network.Ipam.Config { - config := networktypes.IPAMConfig{ - Subnet: ipamConfig.Subnet, - } - createOpts.IPAM.Config = append(createOpts.IPAM.Config, config) - } - result[internalName] = createOpts - } - - return result, externalNetworks -} - -// Secrets converts secrets from the Compose type to the engine API type -func Secrets(namespace Namespace, secrets map[string]composetypes.SecretConfig) ([]swarm.SecretSpec, error) { - result := []swarm.SecretSpec{} - for name, secret := range secrets { - if secret.External.External { - continue - } - - data, err := ioutil.ReadFile(secret.File) - if err != nil { - return nil, err - } - - result = append(result, swarm.SecretSpec{ - Annotations: swarm.Annotations{ - Name: namespace.Scope(name), - Labels: AddStackLabel(namespace, secret.Labels), - }, - Data: data, - }) - } - return result, nil -} - -// Configs converts config objects from the Compose type to the engine API type -func Configs(namespace Namespace, configs map[string]composetypes.ConfigObjConfig) ([]swarm.ConfigSpec, error) { - result := []swarm.ConfigSpec{} - for name, config := range configs { - if config.External.External { - continue - } - - data, err := ioutil.ReadFile(config.File) - if err != nil { - return nil, err - } - - result = append(result, swarm.ConfigSpec{ - Annotations: swarm.Annotations{ - Name: namespace.Scope(name), - Labels: AddStackLabel(namespace, config.Labels), - }, - Data: data, - }) - } - return result, nil -} diff --git a/vendor/github.com/docker/cli/cli/compose/convert/service.go b/vendor/github.com/docker/cli/cli/compose/convert/service.go deleted file mode 100644 index 730f5e1ee5..0000000000 --- a/vendor/github.com/docker/cli/cli/compose/convert/service.go +++ /dev/null @@ -1,568 +0,0 @@ -package convert - -import ( - "fmt" - "os" - "sort" - "strings" - "time" - - servicecli "github.com/docker/cli/cli/command/service" - composetypes "github.com/docker/cli/cli/compose/types" - "github.com/docker/cli/opts" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/swarm" - "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/client" - "github.com/pkg/errors" -) - -const ( - defaultNetwork = "default" - // LabelImage is the label used to store image name provided in the compose file - LabelImage = "com.docker.stack.image" -) - -// Services from compose-file types to engine API types -func Services( - namespace Namespace, - config *composetypes.Config, - client client.CommonAPIClient, -) (map[string]swarm.ServiceSpec, error) { - result := make(map[string]swarm.ServiceSpec) - - services := config.Services - volumes := config.Volumes - networks := config.Networks - - for _, service := range services { - secrets, err := convertServiceSecrets(client, namespace, service.Secrets, config.Secrets) - if err != nil { - return nil, errors.Wrapf(err, "service %s", service.Name) - } - configs, err := convertServiceConfigObjs(client, namespace, service.Configs, config.Configs) - if err != nil { - return nil, errors.Wrapf(err, "service %s", service.Name) - } - - serviceSpec, err := Service(client.ClientVersion(), namespace, service, networks, volumes, secrets, configs) - if err != nil { - return nil, errors.Wrapf(err, "service %s", service.Name) - } - result[service.Name] = serviceSpec - } - - return result, nil -} - -// Service converts a ServiceConfig into a swarm ServiceSpec -func Service( - apiVersion string, - namespace Namespace, - service composetypes.ServiceConfig, - networkConfigs map[string]composetypes.NetworkConfig, - volumes map[string]composetypes.VolumeConfig, - secrets []*swarm.SecretReference, - configs []*swarm.ConfigReference, -) (swarm.ServiceSpec, error) { - name := namespace.Scope(service.Name) - - endpoint, err := convertEndpointSpec(service.Deploy.EndpointMode, service.Ports) - if err != nil { - return swarm.ServiceSpec{}, err - } - - mode, err := convertDeployMode(service.Deploy.Mode, service.Deploy.Replicas) - if err != nil { - return swarm.ServiceSpec{}, err - } - - mounts, err := Volumes(service.Volumes, volumes, namespace) - if err != nil { - return swarm.ServiceSpec{}, err - } - - resources, err := convertResources(service.Deploy.Resources) - if err != nil { - return swarm.ServiceSpec{}, err - } - - restartPolicy, err := convertRestartPolicy( - service.Restart, service.Deploy.RestartPolicy) - if err != nil { - return swarm.ServiceSpec{}, err - } - - healthcheck, err := convertHealthcheck(service.HealthCheck) - if err != nil { - return swarm.ServiceSpec{}, err - } - - networks, err := convertServiceNetworks(service.Networks, networkConfigs, namespace, service.Name) - if err != nil { - return swarm.ServiceSpec{}, err - } - - dnsConfig, err := convertDNSConfig(service.DNS, service.DNSSearch) - if err != nil { - return swarm.ServiceSpec{}, err - } - - var privileges swarm.Privileges - privileges.CredentialSpec, err = convertCredentialSpec(service.CredentialSpec) - if err != nil { - return swarm.ServiceSpec{}, err - } - - var logDriver *swarm.Driver - if service.Logging != nil { - logDriver = &swarm.Driver{ - Name: service.Logging.Driver, - Options: service.Logging.Options, - } - } - - serviceSpec := swarm.ServiceSpec{ - Annotations: swarm.Annotations{ - Name: name, - Labels: AddStackLabel(namespace, service.Deploy.Labels), - }, - TaskTemplate: swarm.TaskSpec{ - ContainerSpec: swarm.ContainerSpec{ - Image: service.Image, - Command: service.Entrypoint, - Args: service.Command, - Hostname: service.Hostname, - Hosts: sortStrings(convertExtraHosts(service.ExtraHosts)), - DNSConfig: dnsConfig, - Healthcheck: healthcheck, - Env: sortStrings(convertEnvironment(service.Environment)), - Labels: AddStackLabel(namespace, service.Labels), - Dir: service.WorkingDir, - User: service.User, - Mounts: mounts, - StopGracePeriod: service.StopGracePeriod, - TTY: service.Tty, - OpenStdin: service.StdinOpen, - Secrets: secrets, - Configs: configs, - ReadOnly: service.ReadOnly, - Privileges: &privileges, - }, - LogDriver: logDriver, - Resources: resources, - RestartPolicy: restartPolicy, - Placement: &swarm.Placement{ - Constraints: service.Deploy.Placement.Constraints, - Preferences: getPlacementPreference(service.Deploy.Placement.Preferences), - }, - }, - EndpointSpec: endpoint, - Mode: mode, - UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig), - } - - // add an image label to serviceSpec - serviceSpec.Labels[LabelImage] = service.Image - - // ServiceSpec.Networks is deprecated and should not have been used by - // this package. It is possible to update TaskTemplate.Networks, but it - // is not possible to update ServiceSpec.Networks. Unfortunately, we - // can't unconditionally start using TaskTemplate.Networks, because that - // will break with older daemons that don't support migrating from - // ServiceSpec.Networks to TaskTemplate.Networks. So which field to use - // is conditional on daemon version. - if versions.LessThan(apiVersion, "1.29") { - serviceSpec.Networks = networks - } else { - serviceSpec.TaskTemplate.Networks = networks - } - return serviceSpec, nil -} - -func getPlacementPreference(preferences []composetypes.PlacementPreferences) []swarm.PlacementPreference { - result := []swarm.PlacementPreference{} - for _, preference := range preferences { - spreadDescriptor := preference.Spread - result = append(result, swarm.PlacementPreference{ - Spread: &swarm.SpreadOver{ - SpreadDescriptor: spreadDescriptor, - }, - }) - } - return result -} - -func sortStrings(strs []string) []string { - sort.Strings(strs) - return strs -} - -type byNetworkTarget []swarm.NetworkAttachmentConfig - -func (a byNetworkTarget) Len() int { return len(a) } -func (a byNetworkTarget) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byNetworkTarget) Less(i, j int) bool { return a[i].Target < a[j].Target } - -func convertServiceNetworks( - networks map[string]*composetypes.ServiceNetworkConfig, - networkConfigs networkMap, - namespace Namespace, - name string, -) ([]swarm.NetworkAttachmentConfig, error) { - if len(networks) == 0 { - networks = map[string]*composetypes.ServiceNetworkConfig{ - defaultNetwork: {}, - } - } - - nets := []swarm.NetworkAttachmentConfig{} - for networkName, network := range networks { - networkConfig, ok := networkConfigs[networkName] - if !ok && networkName != defaultNetwork { - return nil, errors.Errorf("undefined network %q", networkName) - } - var aliases []string - if network != nil { - aliases = network.Aliases - } - target := namespace.Scope(networkName) - if networkConfig.External.External { - target = networkConfig.External.Name - } - netAttachConfig := swarm.NetworkAttachmentConfig{ - Target: target, - Aliases: aliases, - } - // Only add default aliases to user defined networks. Other networks do - // not support aliases. - if container.NetworkMode(target).IsUserDefined() { - netAttachConfig.Aliases = append(netAttachConfig.Aliases, name) - } - nets = append(nets, netAttachConfig) - } - - sort.Sort(byNetworkTarget(nets)) - return nets, nil -} - -// TODO: fix secrets API so that SecretAPIClient is not required here -func convertServiceSecrets( - client client.SecretAPIClient, - namespace Namespace, - secrets []composetypes.ServiceSecretConfig, - secretSpecs map[string]composetypes.SecretConfig, -) ([]*swarm.SecretReference, error) { - refs := []*swarm.SecretReference{} - for _, secret := range secrets { - target := secret.Target - if target == "" { - target = secret.Source - } - - secretSpec, exists := secretSpecs[secret.Source] - if !exists { - return nil, errors.Errorf("undefined secret %q", secret.Source) - } - - source := namespace.Scope(secret.Source) - if secretSpec.External.External { - source = secretSpec.External.Name - } - - uid := secret.UID - gid := secret.GID - if uid == "" { - uid = "0" - } - if gid == "" { - gid = "0" - } - mode := secret.Mode - if mode == nil { - mode = uint32Ptr(0444) - } - - refs = append(refs, &swarm.SecretReference{ - File: &swarm.SecretReferenceFileTarget{ - Name: target, - UID: uid, - GID: gid, - Mode: os.FileMode(*mode), - }, - SecretName: source, - }) - } - - return servicecli.ParseSecrets(client, refs) -} - -// TODO: fix configs API so that ConfigsAPIClient is not required here -func convertServiceConfigObjs( - client client.ConfigAPIClient, - namespace Namespace, - configs []composetypes.ServiceConfigObjConfig, - configSpecs map[string]composetypes.ConfigObjConfig, -) ([]*swarm.ConfigReference, error) { - refs := []*swarm.ConfigReference{} - for _, config := range configs { - target := config.Target - if target == "" { - target = config.Source - } - - configSpec, exists := configSpecs[config.Source] - if !exists { - return nil, errors.Errorf("undefined config %q", config.Source) - } - - source := namespace.Scope(config.Source) - if configSpec.External.External { - source = configSpec.External.Name - } - - uid := config.UID - gid := config.GID - if uid == "" { - uid = "0" - } - if gid == "" { - gid = "0" - } - mode := config.Mode - if mode == nil { - mode = uint32Ptr(0444) - } - - refs = append(refs, &swarm.ConfigReference{ - File: &swarm.ConfigReferenceFileTarget{ - Name: target, - UID: uid, - GID: gid, - Mode: os.FileMode(*mode), - }, - ConfigName: source, - }) - } - - return servicecli.ParseConfigs(client, refs) -} - -func uint32Ptr(value uint32) *uint32 { - return &value -} - -func convertExtraHosts(extraHosts map[string]string) []string { - hosts := []string{} - for host, ip := range extraHosts { - hosts = append(hosts, fmt.Sprintf("%s %s", ip, host)) - } - return hosts -} - -func convertHealthcheck(healthcheck *composetypes.HealthCheckConfig) (*container.HealthConfig, error) { - if healthcheck == nil { - return nil, nil - } - var ( - err error - timeout, interval, startPeriod time.Duration - retries int - ) - if healthcheck.Disable { - if len(healthcheck.Test) != 0 { - return nil, errors.Errorf("test and disable can't be set at the same time") - } - return &container.HealthConfig{ - Test: []string{"NONE"}, - }, nil - - } - if healthcheck.Timeout != "" { - timeout, err = time.ParseDuration(healthcheck.Timeout) - if err != nil { - return nil, err - } - } - if healthcheck.Interval != "" { - interval, err = time.ParseDuration(healthcheck.Interval) - if err != nil { - return nil, err - } - } - if healthcheck.StartPeriod != "" { - startPeriod, err = time.ParseDuration(healthcheck.StartPeriod) - if err != nil { - return nil, err - } - } - if healthcheck.Retries != nil { - retries = int(*healthcheck.Retries) - } - return &container.HealthConfig{ - Test: healthcheck.Test, - Timeout: timeout, - Interval: interval, - Retries: retries, - StartPeriod: startPeriod, - }, nil -} - -func convertRestartPolicy(restart string, source *composetypes.RestartPolicy) (*swarm.RestartPolicy, error) { - // TODO: log if restart is being ignored - if source == nil { - policy, err := opts.ParseRestartPolicy(restart) - if err != nil { - return nil, err - } - switch { - case policy.IsNone(): - return nil, nil - case policy.IsAlways(), policy.IsUnlessStopped(): - return &swarm.RestartPolicy{ - Condition: swarm.RestartPolicyConditionAny, - }, nil - case policy.IsOnFailure(): - attempts := uint64(policy.MaximumRetryCount) - return &swarm.RestartPolicy{ - Condition: swarm.RestartPolicyConditionOnFailure, - MaxAttempts: &attempts, - }, nil - default: - return nil, errors.Errorf("unknown restart policy: %s", restart) - } - } - return &swarm.RestartPolicy{ - Condition: swarm.RestartPolicyCondition(source.Condition), - Delay: source.Delay, - MaxAttempts: source.MaxAttempts, - Window: source.Window, - }, nil -} - -func convertUpdateConfig(source *composetypes.UpdateConfig) *swarm.UpdateConfig { - if source == nil { - return nil - } - parallel := uint64(1) - if source.Parallelism != nil { - parallel = *source.Parallelism - } - return &swarm.UpdateConfig{ - Parallelism: parallel, - Delay: source.Delay, - FailureAction: source.FailureAction, - Monitor: source.Monitor, - MaxFailureRatio: source.MaxFailureRatio, - } -} - -func convertResources(source composetypes.Resources) (*swarm.ResourceRequirements, error) { - resources := &swarm.ResourceRequirements{} - var err error - if source.Limits != nil { - var cpus int64 - if source.Limits.NanoCPUs != "" { - cpus, err = opts.ParseCPUs(source.Limits.NanoCPUs) - if err != nil { - return nil, err - } - } - resources.Limits = &swarm.Resources{ - NanoCPUs: cpus, - MemoryBytes: int64(source.Limits.MemoryBytes), - } - } - if source.Reservations != nil { - var cpus int64 - if source.Reservations.NanoCPUs != "" { - cpus, err = opts.ParseCPUs(source.Reservations.NanoCPUs) - if err != nil { - return nil, err - } - } - resources.Reservations = &swarm.Resources{ - NanoCPUs: cpus, - MemoryBytes: int64(source.Reservations.MemoryBytes), - } - } - return resources, nil -} - -type byPublishedPort []swarm.PortConfig - -func (a byPublishedPort) Len() int { return len(a) } -func (a byPublishedPort) Swap(i, j int) { a[i], a[j] = a[j], a[i] } -func (a byPublishedPort) Less(i, j int) bool { return a[i].PublishedPort < a[j].PublishedPort } - -func convertEndpointSpec(endpointMode string, source []composetypes.ServicePortConfig) (*swarm.EndpointSpec, error) { - portConfigs := []swarm.PortConfig{} - for _, port := range source { - portConfig := swarm.PortConfig{ - Protocol: swarm.PortConfigProtocol(port.Protocol), - TargetPort: port.Target, - PublishedPort: port.Published, - PublishMode: swarm.PortConfigPublishMode(port.Mode), - } - portConfigs = append(portConfigs, portConfig) - } - - sort.Sort(byPublishedPort(portConfigs)) - return &swarm.EndpointSpec{ - Mode: swarm.ResolutionMode(strings.ToLower(endpointMode)), - Ports: portConfigs, - }, nil -} - -func convertEnvironment(source map[string]*string) []string { - var output []string - - for name, value := range source { - switch value { - case nil: - output = append(output, name) - default: - output = append(output, fmt.Sprintf("%s=%s", name, *value)) - } - } - - return output -} - -func convertDeployMode(mode string, replicas *uint64) (swarm.ServiceMode, error) { - serviceMode := swarm.ServiceMode{} - - switch mode { - case "global": - if replicas != nil { - return serviceMode, errors.Errorf("replicas can only be used with replicated mode") - } - serviceMode.Global = &swarm.GlobalService{} - case "replicated", "": - serviceMode.Replicated = &swarm.ReplicatedService{Replicas: replicas} - default: - return serviceMode, errors.Errorf("Unknown mode: %s", mode) - } - return serviceMode, nil -} - -func convertDNSConfig(DNS []string, DNSSearch []string) (*swarm.DNSConfig, error) { - if DNS != nil || DNSSearch != nil { - return &swarm.DNSConfig{ - Nameservers: DNS, - Search: DNSSearch, - }, nil - } - return nil, nil -} - -func convertCredentialSpec(spec composetypes.CredentialSpecConfig) (*swarm.CredentialSpec, error) { - if spec.File == "" && spec.Registry == "" { - return nil, nil - } - if spec.File != "" && spec.Registry != "" { - return nil, errors.New("Invalid credential spec - must provide one of `File` or `Registry`") - } - swarmCredSpec := swarm.CredentialSpec(spec) - return &swarmCredSpec, nil -} diff --git a/vendor/github.com/docker/cli/cli/compose/convert/volume.go b/vendor/github.com/docker/cli/cli/compose/convert/volume.go deleted file mode 100644 index e767b07ee9..0000000000 --- a/vendor/github.com/docker/cli/cli/compose/convert/volume.go +++ /dev/null @@ -1,87 +0,0 @@ -package convert - -import ( - composetypes "github.com/docker/cli/cli/compose/types" - "github.com/docker/docker/api/types/mount" - "github.com/pkg/errors" -) - -type volumes map[string]composetypes.VolumeConfig - -// Volumes from compose-file types to engine api types -func Volumes(serviceVolumes []composetypes.ServiceVolumeConfig, stackVolumes volumes, namespace Namespace) ([]mount.Mount, error) { - var mounts []mount.Mount - - for _, volumeConfig := range serviceVolumes { - mount, err := convertVolumeToMount(volumeConfig, stackVolumes, namespace) - if err != nil { - return nil, err - } - mounts = append(mounts, mount) - } - return mounts, nil -} - -func convertVolumeToMount( - volume composetypes.ServiceVolumeConfig, - stackVolumes volumes, - namespace Namespace, -) (mount.Mount, error) { - result := mount.Mount{ - Type: mount.Type(volume.Type), - Source: volume.Source, - Target: volume.Target, - ReadOnly: volume.ReadOnly, - Consistency: mount.Consistency(volume.Consistency), - } - - // Anonymous volumes - if volume.Source == "" { - return result, nil - } - if volume.Type == "volume" && volume.Bind != nil { - return result, errors.New("bind options are incompatible with type volume") - } - if volume.Type == "bind" && volume.Volume != nil { - return result, errors.New("volume options are incompatible with type bind") - } - - if volume.Bind != nil { - result.BindOptions = &mount.BindOptions{ - Propagation: mount.Propagation(volume.Bind.Propagation), - } - } - // Binds volumes - if volume.Type == "bind" { - return result, nil - } - - stackVolume, exists := stackVolumes[volume.Source] - if !exists { - return result, errors.Errorf("undefined volume %q", volume.Source) - } - - result.Source = namespace.Scope(volume.Source) - result.VolumeOptions = &mount.VolumeOptions{} - - if volume.Volume != nil { - result.VolumeOptions.NoCopy = volume.Volume.NoCopy - } - - // External named volumes - if stackVolume.External.External { - result.Source = stackVolume.External.Name - return result, nil - } - - result.VolumeOptions.Labels = AddStackLabel(namespace, stackVolume.Labels) - if stackVolume.Driver != "" || stackVolume.DriverOpts != nil { - result.VolumeOptions.DriverConfig = &mount.Driver{ - Name: stackVolume.Driver, - Options: stackVolume.DriverOpts, - } - } - - // Named volumes - return result, nil -} diff --git a/vendor/github.com/flynn-archive/go-shlex/COPYING b/vendor/github.com/flynn-archive/go-shlex/COPYING deleted file mode 100644 index d645695673..0000000000 --- a/vendor/github.com/flynn-archive/go-shlex/COPYING +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/github.com/flynn-archive/go-shlex/README.md b/vendor/github.com/flynn-archive/go-shlex/README.md deleted file mode 100644 index c86bcc066f..0000000000 --- a/vendor/github.com/flynn-archive/go-shlex/README.md +++ /dev/null @@ -1,2 +0,0 @@ -go-shlex is a simple lexer for go that supports shell-style quoting, -commenting, and escaping. diff --git a/vendor/github.com/flynn-archive/go-shlex/shlex.go b/vendor/github.com/flynn-archive/go-shlex/shlex.go deleted file mode 100644 index 7aeace801e..0000000000 --- a/vendor/github.com/flynn-archive/go-shlex/shlex.go +++ /dev/null @@ -1,457 +0,0 @@ -/* -Copyright 2012 Google Inc. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package shlex - -/* -Package shlex implements a simple lexer which splits input in to tokens using -shell-style rules for quoting and commenting. -*/ -import ( - "bufio" - "errors" - "fmt" - "io" - "strings" -) - -/* -A TokenType is a top-level token; a word, space, comment, unknown. -*/ -type TokenType int - -/* -A RuneTokenType is the type of a UTF-8 character; a character, quote, space, escape. -*/ -type RuneTokenType int - -type lexerState int - -type Token struct { - tokenType TokenType - value string -} - -/* -Two tokens are equal if both their types and values are equal. A nil token can -never equal another token. -*/ -func (a *Token) Equal(b *Token) bool { - if a == nil || b == nil { - return false - } - if a.tokenType != b.tokenType { - return false - } - return a.value == b.value -} - -const ( - RUNE_CHAR string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-,/@$*()+=><:;&^%~|!?[]{}" - RUNE_SPACE string = " \t\r\n" - RUNE_ESCAPING_QUOTE string = "\"" - RUNE_NONESCAPING_QUOTE string = "'" - RUNE_ESCAPE = "\\" - RUNE_COMMENT = "#" - - RUNETOKEN_UNKNOWN RuneTokenType = 0 - RUNETOKEN_CHAR RuneTokenType = 1 - RUNETOKEN_SPACE RuneTokenType = 2 - RUNETOKEN_ESCAPING_QUOTE RuneTokenType = 3 - RUNETOKEN_NONESCAPING_QUOTE RuneTokenType = 4 - RUNETOKEN_ESCAPE RuneTokenType = 5 - RUNETOKEN_COMMENT RuneTokenType = 6 - RUNETOKEN_EOF RuneTokenType = 7 - - TOKEN_UNKNOWN TokenType = 0 - TOKEN_WORD TokenType = 1 - TOKEN_SPACE TokenType = 2 - TOKEN_COMMENT TokenType = 3 - - STATE_START lexerState = 0 - STATE_INWORD lexerState = 1 - STATE_ESCAPING lexerState = 2 - STATE_ESCAPING_QUOTED lexerState = 3 - STATE_QUOTED_ESCAPING lexerState = 4 - STATE_QUOTED lexerState = 5 - STATE_COMMENT lexerState = 6 - - INITIAL_TOKEN_CAPACITY int = 100 -) - -/* -A type for classifying characters. This allows for different sorts of -classifiers - those accepting extended non-ascii chars, or strict posix -compatibility, for example. -*/ -type TokenClassifier struct { - typeMap map[int32]RuneTokenType -} - -func addRuneClass(typeMap *map[int32]RuneTokenType, runes string, tokenType RuneTokenType) { - for _, rune := range runes { - (*typeMap)[int32(rune)] = tokenType - } -} - -/* -Create a new classifier for basic ASCII characters. -*/ -func NewDefaultClassifier() *TokenClassifier { - typeMap := map[int32]RuneTokenType{} - addRuneClass(&typeMap, RUNE_CHAR, RUNETOKEN_CHAR) - addRuneClass(&typeMap, RUNE_SPACE, RUNETOKEN_SPACE) - addRuneClass(&typeMap, RUNE_ESCAPING_QUOTE, RUNETOKEN_ESCAPING_QUOTE) - addRuneClass(&typeMap, RUNE_NONESCAPING_QUOTE, RUNETOKEN_NONESCAPING_QUOTE) - addRuneClass(&typeMap, RUNE_ESCAPE, RUNETOKEN_ESCAPE) - addRuneClass(&typeMap, RUNE_COMMENT, RUNETOKEN_COMMENT) - return &TokenClassifier{ - typeMap: typeMap} -} - -func (classifier *TokenClassifier) ClassifyRune(rune int32) RuneTokenType { - return classifier.typeMap[rune] -} - -/* -A type for turning an input stream in to a sequence of strings. Whitespace and -comments are skipped. -*/ -type Lexer struct { - tokenizer *Tokenizer -} - -/* -Create a new lexer. -*/ -func NewLexer(r io.Reader) (*Lexer, error) { - - tokenizer, err := NewTokenizer(r) - if err != nil { - return nil, err - } - lexer := &Lexer{tokenizer: tokenizer} - return lexer, nil -} - -/* -Return the next word, and an error value. If there are no more words, the error -will be io.EOF. -*/ -func (l *Lexer) NextWord() (string, error) { - var token *Token - var err error - for { - token, err = l.tokenizer.NextToken() - if err != nil { - return "", err - } - switch token.tokenType { - case TOKEN_WORD: - { - return token.value, nil - } - case TOKEN_COMMENT: - { - // skip comments - } - default: - { - panic(fmt.Sprintf("Unknown token type: %v", token.tokenType)) - } - } - } - return "", io.EOF -} - -/* -A type for turning an input stream in to a sequence of typed tokens. -*/ -type Tokenizer struct { - input *bufio.Reader - classifier *TokenClassifier -} - -/* -Create a new tokenizer. -*/ -func NewTokenizer(r io.Reader) (*Tokenizer, error) { - input := bufio.NewReader(r) - classifier := NewDefaultClassifier() - tokenizer := &Tokenizer{ - input: input, - classifier: classifier} - return tokenizer, nil -} - -/* -Scan the stream for the next token. - -This uses an internal state machine. It will panic if it encounters a character -which it does not know how to handle. -*/ -func (t *Tokenizer) scanStream() (*Token, error) { - state := STATE_START - var tokenType TokenType - value := make([]int32, 0, INITIAL_TOKEN_CAPACITY) - var ( - nextRune int32 - nextRuneType RuneTokenType - err error - ) -SCAN: - for { - nextRune, _, err = t.input.ReadRune() - nextRuneType = t.classifier.ClassifyRune(nextRune) - if err != nil { - if err == io.EOF { - nextRuneType = RUNETOKEN_EOF - err = nil - } else { - return nil, err - } - } - switch state { - case STATE_START: // no runes read yet - { - switch nextRuneType { - case RUNETOKEN_EOF: - { - return nil, io.EOF - } - case RUNETOKEN_CHAR: - { - tokenType = TOKEN_WORD - value = append(value, nextRune) - state = STATE_INWORD - } - case RUNETOKEN_SPACE: - { - } - case RUNETOKEN_ESCAPING_QUOTE: - { - tokenType = TOKEN_WORD - state = STATE_QUOTED_ESCAPING - } - case RUNETOKEN_NONESCAPING_QUOTE: - { - tokenType = TOKEN_WORD - state = STATE_QUOTED - } - case RUNETOKEN_ESCAPE: - { - tokenType = TOKEN_WORD - state = STATE_ESCAPING - } - case RUNETOKEN_COMMENT: - { - tokenType = TOKEN_COMMENT - state = STATE_COMMENT - } - default: - { - return nil, errors.New(fmt.Sprintf("Unknown rune: %v", nextRune)) - } - } - } - case STATE_INWORD: // in a regular word - { - switch nextRuneType { - case RUNETOKEN_EOF: - { - break SCAN - } - case RUNETOKEN_CHAR, RUNETOKEN_COMMENT: - { - value = append(value, nextRune) - } - case RUNETOKEN_SPACE: - { - t.input.UnreadRune() - break SCAN - } - case RUNETOKEN_ESCAPING_QUOTE: - { - state = STATE_QUOTED_ESCAPING - } - case RUNETOKEN_NONESCAPING_QUOTE: - { - state = STATE_QUOTED - } - case RUNETOKEN_ESCAPE: - { - state = STATE_ESCAPING - } - default: - { - return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune)) - } - } - } - case STATE_ESCAPING: // the next rune after an escape character - { - switch nextRuneType { - case RUNETOKEN_EOF: - { - err = errors.New("EOF found after escape character") - break SCAN - } - case RUNETOKEN_CHAR, RUNETOKEN_SPACE, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_NONESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT: - { - state = STATE_INWORD - value = append(value, nextRune) - } - default: - { - return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune)) - } - } - } - case STATE_ESCAPING_QUOTED: // the next rune after an escape character, in double quotes - { - switch nextRuneType { - case RUNETOKEN_EOF: - { - err = errors.New("EOF found after escape character") - break SCAN - } - case RUNETOKEN_CHAR, RUNETOKEN_SPACE, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_NONESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT: - { - state = STATE_QUOTED_ESCAPING - value = append(value, nextRune) - } - default: - { - return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune)) - } - } - } - case STATE_QUOTED_ESCAPING: // in escaping double quotes - { - switch nextRuneType { - case RUNETOKEN_EOF: - { - err = errors.New("EOF found when expecting closing quote.") - break SCAN - } - case RUNETOKEN_CHAR, RUNETOKEN_UNKNOWN, RUNETOKEN_SPACE, RUNETOKEN_NONESCAPING_QUOTE, RUNETOKEN_COMMENT: - { - value = append(value, nextRune) - } - case RUNETOKEN_ESCAPING_QUOTE: - { - state = STATE_INWORD - } - case RUNETOKEN_ESCAPE: - { - state = STATE_ESCAPING_QUOTED - } - default: - { - return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune)) - } - } - } - case STATE_QUOTED: // in non-escaping single quotes - { - switch nextRuneType { - case RUNETOKEN_EOF: - { - err = errors.New("EOF found when expecting closing quote.") - break SCAN - } - case RUNETOKEN_CHAR, RUNETOKEN_UNKNOWN, RUNETOKEN_SPACE, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT: - { - value = append(value, nextRune) - } - case RUNETOKEN_NONESCAPING_QUOTE: - { - state = STATE_INWORD - } - default: - { - return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune)) - } - } - } - case STATE_COMMENT: - { - switch nextRuneType { - case RUNETOKEN_EOF: - { - break SCAN - } - case RUNETOKEN_CHAR, RUNETOKEN_UNKNOWN, RUNETOKEN_ESCAPING_QUOTE, RUNETOKEN_ESCAPE, RUNETOKEN_COMMENT, RUNETOKEN_NONESCAPING_QUOTE: - { - value = append(value, nextRune) - } - case RUNETOKEN_SPACE: - { - if nextRune == '\n' { - state = STATE_START - break SCAN - } else { - value = append(value, nextRune) - } - } - default: - { - return nil, errors.New(fmt.Sprintf("Uknown rune: %v", nextRune)) - } - } - } - default: - { - panic(fmt.Sprintf("Unexpected state: %v", state)) - } - } - } - token := &Token{ - tokenType: tokenType, - value: string(value)} - return token, err -} - -/* -Return the next token in the stream, and an error value. If there are no more -tokens available, the error value will be io.EOF. -*/ -func (t *Tokenizer) NextToken() (*Token, error) { - return t.scanStream() -} - -/* -Split a string in to a slice of strings, based upon shell-style rules for -quoting, escaping, and spaces. -*/ -func Split(s string) ([]string, error) { - l, err := NewLexer(strings.NewReader(s)) - if err != nil { - return nil, err - } - subStrings := []string{} - for { - word, err := l.NextWord() - if err != nil { - if err == io.EOF { - return subStrings, nil - } - return subStrings, err - } - subStrings = append(subStrings, word) - } - return subStrings, nil -} diff --git a/vendor/github.com/jhowardmsft/opengcs/LICENSE b/vendor/github.com/jhowardmsft/opengcs/LICENSE deleted file mode 100644 index 8739a025ea..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2017 Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/config.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/config.go deleted file mode 100644 index 49f3e0b1c5..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/config.go +++ /dev/null @@ -1,247 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "encoding/json" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/Microsoft/hcsshim" - "github.com/Sirupsen/logrus" -) - -// Mode is the operational mode, both requested, and actual after verification -type Mode uint - -const ( - // Constants for the actual mode after validation - - // ModeActualError means an error has occurred during validation - ModeActualError = iota - // ModeActualVhdx means that we are going to use VHDX boot after validation - ModeActualVhdx - // ModeActualKernelInitrd means that we are going to use kernel+initrd for boot after validation - ModeActualKernelInitrd - - // Constants for the requested mode - - // ModeRequestAuto means auto-select the boot mode for a utility VM - ModeRequestAuto = iota // VHDX will be priority over kernel+initrd - // ModeRequestVhdx means request VHDX boot if possible - ModeRequestVhdx - // ModeRequestKernelInitrd means request Kernel+initrd boot if possible - ModeRequestKernelInitrd - - // defaultUvmTimeoutSeconds is the default time to wait for utility VM operations - defaultUvmTimeoutSeconds = 5 * 60 - - // DefaultSandboxSizeMB is the size of the default sandbox size in MB - DefaultSandboxSizeMB = 20 * 1024 * 1024 -) - -// Config is the structure used to configuring a utility VM to be used -// as a service VM. There are two ways of starting. Either supply a VHD, -// or a Kernel+Initrd. For the latter, both must be supplied, and both -// must be in the same directory. -// -// VHD is the priority. -type Config struct { - KirdPath string // Path to where kernel/initrd are found (defaults to c:\program files\Linux Containers) - KernelFile string // Kernel for Utility VM (embedded in a UEFI bootloader) - does NOT include full path, just filename - InitrdFile string // Initrd image for Utility VM - does NOT include full path, just filename - Vhdx string // VHD for booting the utility VM - is a full path - Name string // Name of the utility VM - RequestedMode Mode // What mode is preferred when validating - ActualMode Mode // What mode was obtained during validation - UvmTimeoutSeconds int // How long to wait for the utility VM to respond in seconds - Uvm hcsshim.Container // The actual container - MappedVirtualDisks []hcsshim.MappedVirtualDisk // Data-disks to be attached -} - -// GenerateDefault generates a default config from a set of options -// If baseDir is not supplied, defaults to $env:ProgramFiles\Linux Containers -func (config *Config) GenerateDefault(options []string) error { - if config.UvmTimeoutSeconds < 0 { - return fmt.Errorf("opengcs: cannot generate a config when supplied a negative utility VM timeout") - } - - envTimeoutSeconds := 0 - optTimeoutSeconds := 0 - - if config.UvmTimeoutSeconds != 0 { - envTimeout := os.Getenv("OPENGCS_UVM_TIMEOUT_SECONDS") - if len(envTimeout) > 0 { - var err error - if envTimeoutSeconds, err = strconv.Atoi(envTimeout); err != nil { - return fmt.Errorf("opengcs: OPENGCS_UVM_TIMEOUT_SECONDS could not be interpreted as an integer") - } - if envTimeoutSeconds < 0 { - return fmt.Errorf("opengcs: OPENGCS_UVM_TIMEOUT_SECONDS cannot be negative") - } - } - } - - for _, v := range options { - opt := strings.SplitN(v, "=", 2) - if len(opt) == 2 { - switch strings.ToLower(opt[0]) { - case "opengcskirdpath": - config.KirdPath = opt[1] - case "opengcskernel": - config.KernelFile = opt[1] - case "opengcsinitrd": - config.InitrdFile = opt[1] - case "opengcsvhdx": - config.Vhdx = opt[1] - case "opengcstimeoutsecs": - var err error - if optTimeoutSeconds, err = strconv.Atoi(opt[1]); err != nil { - return fmt.Errorf("opengcs: opengcstimeoutsecs option could not be interpreted as an integer") - } - if optTimeoutSeconds < 0 { - return fmt.Errorf("opengcs: opengcstimeoutsecs option cannot be negative") - } - } - } - } - - if config.KirdPath == "" { - config.KirdPath = filepath.Join(os.Getenv("ProgramFiles"), "Linux Containers") - } - - if config.Vhdx == "" { - config.Vhdx = filepath.Join(config.KirdPath, `uvm.vhdx`) - } - if config.KernelFile == "" { - config.KernelFile = `bootx64.efi` - } - if config.InitrdFile == "" { - config.InitrdFile = `initrd.img` - } - - // Which timeout are we going to take? If not through option or environment, - // then use the default constant, otherwise the maximum of the option or - // environment supplied setting. A requested on in the config supplied - // overrides all of this. - if config.UvmTimeoutSeconds == 0 { - config.UvmTimeoutSeconds = defaultUvmTimeoutSeconds - if optTimeoutSeconds != 0 || envTimeoutSeconds != 0 { - config.UvmTimeoutSeconds = optTimeoutSeconds - if envTimeoutSeconds > optTimeoutSeconds { - config.UvmTimeoutSeconds = envTimeoutSeconds - } - } - } - - config.MappedVirtualDisks = nil - - return nil -} - -// validate validates a Config structure for starting a utility VM. -func (config *Config) validate() error { - config.ActualMode = ModeActualError - - if config.RequestedMode == ModeRequestVhdx && config.Vhdx == "" { - return fmt.Errorf("opengcs: config is invalid - request for VHDX mode did not supply a VHDX") - } - if config.RequestedMode == ModeRequestKernelInitrd && (config.KernelFile == "" || config.InitrdFile == "") { - return fmt.Errorf("opengcs: config is invalid - request for Kernel+Initrd mode must supply both kernel and initrd") - } - - // Validate that if VHDX requested or auto, it exists. - if config.RequestedMode == ModeRequestAuto || config.RequestedMode == ModeRequestVhdx { - if _, err := os.Stat(config.Vhdx); os.IsNotExist(err) { - if config.RequestedMode == ModeRequestVhdx { - return fmt.Errorf("opengcs: mode requested was VHDX but '%s' could not be found", config.Vhdx) - } - } else { - config.ActualMode = ModeActualVhdx - return nil - } - } - - // So must be kernel+initrd, or auto where we fallback as the VHDX doesn't exist - if config.InitrdFile == "" || config.KernelFile == "" { - if config.RequestedMode == ModeRequestKernelInitrd { - return fmt.Errorf("opengcs: both initrd and kernel options for utility VM boot must be supplied") - } - return fmt.Errorf("opengcs: configuration is invalid") - } - - if _, err := os.Stat(filepath.Join(config.KirdPath, config.KernelFile)); os.IsNotExist(err) { - return fmt.Errorf("opengcs: kernel '%s' was not found", filepath.Join(config.KirdPath, config.KernelFile)) - } - if _, err := os.Stat(filepath.Join(config.KirdPath, config.InitrdFile)); os.IsNotExist(err) { - return fmt.Errorf("opengcs: initrd '%s' was not found", filepath.Join(config.KirdPath, config.InitrdFile)) - } - - config.ActualMode = ModeActualKernelInitrd - - // Ensure all the MappedVirtualDisks exist on the host - for _, mvd := range config.MappedVirtualDisks { - if _, err := os.Stat(mvd.HostPath); err != nil { - return fmt.Errorf("opengcs: MappedVirtualDisk '%s' was not found", mvd.HostPath) - } - if mvd.ContainerPath == "" { - return fmt.Errorf("opengcs: MappedVirtualDisk '%s' has no container path", mvd.HostPath) - } - } - - return nil -} - -// Create creates a utility VM from a configuration. -func (config *Config) Create() error { - logrus.Debugf("opengcs Create: %+v", config) - - if err := config.validate(); err != nil { - return err - } - - configuration := &hcsshim.ContainerConfig{ - HvPartition: true, - Name: config.Name, - SystemType: "container", - ContainerType: "linux", - TerminateOnLastHandleClosed: true, - MappedVirtualDisks: config.MappedVirtualDisks, - } - - if config.ActualMode == ModeActualVhdx { - configuration.HvRuntime = &hcsshim.HvRuntime{ - ImagePath: config.Vhdx, - } - } else { - configuration.HvRuntime = &hcsshim.HvRuntime{ - ImagePath: config.KirdPath, - LinuxInitrdFile: config.InitrdFile, - LinuxKernelFile: config.KernelFile, - } - } - - configurationS, _ := json.Marshal(configuration) - logrus.Debugf("opengcs Create: calling HCS with '%s'", string(configurationS)) - uvm, err := hcsshim.CreateContainer(config.Name, configuration) - if err != nil { - return err - } - logrus.Debugf("opengcs Create: uvm created, starting...") - err = uvm.Start() - if err != nil { - logrus.Debugf("opengcs Create: uvm failed to start: %s", err) - // Make sure we don't leave it laying around as it's been created in HCS - uvm.Terminate() - return err - } - - config.Uvm = uvm - logrus.Debugf("opengcs Create: uvm %s is running", config.Name) - return nil -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/createsandbox.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/createsandbox.go deleted file mode 100644 index 4fd9cc907a..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/createsandbox.go +++ /dev/null @@ -1,78 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - "os" - "sync" - - "github.com/Sirupsen/logrus" -) - -var sandboxCacheLock sync.Mutex - -// CreateSandbox does what it says on the tin. This is done by copying a prebuilt-sandbox from the ServiceVM -// TODO: @jhowardmsft maxSizeInMB isn't hooked up in GCS. Needs a platform change which is in flight. -func (config *Config) CreateSandbox(destFile string, maxSizeInMB uint32, cacheFile string) error { - // Smallest we can accept is the default sandbox size as we can't size down, only expand. - if maxSizeInMB < DefaultSandboxSizeMB { - maxSizeInMB = DefaultSandboxSizeMB - } - - logrus.Debugf("opengcs: CreateSandbox: %s size:%dMB cache:%s", destFile, maxSizeInMB, cacheFile) - - // Retrieve from cache if the default size and already on disk - if cacheFile != "" && maxSizeInMB == DefaultSandboxSizeMB { - sandboxCacheLock.Lock() - if _, err := os.Stat(cacheFile); err == nil { - if err := copyFile(cacheFile, destFile); err != nil { - sandboxCacheLock.Unlock() - return fmt.Errorf("opengcs: CreateSandbox: Failed to copy cached sandbox '%s' to '%s': %s", cacheFile, destFile, err) - } - sandboxCacheLock.Unlock() - logrus.Debugf("opengcs: CreateSandbox: %s fulfilled from cache", destFile) - return nil - } - sandboxCacheLock.Unlock() - } - - if config.Uvm == nil { - return fmt.Errorf("opengcs: CreateSandbox: No utility VM has been created") - } - - // TODO @jhowardmsft - needs a platform change so that can specify size. eg fmt.Sprintf("createSandbox -size %d", maxSizeInMB)) - process, err := config.createUtilsProcess("createSandbox") - if err != nil { - return fmt.Errorf("opengcs: CreateSandbox: %s: failed to create utils process: %s", destFile, err) - } - - defer func() { - process.Process.Close() - }() - - logrus.Debugf("opengcs: CreateSandbox: %s: writing from stdout", destFile) - // Get back the sandbox VHDx stream from the service VM and write it to file - resultSize, err := writeFileFromReader(destFile, process.Stdout, config.UvmTimeoutSeconds, fmt.Sprintf("createSandbox %s", destFile)) - if err != nil { - return fmt.Errorf("opengcs: CreateSandbox: %s: failed writing %d bytes to target file: %s", destFile, resultSize, err) - } - - // Populate the cache - if cacheFile != "" && maxSizeInMB == DefaultSandboxSizeMB { - sandboxCacheLock.Lock() - // It may already exist due to being created on another thread, in which case no copy back needed. - if _, err := os.Stat(cacheFile); os.IsNotExist(err) { - if err := copyFile(destFile, cacheFile); err != nil { - sandboxCacheLock.Unlock() - return fmt.Errorf("opengcs: CreateSandbox: Failed to seed sandbox cache '%s' from '%s': %s", destFile, cacheFile, err) - } - } - sandboxCacheLock.Unlock() - } - - logrus.Debugf("opengcs: CreateSandbox: %s created (non-cache)", destFile) - return nil -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/hotaddvhd.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/hotaddvhd.go deleted file mode 100644 index 62de79016a..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/hotaddvhd.go +++ /dev/null @@ -1,41 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - - "github.com/Microsoft/hcsshim" - "github.com/Sirupsen/logrus" -) - -// HotAddVhd hot-adds a VHD to a utility VM. This is used in the global one-utility-VM- -// service-VM per host scenario. In order to do a graphdriver `Diff`, we hot-add the -// sandbox to /mnt/ so that we can run `exportSandbox` inside the utility VM to -// get a tar-stream of the sandboxes contents back to the daemon. -func (config *Config) HotAddVhd(hostPath string, containerPath string) error { - logrus.Debugf("opengcs: HotAddVhd: %s: %s", hostPath, containerPath) - - if config.Uvm == nil { - return fmt.Errorf("cannot hot-add VHD as no utility VM is in configuration") - } - - modification := &hcsshim.ResourceModificationRequestResponse{ - Resource: "MappedVirtualDisk", - Data: hcsshim.MappedVirtualDisk{ - HostPath: hostPath, - ContainerPath: containerPath, - CreateInUtilityVM: true, - //ReadOnly: true, - }, - Request: "Add", - } - logrus.Debugf("opengcs: HotAddVhd: %s to %s", hostPath, containerPath) - if err := config.Uvm.Modify(modification); err != nil { - return fmt.Errorf("opengcs: HotAddVhd: failed: %s", err) - } - logrus.Debugf("opengcs: HotAddVhd: %s added successfully", hostPath) - return nil -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/hotremovevhd.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/hotremovevhd.go deleted file mode 100644 index 71167d00ee..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/hotremovevhd.go +++ /dev/null @@ -1,36 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - - "github.com/Microsoft/hcsshim" - "github.com/Sirupsen/logrus" -) - -// HotRemoveVhd hot-removes a VHD from a utility VM. This is used in the global one-utility-VM- -// service-VM per host scenario. -func (config *Config) HotRemoveVhd(hostPath string) error { - logrus.Debugf("opengcs: HotRemoveVhd: %s", hostPath) - - if config.Uvm == nil { - return fmt.Errorf("cannot hot-add VHD as no utility VM is in configuration") - } - - modification := &hcsshim.ResourceModificationRequestResponse{ - Resource: "MappedVirtualDisk", - Data: hcsshim.MappedVirtualDisk{ - HostPath: hostPath, - CreateInUtilityVM: true, - }, - Request: "Remove", - } - if err := config.Uvm.Modify(modification); err != nil { - return fmt.Errorf("opengcs: HotRemoveVhd: %s failed: %s", hostPath, err) - } - logrus.Debugf("opengcs: HotRemoveVhd: %s removed successfully", hostPath) - return nil -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/layervhddetails.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/layervhddetails.go deleted file mode 100644 index 6ce29cdc56..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/layervhddetails.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - "os" - "path/filepath" -) - -// LayerVhdDetails is a utility for getting a file name, size and indication of -// sandbox for a VHD(x) in a folder. A read-only layer will be layer.vhd. A -// read-write layer will be sandbox.vhdx. -func LayerVhdDetails(folder string) (string, int64, bool, error) { - var fileInfo os.FileInfo - isSandbox := false - filename := filepath.Join(folder, "layer.vhd") - var err error - - if fileInfo, err = os.Stat(filename); err != nil { - filename = filepath.Join(folder, "sandbox.vhdx") - if fileInfo, err = os.Stat(filename); err != nil { - if os.IsNotExist(err) { - return "", 0, isSandbox, fmt.Errorf("could not find layer or sandbox in %s", folder) - } - return "", 0, isSandbox, fmt.Errorf("error locating layer or sandbox in %s: %s", folder, err) - } - isSandbox = true - } - return filename, fileInfo.Size(), isSandbox, nil -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/process.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/process.go deleted file mode 100644 index 6592ab6a03..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/process.go +++ /dev/null @@ -1,61 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - "io" - - "github.com/Microsoft/hcsshim" - "github.com/Sirupsen/logrus" -) - -// Process is the structure pertaining to a process running in a utility VM. -type process struct { - Process hcsshim.Process - Stdin io.WriteCloser - Stdout io.ReadCloser -} - -// createUtilsProcess is a convenient wrapper for hcsshim.createUtilsProcess to use when -// communicating with a utility VM. -func (config *Config) createUtilsProcess(commandLine string) (process, error) { - logrus.Debugf("opengcs: createUtilsProcess") - - if config.Uvm == nil { - return process{}, fmt.Errorf("cannot create utils process as no utility VM is in configuration") - } - - var ( - err error - proc process - ) - - env := make(map[string]string) - env["PATH"] = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:" - processConfig := &hcsshim.ProcessConfig{ - EmulateConsole: false, - CreateStdInPipe: true, - CreateStdOutPipe: true, - CreateStdErrPipe: true, - CreateInUtilityVm: true, - WorkingDirectory: "/bin", - Environment: env, - CommandLine: commandLine, - } - proc.Process, err = config.Uvm.CreateProcess(processConfig) - if err != nil { - return process{}, fmt.Errorf("opengcs: createUtilsProcess: CreateProcess %+v failed %s", config, err) - } - - if proc.Stdin, proc.Stdout, _, err = proc.Process.Stdio(); err != nil { - proc.Process.Kill() // Should this have a timeout? - proc.Process.Close() - return process{}, fmt.Errorf("opengcs: createUtilsProcess: failed to get Stdio pipes %s", err) - } - - logrus.Debugf("opengcs: createUtilsProcess success: pid %d", proc.Process.Pid()) - return proc, nil -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/tartovhd.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/tartovhd.go deleted file mode 100644 index f6ce79ecb6..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/tartovhd.go +++ /dev/null @@ -1,46 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - "io" - - "github.com/Sirupsen/logrus" -) - -// TarToVhd streams a tarstream contained in an io.Reader to a fixed vhd file -func (config *Config) TarToVhd(targetVHDFile string, reader io.Reader) (int64, error) { - logrus.Debugf("opengcs: TarToVhd: %s", targetVHDFile) - - if config.Uvm == nil { - return 0, fmt.Errorf("cannot Tar2Vhd as no utility VM is in configuration") - } - - process, err := config.createUtilsProcess("tar2vhd") - if err != nil { - return 0, fmt.Errorf("opengcs: TarToVhd: %s: failed to create utils process tar2vhd: %s", targetVHDFile, err) - } - defer process.Process.Close() - - // Send the tarstream into the `tar2vhd`s stdin - if _, err = copyWithTimeout(process.Stdin, reader, 0, config.UvmTimeoutSeconds, fmt.Sprintf("send %s, to stdin of tar2vhd", targetVHDFile)); err != nil { - return 0, fmt.Errorf("opengcs: TarToVhd: %s: failed to send to tar2vhd in uvm: %s", targetVHDFile, err) - } - - // Don't need stdin now we've sent everything. This signals GCS that we are finished sending data. - if err := process.Process.CloseStdin(); err != nil { - return 0, fmt.Errorf("opengcs: TarToVhd: %s: failed closing stdin handle: %s", targetVHDFile, err) - } - - // Write stdout contents of `tar2vhd` to the VHD file - payloadSize, err := writeFileFromReader(targetVHDFile, process.Stdout, config.UvmTimeoutSeconds, fmt.Sprintf("output of tar2vhd to %s", targetVHDFile)) - if err != nil { - return 0, fmt.Errorf("opengcs: TarToVhd: %s: failed writing VHD file: %s", targetVHDFile, err) - } - - logrus.Debugf("opengcs: TarToVhd: %s created, %d bytes", targetVHDFile, payloadSize) - return payloadSize, err -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/unsupported.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/unsupported.go deleted file mode 100644 index 4a7abab3b0..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/unsupported.go +++ /dev/null @@ -1,5 +0,0 @@ -// +build !windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/utilities.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/utilities.go deleted file mode 100644 index 4ebd9bb156..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/utilities.go +++ /dev/null @@ -1,99 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - "io" - "os" - "syscall" - "time" - "unsafe" - - "github.com/Sirupsen/logrus" -) - -var ( - modkernel32 = syscall.NewLazyDLL("kernel32.dll") - procCopyFileW = modkernel32.NewProc("CopyFileW") -) - -// writeFileFromReader writes an output file from an io.Reader -func writeFileFromReader(path string, reader io.Reader, timeoutSeconds int, context string) (int64, error) { - outFile, err := os.Create(path) - if err != nil { - return 0, fmt.Errorf("opengcs: writeFileFromReader: failed to create %s: %s", path, err) - } - defer outFile.Close() - return copyWithTimeout(outFile, reader, 0, timeoutSeconds, context) -} - -// copyWithTimeout is a wrapper for io.Copy using a timeout duration -func copyWithTimeout(dst io.Writer, src io.Reader, size int64, timeoutSeconds int, context string) (int64, error) { - logrus.Debugf("opengcs: copywithtimeout: size %d: timeout %d: (%s)", size, timeoutSeconds, context) - - type resultType struct { - err error - bytes int64 - } - - done := make(chan resultType, 1) - go func() { - result := resultType{} - result.bytes, result.err = io.Copy(dst, src) - done <- result - }() - - var result resultType - timedout := time.After(time.Duration(timeoutSeconds) * time.Second) - - select { - case <-timedout: - return 0, fmt.Errorf("opengcs: copyWithTimeout: timed out (%s)", context) - case result = <-done: - if result.err != nil && result.err != io.EOF { - // See https://github.com/golang/go/blob/f3f29d1dea525f48995c1693c609f5e67c046893/src/os/exec/exec_windows.go for a clue as to why we are doing this :) - if se, ok := result.err.(syscall.Errno); ok { - const ( - errNoData = syscall.Errno(232) - errBrokenPipe = syscall.Errno(109) - ) - if se == errNoData || se == errBrokenPipe { - logrus.Debugf("opengcs: copyWithTimeout: hit NoData or BrokenPipe: %d: %s", se, context) - return result.bytes, nil - } - } - return 0, fmt.Errorf("opengcs: copyWithTimeout: error reading: '%s' after %d bytes (%s)", result.err, result.bytes, context) - } - } - logrus.Debugf("opengcs: copyWithTimeout: success - copied %d bytes (%s)", result.bytes, context) - return result.bytes, nil -} - -// copyFile is a utility for copying a file - used for the sandbox cache. -// Uses CopyFileW win32 API for performance -func copyFile(srcFile, destFile string) error { - var bFailIfExists uint32 = 1 - - lpExistingFileName, err := syscall.UTF16PtrFromString(srcFile) - if err != nil { - return err - } - lpNewFileName, err := syscall.UTF16PtrFromString(destFile) - if err != nil { - return err - } - r1, _, err := syscall.Syscall( - procCopyFileW.Addr(), - 3, - uintptr(unsafe.Pointer(lpExistingFileName)), - uintptr(unsafe.Pointer(lpNewFileName)), - uintptr(bFailIfExists)) - if r1 == 0 { - return fmt.Errorf("failed CopyFileW Win32 call from '%s' to %s: %s", srcFile, destFile, err) - } - return nil - -} diff --git a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/vhdtotar.go b/vendor/github.com/jhowardmsft/opengcs/gogcs/client/vhdtotar.go deleted file mode 100644 index 9504fb7c84..0000000000 --- a/vendor/github.com/jhowardmsft/opengcs/gogcs/client/vhdtotar.go +++ /dev/null @@ -1,69 +0,0 @@ -// +build windows - -package client - -// TODO @jhowardmsft - This will move to Microsoft/opengcs soon - -import ( - "fmt" - "io" - "os" - - "github.com/Sirupsen/logrus" -) - -// VhdToTar does what is says - it exports a VHD in a specified -// folder (either a read-only layer.vhd, or a read-write sandbox.vhd) to a -// ReadCloser containing a tar-stream of the layers contents. -func (config *Config) VhdToTar(vhdFile string, uvmMountPath string, isSandbox bool, vhdSize int64) (io.ReadCloser, error) { - logrus.Debugf("opengcs: VhdToTar: %s isSandbox: %t", vhdFile, isSandbox) - - if config.Uvm == nil { - return nil, fmt.Errorf("cannot VhdToTar as no utility VM is in configuration") - } - - vhdHandle, err := os.Open(vhdFile) - if err != nil { - return nil, fmt.Errorf("opengcs: VhdToTar: failed to open %s: %s", vhdFile, err) - } - defer vhdHandle.Close() - logrus.Debugf("opengcs: VhdToTar: exporting %s, size %d, isSandbox %t", vhdHandle.Name(), vhdSize, isSandbox) - - // Different binary depending on whether a RO layer or a RW sandbox - command := "vhd2tar" - if isSandbox { - command = fmt.Sprintf("exportSandbox -path %s", uvmMountPath) - } - - // Start the binary in the utility VM - process, err := config.createUtilsProcess(command) - if err != nil { - return nil, fmt.Errorf("opengcs: VhdToTar: %s: failed to create utils process %s: %s", vhdHandle.Name(), command, err) - } - - if !isSandbox { - // Send the VHD contents to the utility VM processes stdin handle if not a sandbox - logrus.Debugf("opengcs: VhdToTar: copying the layer VHD into the utility VM") - if _, err = copyWithTimeout(process.Stdin, vhdHandle, vhdSize, config.UvmTimeoutSeconds, fmt.Sprintf("vhdtotarstream: sending %s to %s", vhdHandle.Name(), command)); err != nil { - process.Process.Close() - return nil, fmt.Errorf("opengcs: VhdToTar: %s: failed to copyWithTimeout on the stdin pipe (to utility VM): %s", vhdHandle.Name(), err) - } - } - - // Start a goroutine which copies the stdout (ie the tar stream) - reader, writer := io.Pipe() - go func() { - defer writer.Close() - defer process.Process.Close() - logrus.Debugf("opengcs: VhdToTar: copying tar stream back from the utility VM") - bytes, err := copyWithTimeout(writer, process.Stdout, vhdSize, config.UvmTimeoutSeconds, fmt.Sprintf("vhdtotarstream: copy tarstream from %s", command)) - if err != nil { - logrus.Errorf("opengcs: VhdToTar: %s: copyWithTimeout on the stdout pipe (from utility VM) failed: %s", vhdHandle.Name(), err) - } - logrus.Debugf("opengcs: VhdToTar: copied %d bytes of the tarstream of %s from the utility VM", bytes, vhdHandle.Name()) - }() - - // Return the read-side of the pipe connected to the goroutine which is reading from the stdout of the process in the utility VM - return reader, nil - -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go b/vendor/golang.org/x/crypto/ssh/terminal/terminal.go deleted file mode 100644 index 741eeb13f0..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/terminal.go +++ /dev/null @@ -1,892 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package terminal - -import ( - "bytes" - "io" - "sync" - "unicode/utf8" -) - -// EscapeCodes contains escape sequences that can be written to the terminal in -// order to achieve different styles of text. -type EscapeCodes struct { - // Foreground colors - Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte - - // Reset all attributes - Reset []byte -} - -var vt100EscapeCodes = EscapeCodes{ - Black: []byte{keyEscape, '[', '3', '0', 'm'}, - Red: []byte{keyEscape, '[', '3', '1', 'm'}, - Green: []byte{keyEscape, '[', '3', '2', 'm'}, - Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, - Blue: []byte{keyEscape, '[', '3', '4', 'm'}, - Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, - Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, - White: []byte{keyEscape, '[', '3', '7', 'm'}, - - Reset: []byte{keyEscape, '[', '0', 'm'}, -} - -// Terminal contains the state for running a VT100 terminal that is capable of -// reading lines of input. -type Terminal struct { - // AutoCompleteCallback, if non-null, is called for each keypress with - // the full input line and the current position of the cursor (in - // bytes, as an index into |line|). If it returns ok=false, the key - // press is processed normally. Otherwise it returns a replacement line - // and the new cursor position. - AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) - - // Escape contains a pointer to the escape codes for this terminal. - // It's always a valid pointer, although the escape codes themselves - // may be empty if the terminal doesn't support them. - Escape *EscapeCodes - - // lock protects the terminal and the state in this object from - // concurrent processing of a key press and a Write() call. - lock sync.Mutex - - c io.ReadWriter - prompt []rune - - // line is the current line being entered. - line []rune - // pos is the logical position of the cursor in line - pos int - // echo is true if local echo is enabled - echo bool - // pasteActive is true iff there is a bracketed paste operation in - // progress. - pasteActive bool - - // cursorX contains the current X value of the cursor where the left - // edge is 0. cursorY contains the row number where the first row of - // the current line is 0. - cursorX, cursorY int - // maxLine is the greatest value of cursorY so far. - maxLine int - - termWidth, termHeight int - - // outBuf contains the terminal data to be sent. - outBuf []byte - // remainder contains the remainder of any partial key sequences after - // a read. It aliases into inBuf. - remainder []byte - inBuf [256]byte - - // history contains previously entered commands so that they can be - // accessed with the up and down keys. - history stRingBuffer - // historyIndex stores the currently accessed history entry, where zero - // means the immediately previous entry. - historyIndex int - // When navigating up and down the history it's possible to return to - // the incomplete, initial line. That value is stored in - // historyPending. - historyPending string -} - -// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is -// a local terminal, that terminal must first have been put into raw mode. -// prompt is a string that is written at the start of each input line (i.e. -// "> "). -func NewTerminal(c io.ReadWriter, prompt string) *Terminal { - return &Terminal{ - Escape: &vt100EscapeCodes, - c: c, - prompt: []rune(prompt), - termWidth: 80, - termHeight: 24, - echo: true, - historyIndex: -1, - } -} - -const ( - keyCtrlD = 4 - keyCtrlU = 21 - keyEnter = '\r' - keyEscape = 27 - keyBackspace = 127 - keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota - keyUp - keyDown - keyLeft - keyRight - keyAltLeft - keyAltRight - keyHome - keyEnd - keyDeleteWord - keyDeleteLine - keyClearScreen - keyPasteStart - keyPasteEnd -) - -var pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} -var pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} - -// bytesToKey tries to parse a key sequence from b. If successful, it returns -// the key and the remainder of the input. Otherwise it returns utf8.RuneError. -func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { - if len(b) == 0 { - return utf8.RuneError, nil - } - - if !pasteActive { - switch b[0] { - case 1: // ^A - return keyHome, b[1:] - case 5: // ^E - return keyEnd, b[1:] - case 8: // ^H - return keyBackspace, b[1:] - case 11: // ^K - return keyDeleteLine, b[1:] - case 12: // ^L - return keyClearScreen, b[1:] - case 23: // ^W - return keyDeleteWord, b[1:] - } - } - - if b[0] != keyEscape { - if !utf8.FullRune(b) { - return utf8.RuneError, b - } - r, l := utf8.DecodeRune(b) - return r, b[l:] - } - - if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { - switch b[2] { - case 'A': - return keyUp, b[3:] - case 'B': - return keyDown, b[3:] - case 'C': - return keyRight, b[3:] - case 'D': - return keyLeft, b[3:] - case 'H': - return keyHome, b[3:] - case 'F': - return keyEnd, b[3:] - } - } - - if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { - switch b[5] { - case 'C': - return keyAltRight, b[6:] - case 'D': - return keyAltLeft, b[6:] - } - } - - if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { - return keyPasteStart, b[6:] - } - - if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { - return keyPasteEnd, b[6:] - } - - // If we get here then we have a key that we don't recognise, or a - // partial sequence. It's not clear how one should find the end of a - // sequence without knowing them all, but it seems that [a-zA-Z~] only - // appears at the end of a sequence. - for i, c := range b[0:] { - if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { - return keyUnknown, b[i+1:] - } - } - - return utf8.RuneError, b -} - -// queue appends data to the end of t.outBuf -func (t *Terminal) queue(data []rune) { - t.outBuf = append(t.outBuf, []byte(string(data))...) -} - -var eraseUnderCursor = []rune{' ', keyEscape, '[', 'D'} -var space = []rune{' '} - -func isPrintable(key rune) bool { - isInSurrogateArea := key >= 0xd800 && key <= 0xdbff - return key >= 32 && !isInSurrogateArea -} - -// moveCursorToPos appends data to t.outBuf which will move the cursor to the -// given, logical position in the text. -func (t *Terminal) moveCursorToPos(pos int) { - if !t.echo { - return - } - - x := visualLength(t.prompt) + pos - y := x / t.termWidth - x = x % t.termWidth - - up := 0 - if y < t.cursorY { - up = t.cursorY - y - } - - down := 0 - if y > t.cursorY { - down = y - t.cursorY - } - - left := 0 - if x < t.cursorX { - left = t.cursorX - x - } - - right := 0 - if x > t.cursorX { - right = x - t.cursorX - } - - t.cursorX = x - t.cursorY = y - t.move(up, down, left, right) -} - -func (t *Terminal) move(up, down, left, right int) { - movement := make([]rune, 3*(up+down+left+right)) - m := movement - for i := 0; i < up; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'A' - m = m[3:] - } - for i := 0; i < down; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'B' - m = m[3:] - } - for i := 0; i < left; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'D' - m = m[3:] - } - for i := 0; i < right; i++ { - m[0] = keyEscape - m[1] = '[' - m[2] = 'C' - m = m[3:] - } - - t.queue(movement) -} - -func (t *Terminal) clearLineToRight() { - op := []rune{keyEscape, '[', 'K'} - t.queue(op) -} - -const maxLineLength = 4096 - -func (t *Terminal) setLine(newLine []rune, newPos int) { - if t.echo { - t.moveCursorToPos(0) - t.writeLine(newLine) - for i := len(newLine); i < len(t.line); i++ { - t.writeLine(space) - } - t.moveCursorToPos(newPos) - } - t.line = newLine - t.pos = newPos -} - -func (t *Terminal) advanceCursor(places int) { - t.cursorX += places - t.cursorY += t.cursorX / t.termWidth - if t.cursorY > t.maxLine { - t.maxLine = t.cursorY - } - t.cursorX = t.cursorX % t.termWidth - - if places > 0 && t.cursorX == 0 { - // Normally terminals will advance the current position - // when writing a character. But that doesn't happen - // for the last character in a line. However, when - // writing a character (except a new line) that causes - // a line wrap, the position will be advanced two - // places. - // - // So, if we are stopping at the end of a line, we - // need to write a newline so that our cursor can be - // advanced to the next line. - t.outBuf = append(t.outBuf, '\n') - } -} - -func (t *Terminal) eraseNPreviousChars(n int) { - if n == 0 { - return - } - - if t.pos < n { - n = t.pos - } - t.pos -= n - t.moveCursorToPos(t.pos) - - copy(t.line[t.pos:], t.line[n+t.pos:]) - t.line = t.line[:len(t.line)-n] - if t.echo { - t.writeLine(t.line[t.pos:]) - for i := 0; i < n; i++ { - t.queue(space) - } - t.advanceCursor(n) - t.moveCursorToPos(t.pos) - } -} - -// countToLeftWord returns then number of characters from the cursor to the -// start of the previous word. -func (t *Terminal) countToLeftWord() int { - if t.pos == 0 { - return 0 - } - - pos := t.pos - 1 - for pos > 0 { - if t.line[pos] != ' ' { - break - } - pos-- - } - for pos > 0 { - if t.line[pos] == ' ' { - pos++ - break - } - pos-- - } - - return t.pos - pos -} - -// countToRightWord returns then number of characters from the cursor to the -// start of the next word. -func (t *Terminal) countToRightWord() int { - pos := t.pos - for pos < len(t.line) { - if t.line[pos] == ' ' { - break - } - pos++ - } - for pos < len(t.line) { - if t.line[pos] != ' ' { - break - } - pos++ - } - return pos - t.pos -} - -// visualLength returns the number of visible glyphs in s. -func visualLength(runes []rune) int { - inEscapeSeq := false - length := 0 - - for _, r := range runes { - switch { - case inEscapeSeq: - if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { - inEscapeSeq = false - } - case r == '\x1b': - inEscapeSeq = true - default: - length++ - } - } - - return length -} - -// handleKey processes the given key and, optionally, returns a line of text -// that the user has entered. -func (t *Terminal) handleKey(key rune) (line string, ok bool) { - if t.pasteActive && key != keyEnter { - t.addKeyToLine(key) - return - } - - switch key { - case keyBackspace: - if t.pos == 0 { - return - } - t.eraseNPreviousChars(1) - case keyAltLeft: - // move left by a word. - t.pos -= t.countToLeftWord() - t.moveCursorToPos(t.pos) - case keyAltRight: - // move right by a word. - t.pos += t.countToRightWord() - t.moveCursorToPos(t.pos) - case keyLeft: - if t.pos == 0 { - return - } - t.pos-- - t.moveCursorToPos(t.pos) - case keyRight: - if t.pos == len(t.line) { - return - } - t.pos++ - t.moveCursorToPos(t.pos) - case keyHome: - if t.pos == 0 { - return - } - t.pos = 0 - t.moveCursorToPos(t.pos) - case keyEnd: - if t.pos == len(t.line) { - return - } - t.pos = len(t.line) - t.moveCursorToPos(t.pos) - case keyUp: - entry, ok := t.history.NthPreviousEntry(t.historyIndex + 1) - if !ok { - return "", false - } - if t.historyIndex == -1 { - t.historyPending = string(t.line) - } - t.historyIndex++ - runes := []rune(entry) - t.setLine(runes, len(runes)) - case keyDown: - switch t.historyIndex { - case -1: - return - case 0: - runes := []rune(t.historyPending) - t.setLine(runes, len(runes)) - t.historyIndex-- - default: - entry, ok := t.history.NthPreviousEntry(t.historyIndex - 1) - if ok { - t.historyIndex-- - runes := []rune(entry) - t.setLine(runes, len(runes)) - } - } - case keyEnter: - t.moveCursorToPos(len(t.line)) - t.queue([]rune("\r\n")) - line = string(t.line) - ok = true - t.line = t.line[:0] - t.pos = 0 - t.cursorX = 0 - t.cursorY = 0 - t.maxLine = 0 - case keyDeleteWord: - // Delete zero or more spaces and then one or more characters. - t.eraseNPreviousChars(t.countToLeftWord()) - case keyDeleteLine: - // Delete everything from the current cursor position to the - // end of line. - for i := t.pos; i < len(t.line); i++ { - t.queue(space) - t.advanceCursor(1) - } - t.line = t.line[:t.pos] - t.moveCursorToPos(t.pos) - case keyCtrlD: - // Erase the character under the current position. - // The EOF case when the line is empty is handled in - // readLine(). - if t.pos < len(t.line) { - t.pos++ - t.eraseNPreviousChars(1) - } - case keyCtrlU: - t.eraseNPreviousChars(t.pos) - case keyClearScreen: - // Erases the screen and moves the cursor to the home position. - t.queue([]rune("\x1b[2J\x1b[H")) - t.queue(t.prompt) - t.cursorX, t.cursorY = 0, 0 - t.advanceCursor(visualLength(t.prompt)) - t.setLine(t.line, t.pos) - default: - if t.AutoCompleteCallback != nil { - prefix := string(t.line[:t.pos]) - suffix := string(t.line[t.pos:]) - - t.lock.Unlock() - newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) - t.lock.Lock() - - if completeOk { - t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) - return - } - } - if !isPrintable(key) { - return - } - if len(t.line) == maxLineLength { - return - } - t.addKeyToLine(key) - } - return -} - -// addKeyToLine inserts the given key at the current position in the current -// line. -func (t *Terminal) addKeyToLine(key rune) { - if len(t.line) == cap(t.line) { - newLine := make([]rune, len(t.line), 2*(1+len(t.line))) - copy(newLine, t.line) - t.line = newLine - } - t.line = t.line[:len(t.line)+1] - copy(t.line[t.pos+1:], t.line[t.pos:]) - t.line[t.pos] = key - if t.echo { - t.writeLine(t.line[t.pos:]) - } - t.pos++ - t.moveCursorToPos(t.pos) -} - -func (t *Terminal) writeLine(line []rune) { - for len(line) != 0 { - remainingOnLine := t.termWidth - t.cursorX - todo := len(line) - if todo > remainingOnLine { - todo = remainingOnLine - } - t.queue(line[:todo]) - t.advanceCursor(visualLength(line[:todo])) - line = line[todo:] - } -} - -func (t *Terminal) Write(buf []byte) (n int, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - if t.cursorX == 0 && t.cursorY == 0 { - // This is the easy case: there's nothing on the screen that we - // have to move out of the way. - return t.c.Write(buf) - } - - // We have a prompt and possibly user input on the screen. We - // have to clear it first. - t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) - t.cursorX = 0 - t.clearLineToRight() - - for t.cursorY > 0 { - t.move(1 /* up */, 0, 0, 0) - t.cursorY-- - t.clearLineToRight() - } - - if _, err = t.c.Write(t.outBuf); err != nil { - return - } - t.outBuf = t.outBuf[:0] - - if n, err = t.c.Write(buf); err != nil { - return - } - - t.writeLine(t.prompt) - if t.echo { - t.writeLine(t.line) - } - - t.moveCursorToPos(t.pos) - - if _, err = t.c.Write(t.outBuf); err != nil { - return - } - t.outBuf = t.outBuf[:0] - return -} - -// ReadPassword temporarily changes the prompt and reads a password, without -// echo, from the terminal. -func (t *Terminal) ReadPassword(prompt string) (line string, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - oldPrompt := t.prompt - t.prompt = []rune(prompt) - t.echo = false - - line, err = t.readLine() - - t.prompt = oldPrompt - t.echo = true - - return -} - -// ReadLine returns a line of input from the terminal. -func (t *Terminal) ReadLine() (line string, err error) { - t.lock.Lock() - defer t.lock.Unlock() - - return t.readLine() -} - -func (t *Terminal) readLine() (line string, err error) { - // t.lock must be held at this point - - if t.cursorX == 0 && t.cursorY == 0 { - t.writeLine(t.prompt) - t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - } - - lineIsPasted := t.pasteActive - - for { - rest := t.remainder - lineOk := false - for !lineOk { - var key rune - key, rest = bytesToKey(rest, t.pasteActive) - if key == utf8.RuneError { - break - } - if !t.pasteActive { - if key == keyCtrlD { - if len(t.line) == 0 { - return "", io.EOF - } - } - if key == keyPasteStart { - t.pasteActive = true - if len(t.line) == 0 { - lineIsPasted = true - } - continue - } - } else if key == keyPasteEnd { - t.pasteActive = false - continue - } - if !t.pasteActive { - lineIsPasted = false - } - line, lineOk = t.handleKey(key) - } - if len(rest) > 0 { - n := copy(t.inBuf[:], rest) - t.remainder = t.inBuf[:n] - } else { - t.remainder = nil - } - t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - if lineOk { - if t.echo { - t.historyIndex = -1 - t.history.Add(line) - } - if lineIsPasted { - err = ErrPasteIndicator - } - return - } - - // t.remainder is a slice at the beginning of t.inBuf - // containing a partial key sequence - readBuf := t.inBuf[len(t.remainder):] - var n int - - t.lock.Unlock() - n, err = t.c.Read(readBuf) - t.lock.Lock() - - if err != nil { - return - } - - t.remainder = t.inBuf[:n+len(t.remainder)] - } - - panic("unreachable") // for Go 1.0. -} - -// SetPrompt sets the prompt to be used when reading subsequent lines. -func (t *Terminal) SetPrompt(prompt string) { - t.lock.Lock() - defer t.lock.Unlock() - - t.prompt = []rune(prompt) -} - -func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { - // Move cursor to column zero at the start of the line. - t.move(t.cursorY, 0, t.cursorX, 0) - t.cursorX, t.cursorY = 0, 0 - t.clearLineToRight() - for t.cursorY < numPrevLines { - // Move down a line - t.move(0, 1, 0, 0) - t.cursorY++ - t.clearLineToRight() - } - // Move back to beginning. - t.move(t.cursorY, 0, 0, 0) - t.cursorX, t.cursorY = 0, 0 - - t.queue(t.prompt) - t.advanceCursor(visualLength(t.prompt)) - t.writeLine(t.line) - t.moveCursorToPos(t.pos) -} - -func (t *Terminal) SetSize(width, height int) error { - t.lock.Lock() - defer t.lock.Unlock() - - if width == 0 { - width = 1 - } - - oldWidth := t.termWidth - t.termWidth, t.termHeight = width, height - - switch { - case width == oldWidth: - // If the width didn't change then nothing else needs to be - // done. - return nil - case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: - // If there is nothing on current line and no prompt printed, - // just do nothing - return nil - case width < oldWidth: - // Some terminals (e.g. xterm) will truncate lines that were - // too long when shinking. Others, (e.g. gnome-terminal) will - // attempt to wrap them. For the former, repainting t.maxLine - // works great, but that behaviour goes badly wrong in the case - // of the latter because they have doubled every full line. - - // We assume that we are working on a terminal that wraps lines - // and adjust the cursor position based on every previous line - // wrapping and turning into two. This causes the prompt on - // xterms to move upwards, which isn't great, but it avoids a - // huge mess with gnome-terminal. - if t.cursorX >= t.termWidth { - t.cursorX = t.termWidth - 1 - } - t.cursorY *= 2 - t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) - case width > oldWidth: - // If the terminal expands then our position calculations will - // be wrong in the future because we think the cursor is - // |t.pos| chars into the string, but there will be a gap at - // the end of any wrapped line. - // - // But the position will actually be correct until we move, so - // we can move back to the beginning and repaint everything. - t.clearAndRepaintLinePlusNPrevious(t.maxLine) - } - - _, err := t.c.Write(t.outBuf) - t.outBuf = t.outBuf[:0] - return err -} - -type pasteIndicatorError struct{} - -func (pasteIndicatorError) Error() string { - return "terminal: ErrPasteIndicator not correctly handled" -} - -// ErrPasteIndicator may be returned from ReadLine as the error, in addition -// to valid line data. It indicates that bracketed paste mode is enabled and -// that the returned line consists only of pasted data. Programs may wish to -// interpret pasted data more literally than typed data. -var ErrPasteIndicator = pasteIndicatorError{} - -// SetBracketedPasteMode requests that the terminal bracket paste operations -// with markers. Not all terminals support this but, if it is supported, then -// enabling this mode will stop any autocomplete callback from running due to -// pastes. Additionally, any lines that are completely pasted will be returned -// from ReadLine with the error set to ErrPasteIndicator. -func (t *Terminal) SetBracketedPasteMode(on bool) { - if on { - io.WriteString(t.c, "\x1b[?2004h") - } else { - io.WriteString(t.c, "\x1b[?2004l") - } -} - -// stRingBuffer is a ring buffer of strings. -type stRingBuffer struct { - // entries contains max elements. - entries []string - max int - // head contains the index of the element most recently added to the ring. - head int - // size contains the number of elements in the ring. - size int -} - -func (s *stRingBuffer) Add(a string) { - if s.entries == nil { - const defaultNumEntries = 100 - s.entries = make([]string, defaultNumEntries) - s.max = defaultNumEntries - } - - s.head = (s.head + 1) % s.max - s.entries[s.head] = a - if s.size < s.max { - s.size++ - } -} - -// NthPreviousEntry returns the value passed to the nth previous call to Add. -// If n is zero then the immediately prior value is returned, if one, then the -// next most recent, and so on. If such an element doesn't exist then ok is -// false. -func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) { - if n >= s.size { - return "", false - } - index := s.head - n - if index < 0 { - index += s.max - } - return s.entries[index], true -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util.go b/vendor/golang.org/x/crypto/ssh/terminal/util.go deleted file mode 100644 index 598e3df77e..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd linux,!appengine netbsd openbsd - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal // import "golang.org/x/crypto/ssh/terminal" - -import ( - "io" - "syscall" - "unsafe" -) - -// State contains the state of a terminal. -type State struct { - termios syscall.Termios -} - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - var termios syscall.Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - var oldState State - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { - return nil, err - } - - newState := oldState.termios - newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF - newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { - return nil, err - } - - return &oldState, nil -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - var oldState State - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { - return nil, err - } - - return &oldState, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&state.termios)), 0, 0, 0) - return err -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - var dimensions [4]uint16 - - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&dimensions)), 0, 0, 0); err != 0 { - return -1, -1, err - } - return int(dimensions[1]), int(dimensions[0]), nil -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - var oldState syscall.Termios - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlReadTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0); err != 0 { - return nil, err - } - - newState := oldState - newState.Lflag &^= syscall.ECHO - newState.Lflag |= syscall.ICANON | syscall.ISIG - newState.Iflag |= syscall.ICRNL - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { - return nil, err - } - - defer func() { - syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), ioctlWriteTermios, uintptr(unsafe.Pointer(&oldState)), 0, 0, 0) - }() - - var buf [16]byte - var ret []byte - for { - n, err := syscall.Read(fd, buf[:]) - if err != nil { - return nil, err - } - if n == 0 { - if len(ret) == 0 { - return nil, io.EOF - } - break - } - if buf[n-1] == '\n' { - n-- - } - ret = append(ret, buf[:n]...) - if n < len(buf) { - break - } - } - - return ret, nil -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go b/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go deleted file mode 100644 index 9c1ffd145a..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build darwin dragonfly freebsd netbsd openbsd - -package terminal - -import "syscall" - -const ioctlReadTermios = syscall.TIOCGETA -const ioctlWriteTermios = syscall.TIOCSETA diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go b/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go deleted file mode 100644 index 5883b22d78..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_linux.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2013 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package terminal - -// These constants are declared here, rather than importing -// them from the syscall package as some syscall packages, even -// on linux, for example gccgo, do not declare them. -const ioctlReadTermios = 0x5401 // syscall.TCGETS -const ioctlWriteTermios = 0x5402 // syscall.TCSETS diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go b/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go deleted file mode 100644 index 799f049f04..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal - -import ( - "fmt" - "runtime" -) - -type State struct{} - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - return false -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) -} diff --git a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go b/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go deleted file mode 100644 index ae9fa9ec1a..0000000000 --- a/vendor/golang.org/x/crypto/ssh/terminal/util_windows.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build windows - -// Package terminal provides support functions for dealing with terminals, as -// commonly found on UNIX systems. -// -// Putting a terminal into raw mode is the most common requirement: -// -// oldState, err := terminal.MakeRaw(0) -// if err != nil { -// panic(err) -// } -// defer terminal.Restore(0, oldState) -package terminal - -import ( - "io" - "syscall" - "unsafe" -) - -const ( - enableLineInput = 2 - enableEchoInput = 4 - enableProcessedInput = 1 - enableWindowInput = 8 - enableMouseInput = 16 - enableInsertMode = 32 - enableQuickEditMode = 64 - enableExtendedFlags = 128 - enableAutoPosition = 256 - enableProcessedOutput = 1 - enableWrapAtEolOutput = 2 -) - -var kernel32 = syscall.NewLazyDLL("kernel32.dll") - -var ( - procGetConsoleMode = kernel32.NewProc("GetConsoleMode") - procSetConsoleMode = kernel32.NewProc("SetConsoleMode") - procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") -) - -type ( - short int16 - word uint16 - - coord struct { - x short - y short - } - smallRect struct { - left short - top short - right short - bottom short - } - consoleScreenBufferInfo struct { - size coord - cursorPosition coord - attributes word - window smallRect - maximumWindowSize coord - } -) - -type State struct { - mode uint32 -} - -// IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd int) bool { - var st uint32 - r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) - return r != 0 && e == 0 -} - -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - var st uint32 - _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) - if e != 0 { - return nil, error(e) - } - raw := st &^ (enableEchoInput | enableProcessedInput | enableLineInput | enableProcessedOutput) - _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(raw), 0) - if e != 0 { - return nil, error(e) - } - return &State{st}, nil -} - -// GetState returns the current state of a terminal which may be useful to -// restore the terminal after a signal. -func GetState(fd int) (*State, error) { - var st uint32 - _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) - if e != 0 { - return nil, error(e) - } - return &State{st}, nil -} - -// Restore restores the terminal connected to the given file descriptor to a -// previous state. -func Restore(fd int, state *State) error { - _, _, err := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(state.mode), 0) - return err -} - -// GetSize returns the dimensions of the given terminal. -func GetSize(fd int) (width, height int, err error) { - var info consoleScreenBufferInfo - _, _, e := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&info)), 0) - if e != 0 { - return 0, 0, error(e) - } - return int(info.size.x), int(info.size.y), nil -} - -// ReadPassword reads a line of input from a terminal without local echo. This -// is commonly used for inputting passwords and other sensitive data. The slice -// returned does not include the \n. -func ReadPassword(fd int) ([]byte, error) { - var st uint32 - _, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) - if e != 0 { - return nil, error(e) - } - old := st - - st &^= (enableEchoInput) - st |= (enableProcessedInput | enableLineInput | enableProcessedOutput) - _, _, e = syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(st), 0) - if e != 0 { - return nil, error(e) - } - - defer func() { - syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(fd), uintptr(old), 0) - }() - - var buf [16]byte - var ret []byte - for { - n, err := syscall.Read(syscall.Handle(fd), buf[:]) - if err != nil { - return nil, err - } - if n == 0 { - if len(ret) == 0 { - return nil, io.EOF - } - break - } - if buf[n-1] == '\n' { - n-- - } - if n > 0 && buf[n-1] == '\r' { - n-- - } - ret = append(ret, buf[:n]...) - if n < len(buf) { - break - } - } - - return ret, nil -}