浏览代码

Merge pull request #24823 from aaronlehmann/join-tokens

Replace secrets with join tokens
Tibor Vass 9 年之前
父节点
当前提交
f5e1f6f688
共有 76 个文件被更改,包括 1806 次插入2337 次删除
  1. 0 32
      api/client/node/accept.go
  2. 0 1
      api/client/node/cmd.go
  3. 2 4
      api/client/node/list.go
  4. 0 9
      api/client/node/opts.go
  5. 0 9
      api/client/node/update.go
  6. 1 1
      api/client/service/opts.go
  7. 1 0
      api/client/swarm/cmd.go
  8. 2 30
      api/client/swarm/init.go
  9. 1 1
      api/client/swarm/inspect.go
  10. 19 13
      api/client/swarm/join.go
  11. 110 0
      api/client/swarm/join_token.go
  12. 1 1
      api/client/swarm/leave.go
  13. 1 87
      api/client/swarm/opts.go
  14. 0 99
      api/client/swarm/opts_test.go
  15. 0 19
      api/client/swarm/secret.go
  16. 5 18
      api/client/swarm/update.go
  17. 0 1
      api/client/system/info.go
  18. 1 1
      api/server/router/swarm/backend.go
  19. 9 1
      api/server/router/swarm/cluster_routes.go
  20. 6 6
      contrib/completion/zsh/_docker
  21. 33 56
      daemon/cluster/cluster.go
  22. 0 7
      daemon/cluster/convert/node.go
  23. 6 74
      daemon/cluster/convert/swarm.go
  24. 20 37
      docs/reference/api/docker_remote_api_v1.24.md
  25. 20 37
      docs/reference/api/docker_remote_api_v1.25.md
  26. 1 1
      docs/reference/commandline/deploy.md
  27. 3 3
      docs/reference/commandline/index.md
  28. 1 1
      docs/reference/commandline/info.md
  29. 0 32
      docs/reference/commandline/node_accept.md
  30. 0 1
      docs/reference/commandline/node_demote.md
  31. 0 1
      docs/reference/commandline/node_inspect.md
  32. 10 10
      docs/reference/commandline/node_ls.md
  33. 0 1
      docs/reference/commandline/node_promote.md
  34. 2 3
      docs/reference/commandline/node_rm.md
  35. 0 1
      docs/reference/commandline/node_update.md
  36. 1 1
      docs/reference/commandline/service_create.md
  37. 1 1
      docs/reference/commandline/service_update.md
  38. 19 54
      docs/reference/commandline/swarm_init.md
  39. 26 27
      docs/reference/commandline/swarm_join.md
  40. 76 0
      docs/reference/commandline/swarm_join_token.md
  41. 9 9
      docs/reference/commandline/swarm_leave.md
  42. 3 5
      docs/reference/commandline/swarm_update.md
  43. 2 2
      hack/vendor.sh
  44. 8 6
      integration-cli/check_test.go
  45. 22 8
      integration-cli/daemon_swarm.go
  46. 27 127
      integration-cli/docker_api_swarm_test.go
  47. 3 56
      integration-cli/docker_cli_swarm_test.go
  48. 1 1
      vendor/src/github.com/docker/engine-api/client/interface.go
  49. 4 1
      vendor/src/github.com/docker/engine-api/client/swarm_update.go
  50. 1 1
      vendor/src/github.com/docker/engine-api/client/transport/cancellable/cancellable.go
  51. 2 2
      vendor/src/github.com/docker/engine-api/types/configs.go
  52. 0 11
      vendor/src/github.com/docker/engine-api/types/swarm/node.go
  53. 37 33
      vendor/src/github.com/docker/engine-api/types/swarm/swarm.go
  54. 3 14
      vendor/src/github.com/docker/swarmkit/agent/node.go
  55. 14 1
      vendor/src/github.com/docker/swarmkit/agent/task.go
  56. 48 46
      vendor/src/github.com/docker/swarmkit/api/ca.pb.go
  57. 7 3
      vendor/src/github.com/docker/swarmkit/api/ca.proto
  58. 332 94
      vendor/src/github.com/docker/swarmkit/api/control.pb.go
  59. 11 0
      vendor/src/github.com/docker/swarmkit/api/control.proto
  60. 103 113
      vendor/src/github.com/docker/swarmkit/api/specs.pb.go
  61. 6 8
      vendor/src/github.com/docker/swarmkit/api/specs.proto
  62. 632 209
      vendor/src/github.com/docker/swarmkit/api/types.pb.go
  63. 23 0
      vendor/src/github.com/docker/swarmkit/api/types.proto
  64. 11 14
      vendor/src/github.com/docker/swarmkit/ca/certificates.go
  65. 45 9
      vendor/src/github.com/docker/swarmkit/ca/config.go
  66. 41 96
      vendor/src/github.com/docker/swarmkit/ca/server.go
  67. 8 0
      vendor/src/github.com/docker/swarmkit/manager/controlapi/cluster.go
  68. 8 5
      vendor/src/github.com/docker/swarmkit/manager/controlapi/server.go
  69. 11 1
      vendor/src/github.com/docker/swarmkit/manager/keymanager/keymanager.go
  70. 5 2
      vendor/src/github.com/docker/swarmkit/manager/manager.go
  71. 1 1
      vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go
  72. 0 35
      vendor/src/golang.org/x/crypto/bcrypt/base64.go
  73. 0 294
      vendor/src/golang.org/x/crypto/bcrypt/bcrypt.go
  74. 0 159
      vendor/src/golang.org/x/crypto/blowfish/block.go
  75. 0 91
      vendor/src/golang.org/x/crypto/blowfish/cipher.go
  76. 0 199
      vendor/src/golang.org/x/crypto/blowfish/const.go

+ 0 - 32
api/client/node/accept.go

@@ -1,32 +0,0 @@
-package node
-
-import (
-	"fmt"
-
-	"github.com/docker/docker/api/client"
-	"github.com/docker/docker/cli"
-	"github.com/docker/engine-api/types/swarm"
-	"github.com/spf13/cobra"
-)
-
-func newAcceptCommand(dockerCli *client.DockerCli) *cobra.Command {
-	return &cobra.Command{
-		Use:   "accept NODE [NODE...]",
-		Short: "Accept a node in the swarm",
-		Args:  cli.RequiresMinArgs(1),
-		RunE: func(cmd *cobra.Command, args []string) error {
-			return runAccept(dockerCli, args)
-		},
-	}
-}
-
-func runAccept(dockerCli *client.DockerCli, nodes []string) error {
-	accept := func(node *swarm.Node) error {
-		node.Spec.Membership = swarm.NodeMembershipAccepted
-		return nil
-	}
-	success := func(nodeID string) {
-		fmt.Fprintf(dockerCli.Out(), "Node %s accepted in the swarm.\n", nodeID)
-	}
-	return updateNodes(dockerCli, nodes, accept, success)
-}

+ 0 - 1
api/client/node/cmd.go

@@ -23,7 +23,6 @@ func NewNodeCommand(dockerCli *client.DockerCli) *cobra.Command {
 		},
 	}
 	cmd.AddCommand(
-		newAcceptCommand(dockerCli),
 		newDemoteCommand(dockerCli),
 		newInspectCommand(dockerCli),
 		newListCommand(dockerCli),

+ 2 - 4
api/client/node/list.go

@@ -16,7 +16,7 @@ import (
 )
 
 const (
-	listItemFmt = "%s\t%s\t%s\t%s\t%s\t%s\n"
+	listItemFmt = "%s\t%s\t%s\t%s\t%s\n"
 )
 
 type listOptions struct {
@@ -74,11 +74,10 @@ func printTable(out io.Writer, nodes []swarm.Node, info types.Info) {
 	// Ignore flushing errors
 	defer writer.Flush()
 
-	fmt.Fprintf(writer, listItemFmt, "ID", "HOSTNAME", "MEMBERSHIP", "STATUS", "AVAILABILITY", "MANAGER STATUS")
+	fmt.Fprintf(writer, listItemFmt, "ID", "HOSTNAME", "STATUS", "AVAILABILITY", "MANAGER STATUS")
 	for _, node := range nodes {
 		name := node.Description.Hostname
 		availability := string(node.Spec.Availability)
-		membership := string(node.Spec.Membership)
 
 		reachability := ""
 		if node.ManagerStatus != nil {
@@ -99,7 +98,6 @@ func printTable(out io.Writer, nodes []swarm.Node, info types.Info) {
 			listItemFmt,
 			ID,
 			name,
-			client.PrettyPrint(membership),
 			client.PrettyPrint(string(node.Status.State)),
 			client.PrettyPrint(availability),
 			client.PrettyPrint(reachability))

+ 0 - 9
api/client/node/opts.go

@@ -12,7 +12,6 @@ import (
 type nodeOptions struct {
 	annotations
 	role         string
-	membership   string
 	availability string
 }
 
@@ -45,14 +44,6 @@ func (opts *nodeOptions) ToNodeSpec() (swarm.NodeSpec, error) {
 		return swarm.NodeSpec{}, fmt.Errorf("invalid role %q, only worker and manager are supported", opts.role)
 	}
 
-	switch swarm.NodeMembership(strings.ToLower(opts.membership)) {
-	case swarm.NodeMembershipAccepted:
-		spec.Membership = swarm.NodeMembershipAccepted
-	case "":
-	default:
-		return swarm.NodeSpec{}, fmt.Errorf("invalid membership %q, only accepted is supported", opts.membership)
-	}
-
 	switch swarm.NodeAvailability(strings.ToLower(opts.availability)) {
 	case swarm.NodeAvailabilityActive:
 		spec.Availability = swarm.NodeAvailabilityActive

+ 0 - 9
api/client/node/update.go

@@ -27,7 +27,6 @@ func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
 
 	flags := cmd.Flags()
 	flags.StringVar(&nodeOpts.role, flagRole, "", "Role of the node (worker/manager)")
-	flags.StringVar(&nodeOpts.membership, flagMembership, "", "Membership of the node (accepted/rejected)")
 	flags.StringVar(&nodeOpts.availability, flagAvailability, "", "Availability of the node (active/pause/drain)")
 	flags.Var(&nodeOpts.annotations.labels, flagLabelAdd, "Add or update a node label (key=value)")
 	labelKeys := opts.NewListOpts(nil)
@@ -76,13 +75,6 @@ func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) error {
 			}
 			spec.Role = swarm.NodeRole(str)
 		}
-		if flags.Changed(flagMembership) {
-			str, err := flags.GetString(flagMembership)
-			if err != nil {
-				return err
-			}
-			spec.Membership = swarm.NodeMembership(str)
-		}
 		if flags.Changed(flagAvailability) {
 			str, err := flags.GetString(flagAvailability)
 			if err != nil {
@@ -115,7 +107,6 @@ func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) error {
 
 const (
 	flagRole         = "role"
-	flagMembership   = "membership"
 	flagAvailability = "availability"
 	flagLabelAdd     = "label-add"
 	flagLabelRemove  = "label-rm"

+ 1 - 1
api/client/service/opts.go

@@ -506,7 +506,7 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
 
 	flags.StringVar(&opts.endpoint.mode, flagEndpointMode, "", "Endpoint mode (vip or dnsrr)")
 
-	flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to Swarm agents")
+	flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to swarm agents")
 
 	flags.StringVar(&opts.logDriver.name, flagLogDriver, "", "Logging driver for service")
 	flags.Var(&opts.logDriver.opts, flagLogOpt, "Logging driver options")

+ 1 - 0
api/client/swarm/cmd.go

@@ -25,6 +25,7 @@ func NewSwarmCommand(dockerCli *client.DockerCli) *cobra.Command {
 		newUpdateCommand(dockerCli),
 		newLeaveCommand(dockerCli),
 		newInspectCommand(dockerCli),
+		newJoinTokenCommand(dockerCli),
 	)
 	return cmd
 }

+ 2 - 30
api/client/swarm/init.go

@@ -28,14 +28,11 @@ type initOptions struct {
 func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
 	opts := initOptions{
 		listenAddr: NewListenAddrOption(),
-		swarmOptions: swarmOptions{
-			autoAccept: NewAutoAcceptOption(),
-		},
 	}
 
 	cmd := &cobra.Command{
 		Use:   "init [OPTIONS]",
-		Short: "Initialize a Swarm",
+		Short: "Initialize a swarm",
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runInit(dockerCli, cmd.Flags(), opts)
@@ -53,12 +50,6 @@ func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions
 	client := dockerCli.Client()
 	ctx := context.Background()
 
-	// If no secret was specified, we create a random one
-	if !flags.Changed("secret") {
-		opts.secret = generateRandomSecret()
-		fmt.Fprintf(dockerCli.Out(), "No --secret provided. Generated random secret:\n    %s\n\n", opts.secret)
-	}
-
 	req := swarm.InitRequest{
 		ListenAddr:      opts.listenAddr.String(),
 		ForceNewCluster: opts.forceNewCluster,
@@ -72,24 +63,5 @@ func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions
 
 	fmt.Fprintf(dockerCli.Out(), "Swarm initialized: current node (%s) is now a manager.\n\n", nodeID)
 
-	// Fetch CAHash and Address from the API
-	info, err := client.Info(ctx)
-	if err != nil {
-		return err
-	}
-
-	node, _, err := client.NodeInspectWithRaw(ctx, nodeID)
-	if err != nil {
-		return err
-	}
-
-	if node.ManagerStatus != nil && info.Swarm.CACertHash != "" {
-		var secretArgs string
-		if opts.secret != "" {
-			secretArgs = "--secret " + opts.secret
-		}
-		fmt.Fprintf(dockerCli.Out(), "To add a worker to this swarm, run the following command:\n    docker swarm join %s \\\n    --ca-hash %s \\\n    %s\n", secretArgs, info.Swarm.CACertHash, node.ManagerStatus.Addr)
-	}
-
-	return nil
+	return printJoinCommand(ctx, dockerCli, nodeID, true, true)
 }

+ 1 - 1
api/client/swarm/inspect.go

@@ -18,7 +18,7 @@ func newInspectCommand(dockerCli *client.DockerCli) *cobra.Command {
 
 	cmd := &cobra.Command{
 		Use:   "inspect [OPTIONS]",
-		Short: "Inspect the Swarm",
+		Short: "Inspect the swarm",
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runInspect(dockerCli, opts)

+ 19 - 13
api/client/swarm/join.go

@@ -2,6 +2,7 @@ package swarm
 
 import (
 	"fmt"
+	"strings"
 
 	"github.com/docker/docker/api/client"
 	"github.com/docker/docker/cli"
@@ -13,9 +14,7 @@ import (
 type joinOptions struct {
 	remote     string
 	listenAddr NodeAddrOption
-	manager    bool
-	secret     string
-	CACertHash string
+	token      string
 }
 
 func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
@@ -25,7 +24,7 @@ func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
 
 	cmd := &cobra.Command{
 		Use:   "join [OPTIONS] HOST:PORT",
-		Short: "Join a Swarm as a node and/or manager",
+		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]
@@ -35,9 +34,7 @@ func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
 
 	flags := cmd.Flags()
 	flags.Var(&opts.listenAddr, flagListenAddr, "Listen address")
-	flags.BoolVar(&opts.manager, "manager", false, "Try joining as a manager.")
-	flags.StringVar(&opts.secret, flagSecret, "", "Secret for node acceptance")
-	flags.StringVar(&opts.CACertHash, "ca-hash", "", "Hash of the Root Certificate Authority certificate used for trusted join")
+	flags.StringVar(&opts.token, flagToken, "", "Token for entry into the swarm")
 	return cmd
 }
 
@@ -46,20 +43,29 @@ func runJoin(dockerCli *client.DockerCli, opts joinOptions) error {
 	ctx := context.Background()
 
 	req := swarm.JoinRequest{
-		Manager:     opts.manager,
-		Secret:      opts.secret,
+		JoinToken:   opts.token,
 		ListenAddr:  opts.listenAddr.String(),
 		RemoteAddrs: []string{opts.remote},
-		CACertHash:  opts.CACertHash,
 	}
 	err := client.SwarmJoin(ctx, req)
 	if err != nil {
 		return err
 	}
-	if opts.manager {
-		fmt.Fprintln(dockerCli.Out(), "This node joined a Swarm as a manager.")
+
+	info, err := client.Info(ctx)
+	if err != nil {
+		return err
+	}
+
+	_, _, err = client.NodeInspectWithRaw(ctx, info.Swarm.NodeID)
+	if err != nil {
+		// TODO(aaronl): is there a better way to do this?
+		if strings.Contains(err.Error(), "This node is not a swarm manager.") {
+			fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a worker.")
+		}
 	} else {
-		fmt.Fprintln(dockerCli.Out(), "This node joined a Swarm as a worker.")
+		fmt.Fprintln(dockerCli.Out(), "This node joined a swarm as a manager.")
 	}
+
 	return nil
 }

+ 110 - 0
api/client/swarm/join_token.go

@@ -0,0 +1,110 @@
+package swarm
+
+import (
+	"errors"
+	"fmt"
+
+	"github.com/spf13/cobra"
+
+	"github.com/docker/docker/api/client"
+	"github.com/docker/docker/cli"
+	"github.com/docker/engine-api/types/swarm"
+	"golang.org/x/net/context"
+)
+
+const (
+	flagRotate = "rotate"
+	flagQuiet  = "quiet"
+)
+
+func newJoinTokenCommand(dockerCli *client.DockerCli) *cobra.Command {
+	var rotate, quiet bool
+
+	cmd := &cobra.Command{
+		Use:   "join-token [-q] [--rotate] (worker|manager)",
+		Short: "Manage join tokens",
+		Args:  cli.ExactArgs(1),
+		RunE: func(cmd *cobra.Command, args []string) error {
+			if args[0] != "worker" && args[0] != "manager" {
+				return errors.New("unknown role " + args[0])
+			}
+
+			client := dockerCli.Client()
+			ctx := context.Background()
+
+			if rotate {
+				var flags swarm.UpdateFlags
+
+				swarm, err := client.SwarmInspect(ctx)
+				if err != nil {
+					return err
+				}
+
+				if args[0] == "worker" {
+					flags.RotateWorkerToken = true
+				} else if args[0] == "manager" {
+					flags.RotateManagerToken = true
+				}
+
+				err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec, flags)
+				if err != nil {
+					return err
+				}
+			}
+
+			swarm, err := client.SwarmInspect(ctx)
+			if err != nil {
+				return err
+			}
+
+			if quiet {
+				if args[0] == "worker" {
+					fmt.Fprintln(dockerCli.Out(), swarm.JoinTokens.Worker)
+				} else if args[0] == "manager" {
+					fmt.Fprintln(dockerCli.Out(), swarm.JoinTokens.Manager)
+				}
+			} else {
+				info, err := client.Info(ctx)
+				if err != nil {
+					return err
+				}
+				return printJoinCommand(ctx, dockerCli, info.Swarm.NodeID, args[0] == "worker", args[0] == "manager")
+			}
+			return nil
+		},
+	}
+
+	flags := cmd.Flags()
+	flags.BoolVar(&rotate, flagRotate, false, "Rotate join token")
+	flags.BoolVarP(&quiet, flagQuiet, "q", false, "Only display token")
+
+	return cmd
+}
+
+func printJoinCommand(ctx context.Context, dockerCli *client.DockerCli, nodeID string, worker bool, manager bool) error {
+	client := dockerCli.Client()
+
+	swarm, err := client.SwarmInspect(ctx)
+	if err != nil {
+		return err
+	}
+
+	node, _, err := client.NodeInspectWithRaw(ctx, nodeID)
+	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    docker swarm join \\\n    --token %s \\\n    %s\n", swarm.JoinTokens.Worker, node.ManagerStatus.Addr)
+		}
+		if manager {
+			if worker {
+				fmt.Fprintln(dockerCli.Out())
+			}
+			fmt.Fprintf(dockerCli.Out(), "To add a manager to this swarm, run the following command:\n    docker swarm join \\\n    --token %s \\\n    %s\n", swarm.JoinTokens.Manager, node.ManagerStatus.Addr)
+		}
+	}
+
+	return nil
+}

+ 1 - 1
api/client/swarm/leave.go

@@ -19,7 +19,7 @@ func newLeaveCommand(dockerCli *client.DockerCli) *cobra.Command {
 
 	cmd := &cobra.Command{
 		Use:   "leave [OPTIONS]",
-		Short: "Leave a Swarm",
+		Short: "Leave a swarm",
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runLeave(dockerCli, opts)

+ 1 - 87
api/client/swarm/opts.go

@@ -15,29 +15,15 @@ import (
 const (
 	defaultListenAddr = "0.0.0.0:2377"
 
-	worker  = "WORKER"
-	manager = "MANAGER"
-	none    = "NONE"
-
-	flagAutoAccept          = "auto-accept"
 	flagCertExpiry          = "cert-expiry"
 	flagDispatcherHeartbeat = "dispatcher-heartbeat"
 	flagListenAddr          = "listen-addr"
-	flagSecret              = "secret"
+	flagToken               = "token"
 	flagTaskHistoryLimit    = "task-history-limit"
 	flagExternalCA          = "external-ca"
 )
 
-var (
-	defaultPolicies = []swarm.Policy{
-		{Role: worker, Autoaccept: true},
-		{Role: manager, Autoaccept: false},
-	}
-)
-
 type swarmOptions struct {
-	autoAccept          AutoAcceptOption
-	secret              string
 	taskHistoryLimit    int64
 	dispatcherHeartbeat time.Duration
 	nodeCertExpiry      time.Duration
@@ -84,71 +70,6 @@ func NewListenAddrOption() NodeAddrOption {
 	return NewNodeAddrOption(defaultListenAddr)
 }
 
-// AutoAcceptOption is a value type for auto-accept policy
-type AutoAcceptOption struct {
-	values map[string]struct{}
-}
-
-// String prints a string representation of this option
-func (o *AutoAcceptOption) String() string {
-	keys := []string{}
-	for key := range o.values {
-		keys = append(keys, fmt.Sprintf("%s=true", strings.ToLower(key)))
-	}
-	return strings.Join(keys, ", ")
-}
-
-// Set sets a new value on this option
-func (o *AutoAcceptOption) Set(acceptValues string) error {
-	for _, value := range strings.Split(acceptValues, ",") {
-		value = strings.ToUpper(value)
-		switch value {
-		case none, worker, manager:
-			o.values[value] = struct{}{}
-		default:
-			return fmt.Errorf("must be one / combination of %s, %s; or NONE", worker, manager)
-		}
-	}
-	// NONE must stand alone, so if any non-NONE setting exist with it, error with conflict
-	if o.isPresent(none) && len(o.values) > 1 {
-		return fmt.Errorf("value NONE cannot be specified alongside other node types")
-	}
-	return nil
-}
-
-// Type returns the type of this option
-func (o *AutoAcceptOption) Type() string {
-	return "auto-accept"
-}
-
-// Policies returns a representation of this option for the api
-func (o *AutoAcceptOption) Policies(secret *string) []swarm.Policy {
-	policies := []swarm.Policy{}
-	for _, p := range defaultPolicies {
-		if len(o.values) != 0 {
-			if _, ok := o.values[string(p.Role)]; ok {
-				p.Autoaccept = true
-			} else {
-				p.Autoaccept = false
-			}
-		}
-		p.Secret = secret
-		policies = append(policies, p)
-	}
-	return policies
-}
-
-// isPresent returns whether the key exists in the set or not
-func (o *AutoAcceptOption) isPresent(key string) bool {
-	_, c := o.values[key]
-	return c
-}
-
-// NewAutoAcceptOption returns a new auto-accept option
-func NewAutoAcceptOption() AutoAcceptOption {
-	return AutoAcceptOption{values: make(map[string]struct{})}
-}
-
 // ExternalCAOption is a Value type for parsing external CA specifications.
 type ExternalCAOption struct {
 	values []*swarm.ExternalCA
@@ -239,8 +160,6 @@ func parseExternalCA(caSpec string) (*swarm.ExternalCA, error) {
 }
 
 func addSwarmFlags(flags *pflag.FlagSet, opts *swarmOptions) {
-	flags.Var(&opts.autoAccept, flagAutoAccept, "Auto acceptance policy (worker, manager or none)")
-	flags.StringVar(&opts.secret, flagSecret, "", "Set secret value needed to join a cluster")
 	flags.Int64Var(&opts.taskHistoryLimit, flagTaskHistoryLimit, 10, "Task history retention limit")
 	flags.DurationVar(&opts.dispatcherHeartbeat, flagDispatcherHeartbeat, time.Duration(5*time.Second), "Dispatcher heartbeat period")
 	flags.DurationVar(&opts.nodeCertExpiry, flagCertExpiry, time.Duration(90*24*time.Hour), "Validity period for node certificates")
@@ -249,11 +168,6 @@ func addSwarmFlags(flags *pflag.FlagSet, opts *swarmOptions) {
 
 func (opts *swarmOptions) ToSpec() swarm.Spec {
 	spec := swarm.Spec{}
-	if opts.secret != "" {
-		spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(&opts.secret)
-	} else {
-		spec.AcceptancePolicy.Policies = opts.autoAccept.Policies(nil)
-	}
 	spec.Orchestration.TaskHistoryRetentionLimit = opts.taskHistoryLimit
 	spec.Dispatcher.HeartbeatPeriod = uint64(opts.dispatcherHeartbeat.Nanoseconds())
 	spec.CAConfig.NodeCertExpiry = opts.nodeCertExpiry

+ 0 - 99
api/client/swarm/opts_test.go

@@ -4,7 +4,6 @@ import (
 	"testing"
 
 	"github.com/docker/docker/pkg/testutil/assert"
-	"github.com/docker/engine-api/types/swarm"
 )
 
 func TestNodeAddrOptionSetHostAndPort(t *testing.T) {
@@ -36,101 +35,3 @@ func TestNodeAddrOptionSetInvalidFormat(t *testing.T) {
 	opt := NewListenAddrOption()
 	assert.Error(t, opt.Set("http://localhost:4545"), "Invalid")
 }
-
-func TestAutoAcceptOptionSetWorker(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.NilError(t, opt.Set("worker"))
-	assert.Equal(t, opt.isPresent(worker), true)
-}
-
-func TestAutoAcceptOptionSetManager(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.NilError(t, opt.Set("manager"))
-	assert.Equal(t, opt.isPresent(manager), true)
-}
-
-func TestAutoAcceptOptionSetInvalid(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.Error(t, opt.Set("bogus"), "must be one / combination")
-}
-
-func TestAutoAcceptOptionSetEmpty(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.Error(t, opt.Set(""), "must be one / combination")
-}
-
-func TestAutoAcceptOptionSetNone(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.NilError(t, opt.Set("none"))
-	assert.Equal(t, opt.isPresent(manager), false)
-	assert.Equal(t, opt.isPresent(worker), false)
-}
-
-func TestAutoAcceptOptionSetTwo(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.NilError(t, opt.Set("worker,manager"))
-	assert.Equal(t, opt.isPresent(manager), true)
-	assert.Equal(t, opt.isPresent(worker), true)
-}
-
-func TestAutoAcceptOptionSetConflict(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.Error(t, opt.Set("none,manager"), "value NONE cannot be specified alongside other node types")
-
-	opt = NewAutoAcceptOption()
-	assert.Error(t, opt.Set("none,worker"), "value NONE cannot be specified alongside other node types")
-
-	opt = NewAutoAcceptOption()
-	assert.Error(t, opt.Set("worker,none,manager"), "value NONE cannot be specified alongside other node types")
-
-	opt = NewAutoAcceptOption()
-	assert.Error(t, opt.Set("worker,manager,none"), "value NONE cannot be specified alongside other node types")
-}
-
-func TestAutoAcceptOptionPoliciesDefault(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	secret := "thesecret"
-
-	policies := opt.Policies(&secret)
-	assert.Equal(t, len(policies), 2)
-	assert.Equal(t, policies[0], swarm.Policy{
-		Role:       worker,
-		Autoaccept: true,
-		Secret:     &secret,
-	})
-	assert.Equal(t, policies[1], swarm.Policy{
-		Role:       manager,
-		Autoaccept: false,
-		Secret:     &secret,
-	})
-}
-
-func TestAutoAcceptOptionPoliciesWithManager(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	secret := "thesecret"
-
-	assert.NilError(t, opt.Set("manager"))
-
-	policies := opt.Policies(&secret)
-	assert.Equal(t, len(policies), 2)
-	assert.Equal(t, policies[0], swarm.Policy{
-		Role:       worker,
-		Autoaccept: false,
-		Secret:     &secret,
-	})
-	assert.Equal(t, policies[1], swarm.Policy{
-		Role:       manager,
-		Autoaccept: true,
-		Secret:     &secret,
-	})
-}
-
-func TestAutoAcceptOptionString(t *testing.T) {
-	opt := NewAutoAcceptOption()
-	assert.NilError(t, opt.Set("manager"))
-	assert.NilError(t, opt.Set("worker"))
-
-	repr := opt.String()
-	assert.Contains(t, repr, "worker=true")
-	assert.Contains(t, repr, "manager=true")
-}

+ 0 - 19
api/client/swarm/secret.go

@@ -1,19 +0,0 @@
-package swarm
-
-import (
-	cryptorand "crypto/rand"
-	"fmt"
-	"math/big"
-)
-
-func generateRandomSecret() string {
-	var secretBytes [generatedSecretEntropyBytes]byte
-
-	if _, err := cryptorand.Read(secretBytes[:]); err != nil {
-		panic(fmt.Errorf("failed to read random bytes: %v", err))
-	}
-
-	var nn big.Int
-	nn.SetBytes(secretBytes[:])
-	return fmt.Sprintf("%0[1]*s", maxGeneratedSecretLength, nn.Text(generatedSecretBase))
-}

+ 5 - 18
api/client/swarm/update.go

@@ -13,11 +13,11 @@ import (
 )
 
 func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
-	opts := swarmOptions{autoAccept: NewAutoAcceptOption()}
+	opts := swarmOptions{}
 
 	cmd := &cobra.Command{
 		Use:   "update [OPTIONS]",
-		Short: "Update the Swarm",
+		Short: "Update the swarm",
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runUpdate(dockerCli, cmd.Flags(), opts)
@@ -32,6 +32,8 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts swarmOpti
 	client := dockerCli.Client()
 	ctx := context.Background()
 
+	var updateFlags swarm.UpdateFlags
+
 	swarm, err := client.SwarmInspect(ctx)
 	if err != nil {
 		return err
@@ -42,7 +44,7 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts swarmOpti
 		return err
 	}
 
-	err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec)
+	err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec, updateFlags)
 	if err != nil {
 		return err
 	}
@@ -55,21 +57,6 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts swarmOpti
 func mergeSwarm(swarm *swarm.Swarm, flags *pflag.FlagSet) error {
 	spec := &swarm.Spec
 
-	if flags.Changed(flagAutoAccept) {
-		value := flags.Lookup(flagAutoAccept).Value.(*AutoAcceptOption)
-		spec.AcceptancePolicy.Policies = value.Policies(nil)
-	}
-
-	var psecret *string
-	if flags.Changed(flagSecret) {
-		secret, _ := flags.GetString(flagSecret)
-		psecret = &secret
-	}
-
-	for i := range spec.AcceptancePolicy.Policies {
-		spec.AcceptancePolicy.Policies[i].Secret = psecret
-	}
-
 	if flags.Changed(flagTaskHistoryLimit) {
 		spec.Orchestration.TaskHistoryRetentionLimit, _ = flags.GetInt64(flagTaskHistoryLimit)
 	}

+ 0 - 1
api/client/system/info.go

@@ -85,7 +85,6 @@ func runInfo(dockerCli *client.DockerCli) error {
 		if info.Swarm.ControlAvailable {
 			fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers)
 			fmt.Fprintf(dockerCli.Out(), " Nodes: %d\n", info.Swarm.Nodes)
-			ioutils.FprintfIfNotEmpty(dockerCli.Out(), " CA Certificate Hash: %s\n", info.Swarm.CACertHash)
 		}
 	}
 

+ 1 - 1
api/server/router/swarm/backend.go

@@ -11,7 +11,7 @@ type Backend interface {
 	Join(req types.JoinRequest) error
 	Leave(force bool) error
 	Inspect() (types.Swarm, error)
-	Update(uint64, types.Spec) error
+	Update(uint64, types.Spec, types.UpdateFlags) error
 	GetServices(basictypes.ServiceListOptions) ([]types.Service, error)
 	GetService(string) (types.Service, error)
 	CreateService(types.ServiceSpec, string) (string, error)

+ 9 - 1
api/server/router/swarm/cluster_routes.go

@@ -66,7 +66,15 @@ func (sr *swarmRouter) updateCluster(ctx context.Context, w http.ResponseWriter,
 		return fmt.Errorf("Invalid swarm version '%s': %s", rawVersion, err.Error())
 	}
 
-	if err := sr.backend.Update(version, swarm); err != nil {
+	var flags types.UpdateFlags
+	if r.URL.Query().Get("rotate_worker_token") == "true" {
+		flags.RotateWorkerToken = true
+	}
+	if r.URL.Query().Get("rotate_manager_token") == "true" {
+		flags.RotateManagerToken = true
+	}
+
+	if err := sr.backend.Update(version, swarm, flags); err != nil {
 		logrus.Errorf("Error configuring swarm: %v", err)
 		return err
 	}

+ 6 - 6
contrib/completion/zsh/_docker

@@ -1087,7 +1087,7 @@ __docker_service_subcommand() {
         "($help)--name=[Service name]:name: "
         "($help)*--network=[Network attachments]:network: "
         "($help)*"{-p=,--publish=}"[Publish a port as a node port]:port: "
-        "($help)--registry-auth[Send registry authentication details to Swarm agents]"
+        "($help)--registry-auth[Send registry authentication details to swarm agents]"
         "($help)--replicas=[Number of tasks]:replicas: "
         "($help)--reserve-cpu=[Reserve CPUs]:value: "
         "($help)--reserve-memory=[Reserve Memory]:value: "
@@ -1185,11 +1185,11 @@ __docker_service_subcommand() {
 __docker_swarm_commands() {
     local -a _docker_swarm_subcommands
     _docker_swarm_subcommands=(
-        "init:Initialize a Swarm"
-        "inspect:Inspect the Swarm"
-        "join:Join a Swarm as a node and/or manager"
-        "leave:Leave a Swarm"
-        "update:Update the Swarm"
+        "init:Initialize a swarm"
+        "inspect:Inspect the swarm"
+        "join:Join a swarm as a node and/or manager"
+        "leave:Leave a swarm"
+        "update:Update the swarm"
     )
     _describe -t docker-swarm-commands "docker swarm command" _docker_swarm_subcommands
 }

+ 33 - 56
daemon/cluster/cluster.go

@@ -13,7 +13,6 @@ import (
 	"google.golang.org/grpc"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/digest"
 	"github.com/docker/docker/daemon/cluster/convert"
 	executorpkg "github.com/docker/docker/daemon/cluster/executor"
 	"github.com/docker/docker/daemon/cluster/executor/container"
@@ -42,16 +41,16 @@ const (
 )
 
 // ErrNoSwarm is returned on leaving a cluster that was never initialized
-var ErrNoSwarm = fmt.Errorf("This node is not part of Swarm")
+var ErrNoSwarm = fmt.Errorf("This node is not part of swarm")
 
 // ErrSwarmExists is returned on initialize or join request for a cluster that has already been activated
-var ErrSwarmExists = fmt.Errorf("This node is already part of a Swarm cluster. Use \"docker swarm leave\" to leave this cluster and join another one.")
+var ErrSwarmExists = fmt.Errorf("This node is already part of a swarm cluster. Use \"docker swarm leave\" to leave this cluster and join another one.")
 
 // ErrPendingSwarmExists is returned on initialize or join request for a cluster that is already processing a similar request but has not succeeded yet.
 var ErrPendingSwarmExists = fmt.Errorf("This node is processing an existing join request that has not succeeded yet. Use \"docker swarm leave\" to cancel the current request.")
 
 // ErrSwarmJoinTimeoutReached is returned when cluster join could not complete before timeout was reached.
-var ErrSwarmJoinTimeoutReached = fmt.Errorf("Timeout was reached before node was joined. Attempt to join the cluster will continue in the background. Use \"docker info\" command to see the current Swarm status of your node.")
+var ErrSwarmJoinTimeoutReached = fmt.Errorf("Timeout was reached before node was joined. Attempt to join the cluster will continue in the background. Use \"docker info\" command to see the current swarm status of your node.")
 
 // defaultSpec contains some sane defaults if cluster options are missing on init
 var defaultSpec = types.Spec{
@@ -127,7 +126,7 @@ func New(config Config) (*Cluster, error) {
 		return nil, err
 	}
 
-	n, err := c.startNewNode(false, st.ListenAddr, "", "", "", false)
+	n, err := c.startNewNode(false, st.ListenAddr, "", "")
 	if err != nil {
 		return nil, err
 	}
@@ -196,7 +195,7 @@ func (c *Cluster) reconnectOnFailure(n *node) {
 			return
 		}
 		var err error
-		n, err = c.startNewNode(false, c.listenAddr, c.getRemoteAddress(), "", "", false)
+		n, err = c.startNewNode(false, c.listenAddr, c.getRemoteAddress(), "")
 		if err != nil {
 			c.err = err
 			close(n.done)
@@ -205,7 +204,7 @@ func (c *Cluster) reconnectOnFailure(n *node) {
 	}
 }
 
-func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secret, cahash string, ismanager bool) (*node, error) {
+func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, joinToken string) (*node, error) {
 	if err := c.config.Backend.IsSwarmCompatible(); err != nil {
 		return nil, err
 	}
@@ -219,12 +218,10 @@ func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secre
 		ListenRemoteAPI:  listenAddr,
 		JoinAddr:         joinAddr,
 		StateDir:         c.root,
-		CAHash:           cahash,
-		Secret:           secret,
+		JoinToken:        joinToken,
 		Executor:         container.NewExecutor(c.config.Backend),
 		HeartbeatTick:    1,
 		ElectionTick:     3,
-		IsManager:        ismanager,
 	})
 	if err != nil {
 		return nil, err
@@ -291,7 +288,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
 	if node := c.node; node != nil {
 		if !req.ForceNewCluster {
 			c.Unlock()
-			return "", errSwarmExists(node)
+			return "", ErrSwarmExists
 		}
 		if err := c.stopNode(); err != nil {
 			c.Unlock()
@@ -305,7 +302,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
 	}
 
 	// todo: check current state existing
-	n, err := c.startNewNode(req.ForceNewCluster, req.ListenAddr, "", "", "", false)
+	n, err := c.startNewNode(req.ForceNewCluster, req.ListenAddr, "", "")
 	if err != nil {
 		c.Unlock()
 		return "", err
@@ -336,40 +333,32 @@ func (c *Cluster) Join(req types.JoinRequest) error {
 	c.Lock()
 	if node := c.node; node != nil {
 		c.Unlock()
-		return errSwarmExists(node)
+		return ErrSwarmExists
 	}
 	if err := validateAndSanitizeJoinRequest(&req); err != nil {
 		c.Unlock()
 		return err
 	}
 	// todo: check current state existing
-	n, err := c.startNewNode(false, req.ListenAddr, req.RemoteAddrs[0], req.Secret, req.CACertHash, req.Manager)
+	n, err := c.startNewNode(false, req.ListenAddr, req.RemoteAddrs[0], req.JoinToken)
 	if err != nil {
 		c.Unlock()
 		return err
 	}
 	c.Unlock()
 
-	certificateRequested := n.CertificateRequested()
-	for {
-		select {
-		case <-certificateRequested:
-			if n.NodeMembership() == swarmapi.NodeMembershipPending {
-				return fmt.Errorf("Your node is in the process of joining the cluster but needs to be accepted by existing cluster member.\nTo accept this node into cluster run \"docker node accept %v\" in an existing cluster manager. Use \"docker info\" command to see the current Swarm status of your node.", n.NodeID())
-			}
-			certificateRequested = nil
-		case <-time.After(swarmConnectTimeout):
-			// attempt to connect will continue in background, also reconnecting
-			go c.reconnectOnFailure(n)
-			return ErrSwarmJoinTimeoutReached
-		case <-n.Ready():
-			go c.reconnectOnFailure(n)
-			return nil
-		case <-n.done:
-			c.RLock()
-			defer c.RUnlock()
-			return c.err
-		}
+	select {
+	case <-time.After(swarmConnectTimeout):
+		// attempt to connect will continue in background, also reconnecting
+		go c.reconnectOnFailure(n)
+		return ErrSwarmJoinTimeoutReached
+	case <-n.Ready():
+		go c.reconnectOnFailure(n)
+		return nil
+	case <-n.done:
+		c.RLock()
+		defer c.RUnlock()
+		return c.err
 	}
 }
 
@@ -489,7 +478,7 @@ func (c *Cluster) Inspect() (types.Swarm, error) {
 }
 
 // Update updates configuration of a managed swarm cluster.
-func (c *Cluster) Update(version uint64, spec types.Spec) error {
+func (c *Cluster) Update(version uint64, spec types.Spec, flags types.UpdateFlags) error {
 	c.RLock()
 	defer c.RUnlock()
 
@@ -505,7 +494,7 @@ func (c *Cluster) Update(version uint64, spec types.Spec) error {
 		return err
 	}
 
-	swarmSpec, err := convert.SwarmSpecToGRPCandMerge(spec, &swarm.Spec)
+	swarmSpec, err := convert.SwarmSpecToGRPC(spec)
 	if err != nil {
 		return err
 	}
@@ -518,6 +507,10 @@ func (c *Cluster) Update(version uint64, spec types.Spec) error {
 			ClusterVersion: &swarmapi.Version{
 				Index: version,
 			},
+			Rotation: swarmapi.JoinTokenRotation{
+				RotateWorkerToken:  flags.RotateWorkerToken,
+				RotateManagerToken: flags.RotateManagerToken,
+			},
 		},
 	)
 	return err
@@ -611,10 +604,6 @@ func (c *Cluster) Info() types.Info {
 				}
 			}
 		}
-
-		if swarm, err := getSwarm(ctx, c.client); err == nil && swarm != nil {
-			info.CACertHash = swarm.RootCA.CACertHash
-		}
 	}
 
 	if c.node != nil {
@@ -636,12 +625,12 @@ func (c *Cluster) isActiveManager() bool {
 // Call with read lock.
 func (c *Cluster) errNoManager() error {
 	if c.node == nil {
-		return fmt.Errorf("This node is not a Swarm manager. Use \"docker swarm init\" or \"docker swarm join --manager\" to connect this node to Swarm and try again.")
+		return fmt.Errorf("This node is not a swarm manager. Use \"docker swarm init\" or \"docker swarm join --manager\" to connect this node to swarm and try again.")
 	}
 	if c.node.Manager() != nil {
-		return fmt.Errorf("This node is not a Swarm manager. Manager is being prepared or has trouble connecting to the cluster.")
+		return fmt.Errorf("This node is not a swarm manager. Manager is being prepared or has trouble connecting to the cluster.")
 	}
-	return fmt.Errorf("This node is not a Swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.")
+	return fmt.Errorf("This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state. Please run this command on a manager node or promote the current node to a manager.")
 }
 
 // GetServices returns all services of a managed swarm cluster.
@@ -1219,11 +1208,6 @@ func validateAndSanitizeJoinRequest(req *types.JoinRequest) error {
 			return fmt.Errorf("invalid remoteAddr %q: %v", req.RemoteAddrs[i], err)
 		}
 	}
-	if req.CACertHash != "" {
-		if _, err := digest.ParseDigest(req.CACertHash); err != nil {
-			return fmt.Errorf("invalid CACertHash %q, %v", req.CACertHash, err)
-		}
-	}
 	return nil
 }
 
@@ -1238,13 +1222,6 @@ func validateAddr(addr string) (string, error) {
 	return strings.TrimPrefix(newaddr, "tcp://"), nil
 }
 
-func errSwarmExists(node *node) error {
-	if node.NodeMembership() != swarmapi.NodeMembershipAccepted {
-		return ErrPendingSwarmExists
-	}
-	return ErrSwarmExists
-}
-
 func initClusterSpec(node *node, spec types.Spec) error {
 	ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
 	for conn := range node.ListenControlSocket(ctx) {
@@ -1269,7 +1246,7 @@ func initClusterSpec(node *node, spec types.Spec) error {
 				cluster = lcr.Clusters[0]
 				break
 			}
-			newspec, err := convert.SwarmSpecToGRPCandMerge(spec, &cluster.Spec)
+			newspec, err := convert.SwarmSpecToGRPC(spec)
 			if err != nil {
 				return fmt.Errorf("error updating cluster settings: %v", err)
 			}

+ 0 - 7
daemon/cluster/convert/node.go

@@ -15,7 +15,6 @@ func NodeFromGRPC(n swarmapi.Node) types.Node {
 		ID: n.ID,
 		Spec: types.NodeSpec{
 			Role:         types.NodeRole(strings.ToLower(n.Spec.Role.String())),
-			Membership:   types.NodeMembership(strings.ToLower(n.Spec.Membership.String())),
 			Availability: types.NodeAvailability(strings.ToLower(n.Spec.Availability.String())),
 		},
 		Status: types.NodeStatus{
@@ -79,12 +78,6 @@ func NodeSpecToGRPC(s types.NodeSpec) (swarmapi.NodeSpec, error) {
 		return swarmapi.NodeSpec{}, fmt.Errorf("invalid Role: %q", s.Role)
 	}
 
-	if membership, ok := swarmapi.NodeSpec_Membership_value[strings.ToUpper(string(s.Membership))]; ok {
-		spec.Membership = swarmapi.NodeSpec_Membership(membership)
-	} else {
-		return swarmapi.NodeSpec{}, fmt.Errorf("invalid Membership: %q", s.Membership)
-	}
-
 	if availability, ok := swarmapi.NodeSpec_Availability_value[strings.ToUpper(string(s.Availability))]; ok {
 		spec.Availability = swarmapi.NodeSpec_Availability(availability)
 	} else {

+ 6 - 74
daemon/cluster/convert/swarm.go

@@ -5,8 +5,6 @@ import (
 	"strings"
 	"time"
 
-	"golang.org/x/crypto/bcrypt"
-
 	types "github.com/docker/engine-api/types/swarm"
 	swarmapi "github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/protobuf/ptypes"
@@ -28,6 +26,10 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
 				ElectionTick:               c.Spec.Raft.ElectionTick,
 			},
 		},
+		JoinTokens: types.JoinTokens{
+			Worker:  c.RootCA.JoinTokens.Worker,
+			Manager: c.RootCA.JoinTokens.Manager,
+		},
 	}
 
 	heartbeatPeriod, _ := ptypes.Duration(c.Spec.Dispatcher.HeartbeatPeriod)
@@ -52,23 +54,11 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
 	swarm.Spec.Name = c.Spec.Annotations.Name
 	swarm.Spec.Labels = c.Spec.Annotations.Labels
 
-	for _, policy := range c.Spec.AcceptancePolicy.Policies {
-		p := types.Policy{
-			Role:       types.NodeRole(strings.ToLower(policy.Role.String())),
-			Autoaccept: policy.Autoaccept,
-		}
-		if policy.Secret != nil {
-			secret := string(policy.Secret.Data)
-			p.Secret = &secret
-		}
-		swarm.Spec.AcceptancePolicy.Policies = append(swarm.Spec.AcceptancePolicy.Policies, p)
-	}
-
 	return swarm
 }
 
-// SwarmSpecToGRPCandMerge converts a Spec to a grpc ClusterSpec and merge AcceptancePolicy from an existing grpc ClusterSpec if provided.
-func SwarmSpecToGRPCandMerge(s types.Spec, existingSpec *swarmapi.ClusterSpec) (swarmapi.ClusterSpec, error) {
+// SwarmSpecToGRPC converts a Spec to a grpc ClusterSpec.
+func SwarmSpecToGRPC(s types.Spec) (swarmapi.ClusterSpec, error) {
 	spec := swarmapi.ClusterSpec{
 		Annotations: swarmapi.Annotations{
 			Name:   s.Name,
@@ -104,63 +94,5 @@ func SwarmSpecToGRPCandMerge(s types.Spec, existingSpec *swarmapi.ClusterSpec) (
 		})
 	}
 
-	if err := SwarmSpecUpdateAcceptancePolicy(&spec, s.AcceptancePolicy, existingSpec); err != nil {
-		return swarmapi.ClusterSpec{}, err
-	}
-
 	return spec, nil
 }
-
-// SwarmSpecUpdateAcceptancePolicy updates a grpc ClusterSpec using AcceptancePolicy.
-func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolicy types.AcceptancePolicy, oldSpec *swarmapi.ClusterSpec) error {
-	spec.AcceptancePolicy.Policies = nil
-	hashs := make(map[string][]byte)
-
-	for _, p := range acceptancePolicy.Policies {
-		role, ok := swarmapi.NodeRole_value[strings.ToUpper(string(p.Role))]
-		if !ok {
-			return fmt.Errorf("invalid Role: %q", p.Role)
-		}
-
-		policy := &swarmapi.AcceptancePolicy_RoleAdmissionPolicy{
-			Role:       swarmapi.NodeRole(role),
-			Autoaccept: p.Autoaccept,
-		}
-
-		if p.Secret != nil {
-			if *p.Secret == "" { // if provided secret is empty, it means erase previous secret.
-				policy.Secret = nil
-			} else { // if provided secret is not empty, we generate a new one.
-				hashPwd, ok := hashs[*p.Secret]
-				if !ok {
-					hashPwd, _ = bcrypt.GenerateFromPassword([]byte(*p.Secret), 0)
-					hashs[*p.Secret] = hashPwd
-				}
-				policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_Secret{
-					Data: hashPwd,
-					Alg:  "bcrypt",
-				}
-			}
-		} else if oldSecret := getOldSecret(oldSpec, policy.Role); oldSecret != nil { // else use the old one.
-			policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_Secret{
-				Data: oldSecret.Data,
-				Alg:  oldSecret.Alg,
-			}
-		}
-
-		spec.AcceptancePolicy.Policies = append(spec.AcceptancePolicy.Policies, policy)
-	}
-	return nil
-}
-
-func getOldSecret(oldSpec *swarmapi.ClusterSpec, role swarmapi.NodeRole) *swarmapi.AcceptancePolicy_RoleAdmissionPolicy_Secret {
-	if oldSpec == nil {
-		return nil
-	}
-	for _, p := range oldSpec.AcceptancePolicy.Policies {
-		if p.Role == role {
-			return p.Secret
-		}
-	}
-	return nil
-}

+ 20 - 37
docs/reference/api/docker_remote_api_v1.24.md

@@ -3351,7 +3351,6 @@ List nodes
         "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
         "Spec": {
           "Role": "MANAGER",
-          "Membership": "ACCEPTED",
           "Availability": "ACTIVE"
         },
         "Description": {
@@ -3481,7 +3480,6 @@ Return low-level information on the node `id`
       "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
       "Spec": {
         "Role": "MANAGER",
-        "Membership": "ACCEPTED",
         "Availability": "ACTIVE"
       },
       "Description": {
@@ -3595,18 +3593,6 @@ Initialize a new Swarm
       "ListenAddr": "0.0.0.0:4500",
       "ForceNewCluster": false,
       "Spec": {
-        "AcceptancePolicy": {
-          "Policies": [
-            {
-              "Role": "MANAGER",
-              "Autoaccept": false
-            },
-            {
-              "Role": "WORKER",
-              "Autoaccept": true
-            }
-          ]
-        },
         "Orchestration": {},
         "Raft": {},
         "Dispatcher": {},
@@ -3676,9 +3662,7 @@ Join an existing new Swarm
     {
       "ListenAddr": "0.0.0.0:4500",
       "RemoteAddrs": ["node1:4500"],
-      "Secret": "",
-      "CACertHash": "",
-      "Manager": false
+      "JoinToken": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
     }
 
 **Example response**:
@@ -3698,9 +3682,7 @@ JSON Parameters:
 - **ListenAddr** – Listen address used for inter-manager communication if the node gets promoted to
   manager, as well as determining the networking interface used for the VXLAN Tunnel Endpoint (VTEP).
 - **RemoteAddr** – Address of any manager node already participating in the Swarm to join.
-- **Secret** – Secret token for joining this Swarm.
-- **CACertHash** – Optional hash of the root CA to avoid relying on trust on first use.
-- **Manager** – Directly join as a manager (only for a Swarm configured to autoaccept managers).
+- **JoinToken** – Secret token for joining this Swarm.
 
 ### Leave a Swarm
 
@@ -3741,18 +3723,6 @@ Update a Swarm
 
     {
       "Name": "default",
-      "AcceptancePolicy": {
-        "Policies": [
-          {
-            "Role": "WORKER",
-            "Autoaccept": false
-          },
-          {
-            "Role": "MANAGER",
-            "Autoaccept": false
-          }
-        ]
-      },
       "Orchestration": {
         "TaskHistoryRetentionLimit": 10
       },
@@ -3767,6 +3737,10 @@ Update a Swarm
       },
       "CAConfig": {
         "NodeCertExpiry": 7776000000000000
+      },
+      "JoinTokens": {
+        "Worker": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx",
+        "Manager": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
       }
     }
 
@@ -3777,6 +3751,13 @@ Update a Swarm
     Content-Length: 0
     Content-Type: text/plain; charset=utf-8
 
+**Query parameters**:
+
+- **version** – The version number of the swarm object being updated. This is
+  required to avoid conflicting writes.
+- **rotate_worker_token** - Set to `true` to rotate the worker join token.
+- **rotate_manager_token** - Set to `true` to rotate the manager join token.
+
 **Status codes**:
 
 - **200** – no error
@@ -3785,11 +3766,6 @@ Update a Swarm
 
 JSON Parameters:
 
-- **Policies** – An array of acceptance policies.
-    - **Role** – The role that policy applies to (`MANAGER` or `WORKER`)
-    - **Autoaccept** – A boolean indicating whether nodes joining for that role should be
-      automatically accepted in the Swarm.
-    - **Secret** – An optional secret to provide for nodes to join the Swarm.
 - **Orchestration** – Configuration settings for the orchestration aspects of the Swarm.
     - **TaskHistoryRetentionLimit** – Maximum number of tasks history stored.
 - **Raft** – Raft related configuration.
@@ -3811,6 +3787,9 @@ JSON Parameters:
         - **URL** - URL where certificate signing requests should be sent.
         - **Options** - An object with key/value pairs that are interpreted
           as protocol-specific options for the external CA driver.
+- **JoinTokens** - Tokens that can be used by other nodes to join the Swarm.
+    - **Worker** - Token to use for joining as a worker.
+    - **Manager** - Token to use for joining as a manager.
 
 ## 3.8 Services
 
@@ -4292,6 +4271,10 @@ Update the service `id`.
           of: `"Ports": { "<port>/<tcp|udp>: {}" }`
     - **VirtualIPs**
 
+**Query parameters**:
+
+- **version** – The version number of the service object being updated. This is
+  required to avoid conflicting writes.
 
 **Status codes**:
 

+ 20 - 37
docs/reference/api/docker_remote_api_v1.25.md

@@ -3352,7 +3352,6 @@ List nodes
         "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
         "Spec": {
           "Role": "MANAGER",
-          "Membership": "ACCEPTED",
           "Availability": "ACTIVE"
         },
         "Description": {
@@ -3482,7 +3481,6 @@ Return low-level information on the node `id`
       "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
       "Spec": {
         "Role": "MANAGER",
-        "Membership": "ACCEPTED",
         "Availability": "ACTIVE"
       },
       "Description": {
@@ -3596,18 +3594,6 @@ Initialize a new Swarm
       "ListenAddr": "0.0.0.0:4500",
       "ForceNewCluster": false,
       "Spec": {
-        "AcceptancePolicy": {
-          "Policies": [
-            {
-              "Role": "MANAGER",
-              "Autoaccept": false
-            },
-            {
-              "Role": "WORKER",
-              "Autoaccept": true
-            }
-          ]
-        },
         "Orchestration": {},
         "Raft": {},
         "Dispatcher": {},
@@ -3677,9 +3663,7 @@ Join an existing new Swarm
     {
       "ListenAddr": "0.0.0.0:4500",
       "RemoteAddrs": ["node1:4500"],
-      "Secret": "",
-      "CACertHash": "",
-      "Manager": false
+      "JoinToken": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
     }
 
 **Example response**:
@@ -3699,9 +3683,7 @@ JSON Parameters:
 - **ListenAddr** – Listen address used for inter-manager communication if the node gets promoted to
   manager, as well as determining the networking interface used for the VXLAN Tunnel Endpoint (VTEP).
 - **RemoteAddr** – Address of any manager node already participating in the Swarm to join.
-- **Secret** – Secret token for joining this Swarm.
-- **CACertHash** – Optional hash of the root CA to avoid relying on trust on first use.
-- **Manager** – Directly join as a manager (only for a Swarm configured to autoaccept managers).
+- **JoinToken** – Secret token for joining this Swarm.
 
 ### Leave a Swarm
 
@@ -3742,18 +3724,6 @@ Update a Swarm
 
     {
       "Name": "default",
-      "AcceptancePolicy": {
-        "Policies": [
-          {
-            "Role": "WORKER",
-            "Autoaccept": false
-          },
-          {
-            "Role": "MANAGER",
-            "Autoaccept": false
-          }
-        ]
-      },
       "Orchestration": {
         "TaskHistoryRetentionLimit": 10
       },
@@ -3768,6 +3738,10 @@ Update a Swarm
       },
       "CAConfig": {
         "NodeCertExpiry": 7776000000000000
+      },
+      "JoinTokens": {
+        "Worker": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx",
+        "Manager": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
       }
     }
 
@@ -3778,6 +3752,13 @@ Update a Swarm
     Content-Length: 0
     Content-Type: text/plain; charset=utf-8
 
+**Query parameters**:
+
+- **version** – The version number of the swarm object being updated. This is
+  required to avoid conflicting writes.
+- **rotate_worker_token** - Set to `true` to rotate the worker join token.
+- **rotate_manager_token** - Set to `true` to rotate the manager join token.
+
 **Status codes**:
 
 - **200** – no error
@@ -3786,11 +3767,6 @@ Update a Swarm
 
 JSON Parameters:
 
-- **Policies** – An array of acceptance policies.
-    - **Role** – The role that policy applies to (`MANAGER` or `WORKER`)
-    - **Autoaccept** – A boolean indicating whether nodes joining for that role should be
-      automatically accepted in the Swarm.
-    - **Secret** – An optional secret to provide for nodes to join the Swarm.
 - **Orchestration** – Configuration settings for the orchestration aspects of the Swarm.
     - **TaskHistoryRetentionLimit** – Maximum number of tasks history stored.
 - **Raft** – Raft related configuration.
@@ -3812,6 +3788,9 @@ JSON Parameters:
         - **URL** - URL where certificate signing requests should be sent.
         - **Options** - An object with key/value pairs that are interpreted
           as protocol-specific options for the external CA driver.
+- **JoinTokens** - Tokens that can be used by other nodes to join the Swarm.
+    - **Worker** - Token to use for joining as a worker.
+    - **Manager** - Token to use for joining as a manager.
 
 ## 3.8 Services
 
@@ -4293,6 +4272,10 @@ Update the service `id`.
           of: `"Ports": { "<port>/<tcp|udp>: {}" }`
     - **VirtualIPs**
 
+**Query parameters**:
+
+- **version** – The version number of the service object being updated. This is
+  required to avoid conflicting writes.
 
 **Status codes**:
 

+ 1 - 1
docs/reference/commandline/deploy.md

@@ -19,7 +19,7 @@ Create and update a stack from a Distributed Application Bundle (DAB)
 Options:
       --file   string   Path to a Distributed Application Bundle file (Default: STACK.dab)
       --help            Print usage
-      --registry-auth   Send registry authentication details to Swarm agents
+      --registry-auth   Send registry authentication details to swarm agents
 ```
 
 Create and update a stack from a `dab` file. This command has to be

+ 3 - 3
docs/reference/commandline/index.md

@@ -111,7 +111,6 @@ read the [`dockerd`](dockerd.md) reference page.
 
 | Command | Description                                                        |
 |:--------|:-------------------------------------------------------------------|
-| [node accept](node_accept.md) | Accept a node into the swarm                 |
 | [node promote](node_promote.md) | Promote a node that is pending a promotion to manager |
 | [node demote](node_demote.md) | Demotes an existing manager so that it is no longer a manager |
 | [node inspect](node_inspect.md) | Inspect a node in the swarm                |
@@ -124,10 +123,11 @@ read the [`dockerd`](dockerd.md) reference page.
 
 | Command | Description                                                        |
 |:--------|:-------------------------------------------------------------------|
-| [swarm init](swarm_init.md) | Initialize a Swarm                             |
-| [swarm join](swarm_join.md) | Join a Swarm as a manager node or worker node  |
+| [swarm init](swarm_init.md) | Initialize a swarm                             |
+| [swarm join](swarm_join.md) | Join a swarm as a manager node or worker node  |
 | [swarm leave](swarm_leave.md) | Remove the current node from the swarm       |
 | [swarm update](swarm_update.md) | Update attributes of a swarm               |
+| [swarm join-token](swarm_join_token.md) | Display or rotate join tokens      |
 
 ### Swarm service commands
 

+ 1 - 1
docs/reference/commandline/info.md

@@ -38,7 +38,7 @@ available on the volume where `/var/lib/docker` is mounted.
 ## Display Docker system information
 
 Here is a sample output for a daemon running on Ubuntu, using the overlay
-storage driver and a node that is part of a 2 node Swarm cluster:
+storage driver and a node that is part of a 2 node swarm cluster:
 
     $ docker -D info
     Containers: 14

+ 0 - 32
docs/reference/commandline/node_accept.md

@@ -1,32 +0,0 @@
-<!--[metadata]>
-+++
-title = "node accept"
-description = "The node accept command description and usage"
-keywords = ["node, accept"]
-[menu.main]
-parent = "smn_cli"
-+++
-<![end-metadata]-->
-
-# node accept
-
-```markdown
-Usage:  docker node accept NODE [NODE...]
-
-Accept a node in the swarm
-
-Options:
-      --help   Print usage
-```
-
-Accept a node into the swarm. This command targets a docker engine that is a manager in the swarm cluster.
-
-
-```bash
-$ docker node accept <node name>
-```
-
-## Related information
-
-* [node promote](node_promote.md)
-* [node demote](node_demote.md)

+ 0 - 1
docs/reference/commandline/node_demote.md

@@ -29,5 +29,4 @@ $ docker node demote <node name>
 
 ## Related information
 
-* [node accept](node_accept.md)
 * [node promote](node_promote.md)

+ 0 - 1
docs/reference/commandline/node_inspect.md

@@ -41,7 +41,6 @@ Example output:
         "UpdatedAt": "2016-06-16T22:52:45.230878043Z",
         "Spec": {
             "Role": "manager",
-            "Membership": "accepted",
             "Availability": "active"
         },
         "Description": {

+ 10 - 10
docs/reference/commandline/node_ls.md

@@ -30,10 +30,10 @@ Lists all the nodes that the Docker Swarm manager knows about. You can filter us
 Example output:
 
     $ docker node ls
-    ID                           HOSTNAME        MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS  LEADER
-    1bcef6utixb0l0ca7gxuivsj0    swarm-worker2   Accepted    Ready   Active
-    38ciaotwjuritcdtn9npbnkuz    swarm-worker1   Accepted    Ready   Active
-    e216jshn25ckzbvmwlnh5jr3g *  swarm-manager1  Accepted    Ready   Active        Reachable       Yes
+    ID                           HOSTNAME        STATUS  AVAILABILITY  MANAGER STATUS
+    1bcef6utixb0l0ca7gxuivsj0    swarm-worker2   Ready   Active
+    38ciaotwjuritcdtn9npbnkuz    swarm-worker1   Ready   Active
+    e216jshn25ckzbvmwlnh5jr3g *  swarm-manager1  Ready   Active        Leader
 
 
 ## Filtering
@@ -54,16 +54,16 @@ The `name` filter matches on all or part of a node name.
 The following filter matches the node with a name equal to `swarm-master` string.
 
     $ docker node ls -f name=swarm-manager1
-    ID                           HOSTNAME        MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS  LEADER
-    e216jshn25ckzbvmwlnh5jr3g *  swarm-manager1  Accepted    Ready   Active        Reachable       Yes
+    ID                           HOSTNAME        STATUS  AVAILABILITY  MANAGER STATUS
+    e216jshn25ckzbvmwlnh5jr3g *  swarm-manager1  Ready   Active        Leader
 
 ### id
 
 The `id` filter matches all or part of a node's id.
 
     $ docker node ls -f id=1
-    ID                         HOSTNAME       MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS  LEADER
-    1bcef6utixb0l0ca7gxuivsj0  swarm-worker2  Accepted    Ready   Active
+    ID                         HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
+    1bcef6utixb0l0ca7gxuivsj0  swarm-worker2  Ready   Active
 
 
 #### label
@@ -75,8 +75,8 @@ The following filter matches nodes with the `usage` label regardless of its valu
 
 ```bash
 $ docker node ls -f "label=foo"
-ID                         HOSTNAME       MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS  LEADER
-1bcef6utixb0l0ca7gxuivsj0  swarm-worker2  Accepted    Ready   Active
+ID                         HOSTNAME       STATUS  AVAILABILITY  MANAGER STATUS
+1bcef6utixb0l0ca7gxuivsj0  swarm-worker2  Ready   Active
 ```
 
 

+ 0 - 1
docs/reference/commandline/node_promote.md

@@ -28,5 +28,4 @@ $ docker node promote <node name>
 
 ## Related information
 
-* [node accept](node_accept.md)
 * [node demote](node_demote.md)

+ 2 - 3
docs/reference/commandline/node_rm.md

@@ -23,14 +23,13 @@ Options:
       --help   Print usage
 ```
 
-Removes specified nodes from a swarm. Rejects nodes with `Pending`
-membership from the swarm.
+Removes specified nodes from a swarm.
 
 
 Example output:
 
     $ docker node rm swarm-node-02
-    Node swarm-node-02 removed from Swarm
+    Node swarm-node-02 removed from swarm
 
 
 ## Related information

+ 0 - 1
docs/reference/commandline/node_update.md

@@ -21,7 +21,6 @@ Options:
       --help                  Print usage
       --label-add value       Add or update a node label (key=value) (default [])
       --label-rm value        Remove a node label if exists (default [])
-      --membership string     Membership of the node (accepted/rejected)
       --role string           Role of the node (worker/manager)
 ```
 

+ 1 - 1
docs/reference/commandline/service_create.md

@@ -31,7 +31,7 @@ Options:
       --name string                  Service name
       --network value                Network attachments (default [])
   -p, --publish value                Publish a port as a node port (default [])
-      --registry-auth                Send registry authentication details to Swarm agents
+      --registry-auth                Send registry authentication details to swarm agents
       --replicas value               Number of tasks (default none)
       --reserve-cpu value            Reserve CPUs (default 0.000)
       --reserve-memory value         Reserve Memory (default 0 B)

+ 1 - 1
docs/reference/commandline/service_update.md

@@ -38,7 +38,7 @@ Options:
       --network-rm value             Remove a network by name (default [])
       --publish-add value            Add or update a published port (default [])
       --publish-rm value             Remove a published port by its target port (default [])
-      --registry-auth                Send registry authentication details to Swarm agents
+      --registry-auth                Send registry authentication details to swarm agents
       --replicas value               Number of tasks (default none)
       --reserve-cpu value            Reserve CPUs (default 0.000)
       --reserve-memory value         Reserve Memory (default 0 B)

+ 19 - 54
docs/reference/commandline/swarm_init.md

@@ -14,74 +14,43 @@ parent = "smn_cli"
 ```markdown
 Usage:  docker swarm init [OPTIONS]
 
-Initialize a Swarm
+Initialize a swarm
 
 Options:
-      --auto-accept value               Auto acceptance policy (default worker)
       --cert-expiry duration            Validity period for node certificates (default 2160h0m0s)
       --dispatcher-heartbeat duration   Dispatcher heartbeat period (default 5s)
       --external-ca value               Specifications of one or more certificate signing endpoints
       --force-new-cluster               Force create a new cluster from current state.
       --help                            Print usage
       --listen-addr value               Listen address (default 0.0.0.0:2377)
-      --secret string                   Set secret value needed to accept nodes into cluster
       --task-history-limit int          Task history retention limit (default 10)
 ```
 
-Initialize a Swarm cluster. The docker engine targeted by this command becomes a manager
-in the newly created one node Swarm cluster.
+Initialize a swarm cluster. The docker engine targeted by this command becomes a manager
+in the newly created one node swarm cluster.
 
 
 ```bash
 $ docker swarm init --listen-addr 192.168.99.121:2377
-No --secret provided. Generated random secret:
-    4ao565v9jsuogtq5t8s379ulb
-
-Swarm initialized: current node (1ujecd0j9n3ro9i6628smdmth) is now a manager.
+Swarm initialized: current node (bvz81updecsj6wjz393c09vti) is now a manager.
 
 To add a worker to this swarm, run the following command:
-    docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb \
-    --ca-hash sha256:07ce22bd1a7619f2adc0d63bd110479a170e7c4e69df05b67a1aa2705c88ef09 \
-    192.168.99.121:2377
-$ docker node ls
-ID                           HOSTNAME  MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS          LEADER
-1ujecd0j9n3ro9i6628smdmth *  manager1  Accepted    Ready   Active        Reachable               Yes
-```
-
-If a secret for joining new nodes is not provided with `--secret`, `docker swarm init` will
-generate a random one and print it to the terminal (as seen in the example above). To initialize
-a swarm with no secret, use `--secret ""`.
-
-### `--auto-accept value`
-
-This flag controls node acceptance into the cluster. By default, `worker` nodes are
-automatically accepted by the cluster. This can be changed by specifying what kinds of nodes
-can be auto-accepted into the cluster. If auto-accept is not turned on, then
-[node accept](node_accept.md) can be used to explicitly accept a node into the cluster.
-
-For example, the following initializes a cluster with auto-acceptance of workers, but not managers
-
-
-```bash
-$ docker swarm init --listen-addr 192.168.99.121:2377 --auto-accept worker
+    docker swarm join \
+    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx \
+    172.17.0.2:2377
+
+To add a manager to this swarm, run the following command:
+    docker swarm join \
+    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2 \
+    172.17.0.2:2377
 ```
 
-It is possible to pass a comma-separated list of node types. The following initializes a cluster
-with auto-acceptance of both `worker` and `manager` nodes
+`docker swarm init` generates two random tokens, a worker token and a manager token. When you join
+a new node to the swarm, the node joins as a worker or manager node based upon the token you pass
+to [swarm join](swarm_join.md).
 
-```bash
-$ docker swarm init --listen-addr 192.168.99.121:2377 --auto-accept worker,manager
-```
-
-To disable auto acceptance, use the `none` option. Note that this option cannot
-be combined with other values. When disabling auto acceptance, nodes must be
-manually accepted or rejected using `docker node accept` or `docker node rm`.
-
-The following example enables swarm mode with auto acceptance disabled:
-
-```bash
-$ docker swarm init --listen-addr 192.168.99.121:2377 --auto-accept none
-```
+After you create the swarm, you can display or rotate the token using
+[swarm join-token](swarm_join_token.md).
 
 ### `--cert-expiry`
 
@@ -105,11 +74,7 @@ This flag forces an existing node that was part of a quorum that was lost to res
 
 ### `--listen-addr value`
 
-The node listens for inbound Swarm manager traffic on this IP:PORT
-
-### `--secret string`
-
-Secret value needed to accept nodes into the Swarm
+The node listens for inbound swarm manager traffic on this IP:PORT
 
 ### `--task-history-limit`
 
@@ -120,5 +85,5 @@ This flag sets up task history retention limit.
 * [swarm join](swarm_join.md)
 * [swarm leave](swarm_leave.md)
 * [swarm update](swarm_update.md)
-* [node accept](node_accept.md)
+* [swarm join-token](swarm_join_token.md)
 * [node rm](node_rm.md)

+ 26 - 27
docs/reference/commandline/swarm_join.md

@@ -14,55 +14,54 @@ parent = "smn_cli"
 ```markdown
 Usage:  docker swarm join [OPTIONS] HOST:PORT
 
-Join a Swarm as a node and/or manager
+Join a swarm as a node and/or manager
 
 Options:
-      --ca-hash string      Hash of the Root Certificate Authority certificate used for trusted join
       --help                Print usage
       --listen-addr value   Listen address (default 0.0.0.0:2377)
-      --manager             Try joining as a manager.
-      --secret string       Secret for node acceptance
+      --token string        Token for entry into the swarm
 ```
 
-Join a node to a Swarm cluster. If the `--manager` flag is specified, the docker engine
-targeted by this command becomes a `manager`. If it is not specified, it becomes a `worker`.
+Join a node to a swarm. The node joins as a manager node or worker node based upon the token you
+pass with the `--token` flag. If you pass a manager token, the node joins as a manager. If you
+pass a worker token, the node joins as a worker.
 
 ### Join a node to swarm as a manager
 
+The example below demonstrates joining a manager node using a manager token.
+
 ```bash
-$ docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb --manager --listen-addr 192.168.99.122:2377 192.168.99.121:2377
-This node joined a Swarm as a manager.
+$ docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2 --listen-addr 192.168.99.122:2377 192.168.99.121:2377
+This node joined a swarm as a manager.
 $ docker node ls
-ID                           HOSTNAME  MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS         LEADER
-dkp8vy1dq1kxleu9g4u78tlag *  manager2  Accepted    Ready   Active        Reachable
-dvfxp4zseq4s0rih1selh0d20    manager1  Accepted    Ready   Active        Reachable              Yes
+ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
+dkp8vy1dq1kxleu9g4u78tlag *  manager2  Ready   Active        Reachable
+dvfxp4zseq4s0rih1selh0d20    manager1  Ready   Active        Leader
 ```
 
+A cluster should only have 3-7 managers at most, because a majority of managers must be available
+for the cluster to function. Nodes that aren't meant to participate in this management quorum
+should join as workers instead. Managers should be stable hosts that have static IP addresses.
+
 ### Join a node to swarm as a worker
 
+The example below demonstrates joining a worker node using a worker token.
+
 ```bash
-$ docker swarm join --secret 4ao565v9jsuogtq5t8s379ulb --listen-addr 192.168.99.123:2377 192.168.99.121:2377
-This node joined a Swarm as a worker.
+$ docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx --listen-addr 192.168.99.123:2377 192.168.99.121:2377
+This node joined a swarm as a worker.
 $ docker node ls
-ID                           HOSTNAME  MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS         LEADER
-7ln70fl22uw2dvjn2ft53m3q5    worker2   Accepted    Ready   Active
-dkp8vy1dq1kxleu9g4u78tlag    worker1   Accepted    Ready   Active        Reachable
-dvfxp4zseq4s0rih1selh0d20 *  manager1  Accepted    Ready   Active        Reachable              Yes
+ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
+7ln70fl22uw2dvjn2ft53m3q5    worker2   Ready   Active
+dkp8vy1dq1kxleu9g4u78tlag    worker1   Ready   Active        Reachable
+dvfxp4zseq4s0rih1selh0d20 *  manager1  Ready   Active        Leader
 ```
 
-### `--ca-hash`
-
-Hash of the Root Certificate Authority certificate used for trusted join.
-
 ### `--listen-addr value`
 
-The node listens for inbound Swarm manager traffic on this IP:PORT
-
-### `--manager`
-
-Joins the node as a manager
+The node listens for inbound swarm manager traffic on this IP:PORT
 
-### `--secret string`
+### `--token string`
 
 Secret value required for nodes to join the swarm
 

+ 76 - 0
docs/reference/commandline/swarm_join_token.md

@@ -0,0 +1,76 @@
+<!--[metadata]>
++++
+title = "swarm join-token"
+description = "The swarm join-token command description and usage"
+keywords = ["swarm, join-token"]
+advisory = "rc"
+[menu.main]
+parent = "smn_cli"
++++
+<![end-metadata]-->
+
+# swarm join-token
+
+```markdown
+Usage:	docker swarm join-token [--rotate] (worker|manager)
+
+Manage join tokens
+
+Options:
+      --help     Print usage
+  -q, --quiet    Only display token
+      --rotate   Rotate join token
+```
+
+Join tokens are secrets that determine whether or not a node will join the swarm as a manager node
+or a worker node. You pass the token using the `--token flag` when you run
+[swarm join](swarm_join.md). You can access the current tokens or rotate the tokens using
+`swarm join-token`.
+
+Run with only a single `worker` or `manager` argument, it will print a command for joining a new
+node to the swarm, including the necessary token:
+
+```bash
+$ docker swarm join-token worker
+To add a worker to this swarm, run the following command:
+    docker swarm join \
+    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx \
+    172.17.0.2:2377
+
+$ docker swarm join-token manager
+To add a manager to this swarm, run the following command:
+    docker swarm join \
+    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2 \
+    172.17.0.2:2377
+```
+
+Use the `--rotate` flag to generate a new join token for the specified role:
+
+```bash
+$ docker swarm join-token --rotate worker
+To add a worker to this swarm, run the following command:
+    docker swarm join \
+    --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-b30ljddcqhef9b9v4rs7mel7t \
+    172.17.0.2:2377
+```
+
+After using `--rotate`, only the new token will be valid for joining with the specified role.
+
+The `-q` (or `--quiet`) flag only prints the token:
+
+```bash
+$ docker swarm join-token -q worker
+SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-b30ljddcqhef9b9v4rs7mel7t
+```
+
+### `--rotate`
+
+Update the join token for a specified role with a new token and print the token.
+
+### `--quiet`
+
+Only print the token. Do not print a complete command for joining.
+
+## Related information
+
+* [swarm join](swarm_join.md)

+ 9 - 9
docs/reference/commandline/swarm_leave.md

@@ -14,7 +14,7 @@ parent = "smn_cli"
 ```markdown
 Usage:  docker swarm leave [OPTIONS]
 
-Leave a Swarm
+Leave a swarm
 
 Options:
       --force   Force leave ignoring warnings.
@@ -26,10 +26,10 @@ This command causes the node to leave the swarm.
 On a manager node:
 ```bash
 $ docker node ls
-ID                           HOSTNAME  MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS         LEADER
-7ln70fl22uw2dvjn2ft53m3q5    worker2   Accepted    Ready   Active
-dkp8vy1dq1kxleu9g4u78tlag    worker1   Accepted    Ready   Active        Reachable
-dvfxp4zseq4s0rih1selh0d20 *  manager1  Accepted    Ready   Active        Reachable              Yes
+ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
+7ln70fl22uw2dvjn2ft53m3q5    worker2   Ready   Active
+dkp8vy1dq1kxleu9g4u78tlag    worker1   Ready   Active        Reachable
+dvfxp4zseq4s0rih1selh0d20 *  manager1  Ready   Active        Leader
 ```
 
 On a worker node:
@@ -41,10 +41,10 @@ Node left the default swarm.
 On a manager node:
 ```bash
 $ docker node ls
-ID                           HOSTNAME  MEMBERSHIP  STATUS  AVAILABILITY  MANAGER STATUS         LEADER
-7ln70fl22uw2dvjn2ft53m3q5    worker2   Accepted    Down    Active
-dkp8vy1dq1kxleu9g4u78tlag    worker1   Accepted    Ready   Active        Reachable
-dvfxp4zseq4s0rih1selh0d20 *  manager1  Accepted    Ready   Active        Reachable              Yes
+ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
+7ln70fl22uw2dvjn2ft53m3q5    worker2   Down    Active
+dkp8vy1dq1kxleu9g4u78tlag    worker1   Ready   Active        Reachable
+dvfxp4zseq4s0rih1selh0d20 *  manager1  Ready   Active        Leader
 ```
 
 ## Related information

+ 3 - 5
docs/reference/commandline/swarm_update.md

@@ -14,23 +14,21 @@ parent = "smn_cli"
 ```markdown
 Usage:  docker swarm update [OPTIONS]
 
-Update the Swarm
+Update the swarm
 
 Options:
-      --auto-accept value               Auto acceptance policy (worker, manager or none)
       --cert-expiry duration            Validity period for node certificates (default 2160h0m0s)
       --dispatcher-heartbeat duration   Dispatcher heartbeat period (default 5s)
       --external-ca value               Specifications of one or more certificate signing endpoints
       --help                            Print usage
-      --secret string                   Set secret value needed to accept nodes into cluster
       --task-history-limit int          Task history retention limit (default 10)
 ```
 
-Updates a Swarm cluster with new parameter values. This command must target a manager node.
+Updates a swarm cluster with new parameter values. This command must target a manager node.
 
 
 ```bash
-$ docker swarm update --auto-accept manager
+$ docker swarm update --cert-expirty 4000h0m0s
 ```
 
 ## Related information

+ 2 - 2
hack/vendor.sh

@@ -60,7 +60,7 @@ clone git golang.org/x/net 2beffdc2e92c8a3027590f898fe88f69af48a3f8 https://gith
 clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://github.com/golang/sys.git
 clone git github.com/docker/go-units 651fc226e7441360384da338d0fd37f2440ffbe3
 clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d
-clone git github.com/docker/engine-api 1d247454d4307fb1ddf10d09fd2996394b085904
+clone git github.com/docker/engine-api c977588a28fa81fbbb06c295e936853cef37cf27
 clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
 clone git github.com/imdario/mergo 0.2.1
 
@@ -139,7 +139,7 @@ clone git github.com/docker/docker-credential-helpers v0.3.0
 clone git github.com/docker/containerd 0ac3cd1be170d180b2baed755e8f0da547ceb267
 
 # cluster
-clone git github.com/docker/swarmkit 9ee5fc3b8db5de8c8593a57bc45fc178f74ceee1
+clone git github.com/docker/swarmkit 38857c06dafcf939a56d2650d8e0011b5aace384
 clone git github.com/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
 clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028
 clone git github.com/cloudflare/cfssl b895b0549c0ff676f92cf09ba971ae02bb41367b

+ 8 - 6
integration-cli/check_test.go

@@ -216,15 +216,17 @@ func (s *DockerSwarmSuite) AddDaemon(c *check.C, joinSwarm, manager bool) *Swarm
 
 	if joinSwarm == true {
 		if len(s.daemons) > 0 {
+			tokens := s.daemons[0].joinTokens(c)
+			token := tokens.Worker
+			if manager {
+				token = tokens.Manager
+			}
 			c.Assert(d.Join(swarm.JoinRequest{
 				RemoteAddrs: []string{s.daemons[0].listenAddr},
-				Manager:     manager}), check.IsNil)
-		} else {
-			c.Assert(d.Init(swarm.InitRequest{
-				Spec: swarm.Spec{
-					AcceptancePolicy: autoAcceptPolicy,
-				},
+				JoinToken:   token,
 			}), check.IsNil)
+		} else {
+			c.Assert(d.Init(swarm.InitRequest{}), check.IsNil)
 		}
 	}
 

+ 22 - 8
integration-cli/daemon_swarm.go

@@ -22,14 +22,6 @@ type SwarmDaemon struct {
 	listenAddr string
 }
 
-// default policy in tests is allow-all
-var autoAcceptPolicy = swarm.AcceptancePolicy{
-	Policies: []swarm.Policy{
-		{Role: swarm.NodeRoleWorker, Autoaccept: true},
-		{Role: swarm.NodeRoleManager, Autoaccept: true},
-	},
-}
-
 // Init initializes a new swarm cluster.
 func (d *SwarmDaemon) Init(req swarm.InitRequest) error {
 	if req.ListenAddr == "" {
@@ -271,6 +263,28 @@ func (d *SwarmDaemon) updateSwarm(c *check.C, f ...specConstructor) {
 	c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
 }
 
+func (d *SwarmDaemon) rotateTokens(c *check.C) {
+	var sw swarm.Swarm
+	status, out, err := d.SockRequest("GET", "/swarm", nil)
+	c.Assert(err, checker.IsNil)
+	c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
+	c.Assert(json.Unmarshal(out, &sw), checker.IsNil)
+
+	url := fmt.Sprintf("/swarm/update?version=%d&rotate_worker_token=true&rotate_manager_token=true", sw.Version.Index)
+	status, out, err = d.SockRequest("POST", url, sw.Spec)
+	c.Assert(err, checker.IsNil)
+	c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
+}
+
+func (d *SwarmDaemon) joinTokens(c *check.C) swarm.JoinTokens {
+	var sw swarm.Swarm
+	status, out, err := d.SockRequest("GET", "/swarm", nil)
+	c.Assert(err, checker.IsNil)
+	c.Assert(status, checker.Equals, http.StatusOK, check.Commentf("output: %q", string(out)))
+	c.Assert(json.Unmarshal(out, &sw), checker.IsNil)
+	return sw.JoinTokens
+}
+
 func (d *SwarmDaemon) checkLocalNodeState(c *check.C) (interface{}, check.CommentInterface) {
 	info, err := d.info()
 	c.Assert(err, checker.IsNil)

+ 27 - 127
integration-cli/docker_api_swarm_test.go

@@ -43,7 +43,7 @@ func (s *DockerSwarmSuite) TestApiSwarmInit(c *check.C) {
 	c.Assert(info.ControlAvailable, checker.False)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 
-	c.Assert(d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
+	c.Assert(d2.Join(swarm.JoinRequest{JoinToken: d1.joinTokens(c).Worker, RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
 
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
@@ -72,89 +72,29 @@ func (s *DockerSwarmSuite) TestApiSwarmInit(c *check.C) {
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
 }
 
-func (s *DockerSwarmSuite) TestApiSwarmManualAcceptance(c *check.C) {
-	testRequires(c, Network)
-	s.testAPISwarmManualAcceptance(c, "")
-}
-func (s *DockerSwarmSuite) TestApiSwarmManualAcceptanceSecret(c *check.C) {
-	testRequires(c, Network)
-	s.testAPISwarmManualAcceptance(c, "foobaz")
-}
-
-func (s *DockerSwarmSuite) testAPISwarmManualAcceptance(c *check.C, secret string) {
-	d1 := s.AddDaemon(c, false, false)
-	c.Assert(d1.Init(swarm.InitRequest{
-		Spec: swarm.Spec{
-			AcceptancePolicy: swarm.AcceptancePolicy{
-				Policies: []swarm.Policy{
-					{Role: swarm.NodeRoleWorker, Secret: &secret},
-					{Role: swarm.NodeRoleManager, Secret: &secret},
-				},
-			},
-		},
-	}), checker.IsNil)
-
-	d2 := s.AddDaemon(c, false, false)
-	err := d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}})
-	c.Assert(err, checker.NotNil)
-	if secret == "" {
-		c.Assert(err.Error(), checker.Contains, "needs to be accepted")
-		info, err := d2.info()
-		c.Assert(err, checker.IsNil)
-		c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStatePending)
-		c.Assert(d2.Leave(false), checker.IsNil)
-		info, err = d2.info()
-		c.Assert(err, checker.IsNil)
-		c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
-	} else {
-		c.Assert(err.Error(), checker.Contains, "valid secret token is necessary")
-		info, err := d2.info()
-		c.Assert(err, checker.IsNil)
-		c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
-	}
-	d3 := s.AddDaemon(c, false, false)
-	c.Assert(d3.Join(swarm.JoinRequest{Secret: secret, RemoteAddrs: []string{d1.listenAddr}}), checker.NotNil)
-	info, err := d3.info()
-	c.Assert(err, checker.IsNil)
-	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStatePending)
-	c.Assert(len(info.NodeID), checker.GreaterThan, 5)
-	d1.updateNode(c, info.NodeID, func(n *swarm.Node) {
-		n.Spec.Membership = swarm.NodeMembershipAccepted
-	})
-	waitAndAssert(c, defaultReconciliationTimeout, d3.checkLocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
-}
-
-func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) {
+func (s *DockerSwarmSuite) TestApiSwarmJoinToken(c *check.C) {
 	testRequires(c, Network)
 	d1 := s.AddDaemon(c, false, false)
-	secret := "foobar"
-	c.Assert(d1.Init(swarm.InitRequest{
-		Spec: swarm.Spec{
-			AcceptancePolicy: swarm.AcceptancePolicy{
-				Policies: []swarm.Policy{
-					{Role: swarm.NodeRoleWorker, Autoaccept: true, Secret: &secret},
-					{Role: swarm.NodeRoleManager, Secret: &secret},
-				},
-			},
-		},
-	}), checker.IsNil)
+	c.Assert(d1.Init(swarm.InitRequest{}), checker.IsNil)
 
 	d2 := s.AddDaemon(c, false, false)
 	err := d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}})
 	c.Assert(err, checker.NotNil)
-	c.Assert(err.Error(), checker.Contains, "secret token is necessary")
+	c.Assert(err.Error(), checker.Contains, "join token is necessary")
 	info, err := d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 
-	err = d2.Join(swarm.JoinRequest{Secret: "foobaz", RemoteAddrs: []string{d1.listenAddr}})
+	err = d2.Join(swarm.JoinRequest{JoinToken: "foobaz", RemoteAddrs: []string{d1.listenAddr}})
 	c.Assert(err, checker.NotNil)
-	c.Assert(err.Error(), checker.Contains, "secret token is necessary")
+	c.Assert(err.Error(), checker.Contains, "join token is necessary")
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 
-	c.Assert(d2.Join(swarm.JoinRequest{Secret: "foobar", RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
+	workerToken := d1.joinTokens(c).Worker
+
+	c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
@@ -163,22 +103,19 @@ func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) {
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 
-	// change secret
-	d1.updateSwarm(c, func(s *swarm.Spec) {
-		for i := range s.AcceptancePolicy.Policies {
-			p := "foobaz"
-			s.AcceptancePolicy.Policies[i].Secret = &p
-		}
-	})
+	// change tokens
+	d1.rotateTokens(c)
 
-	err = d2.Join(swarm.JoinRequest{Secret: "foobar", RemoteAddrs: []string{d1.listenAddr}})
+	err = d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.listenAddr}})
 	c.Assert(err, checker.NotNil)
-	c.Assert(err.Error(), checker.Contains, "secret token is necessary")
+	c.Assert(err.Error(), checker.Contains, "join token is necessary")
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 
-	c.Assert(d2.Join(swarm.JoinRequest{Secret: "foobaz", RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
+	workerToken = d1.joinTokens(c).Worker
+
+	c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
@@ -187,41 +124,17 @@ func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) {
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 
-	// change policy, don't change secret
-	d1.updateSwarm(c, func(s *swarm.Spec) {
-		for i, p := range s.AcceptancePolicy.Policies {
-			if p.Role == swarm.NodeRoleManager {
-				s.AcceptancePolicy.Policies[i].Autoaccept = false
-			}
-			s.AcceptancePolicy.Policies[i].Secret = nil
-		}
-	})
+	// change spec, don't change tokens
+	d1.updateSwarm(c, func(s *swarm.Spec) {})
 
 	err = d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}})
 	c.Assert(err, checker.NotNil)
-	c.Assert(err.Error(), checker.Contains, "secret token is necessary")
-	info, err = d2.info()
-	c.Assert(err, checker.IsNil)
-	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
-
-	c.Assert(d2.Join(swarm.JoinRequest{Secret: "foobaz", RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
-	info, err = d2.info()
-	c.Assert(err, checker.IsNil)
-	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
-	c.Assert(d2.Leave(false), checker.IsNil)
+	c.Assert(err.Error(), checker.Contains, "join token is necessary")
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 
-	// clear secret
-	d1.updateSwarm(c, func(s *swarm.Spec) {
-		for i := range s.AcceptancePolicy.Policies {
-			p := ""
-			s.AcceptancePolicy.Policies[i].Secret = &p
-		}
-	})
-
-	c.Assert(d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
+	c.Assert(d2.Join(swarm.JoinRequest{JoinToken: workerToken, RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
@@ -229,34 +142,24 @@ func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) {
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
-
 }
 
 func (s *DockerSwarmSuite) TestApiSwarmCAHash(c *check.C) {
 	testRequires(c, Network)
 	d1 := s.AddDaemon(c, true, true)
 	d2 := s.AddDaemon(c, false, false)
-	err := d2.Join(swarm.JoinRequest{CACertHash: "foobar", RemoteAddrs: []string{d1.listenAddr}})
+	splitToken := strings.Split(d1.joinTokens(c).Worker, "-")
+	splitToken[2] = "1kxftv4ofnc6mt30lmgipg6ngf9luhwqopfk1tz6bdmnkubg0e"
+	replacementToken := strings.Join(splitToken, "-")
+	err := d2.Join(swarm.JoinRequest{JoinToken: replacementToken, RemoteAddrs: []string{d1.listenAddr}})
 	c.Assert(err, checker.NotNil)
-	c.Assert(err.Error(), checker.Contains, "invalid checksum digest format")
-
-	c.Assert(len(d1.CACertHash), checker.GreaterThan, 0)
-	c.Assert(d2.Join(swarm.JoinRequest{CACertHash: d1.CACertHash, RemoteAddrs: []string{d1.listenAddr}}), checker.IsNil)
+	c.Assert(err.Error(), checker.Contains, "remote CA does not match fingerprint")
 }
 
 func (s *DockerSwarmSuite) TestApiSwarmPromoteDemote(c *check.C) {
 	testRequires(c, Network)
 	d1 := s.AddDaemon(c, false, false)
-	c.Assert(d1.Init(swarm.InitRequest{
-		Spec: swarm.Spec{
-			AcceptancePolicy: swarm.AcceptancePolicy{
-				Policies: []swarm.Policy{
-					{Role: swarm.NodeRoleWorker, Autoaccept: true},
-					{Role: swarm.NodeRoleManager},
-				},
-			},
-		},
-	}), checker.IsNil)
+	c.Assert(d1.Init(swarm.InitRequest{}), checker.IsNil)
 	d2 := s.AddDaemon(c, true, false)
 
 	info, err := d2.info()
@@ -838,9 +741,7 @@ func (s *DockerSwarmSuite) TestApiSwarmForceNewCluster(c *check.C) {
 
 	c.Assert(d1.Init(swarm.InitRequest{
 		ForceNewCluster: true,
-		Spec: swarm.Spec{
-			AcceptancePolicy: autoAcceptPolicy,
-		},
+		Spec:            swarm.Spec{},
 	}), checker.IsNil)
 
 	waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.Equals, instances)
@@ -937,7 +838,6 @@ func checkClusterHealth(c *check.C, cl []*SwarmDaemon, managerCount, workerCount
 		for _, n := range d.listNodes(c) {
 			c.Assert(n.Status.State, checker.Equals, swarm.NodeStateReady, check.Commentf("state of node %s, reported by %s", n.ID, d.Info.NodeID))
 			c.Assert(n.Spec.Availability, checker.Equals, swarm.NodeAvailabilityActive, check.Commentf("availability of node %s, reported by %s", n.ID, d.Info.NodeID))
-			c.Assert(n.Spec.Membership, checker.Equals, swarm.NodeMembershipAccepted, check.Commentf("membership of node %s, reported by %s", n.ID, d.Info.NodeID))
 			if n.Spec.Role == swarm.NodeRoleManager {
 				c.Assert(n.ManagerStatus, checker.NotNil, check.Commentf("manager status of node %s (manager), reported by %s", n.ID, d.Info.NodeID))
 				if n.ManagerStatus.Leader {

+ 3 - 56
integration-cli/docker_cli_swarm_test.go

@@ -25,50 +25,13 @@ func (s *DockerSwarmSuite) TestSwarmUpdate(c *check.C) {
 		return sw[0].Spec
 	}
 
-	out, err := d.Cmd("swarm", "update", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s", "--auto-accept", "manager", "--auto-accept", "worker", "--secret", "foo")
+	out, err := d.Cmd("swarm", "update", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s")
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
 
 	spec := getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
 	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(11*time.Second))
 
-	c.Assert(spec.AcceptancePolicy.Policies, checker.HasLen, 2)
-
-	for _, p := range spec.AcceptancePolicy.Policies {
-		c.Assert(p.Autoaccept, checker.Equals, true)
-		c.Assert(p.Secret, checker.NotNil)
-		c.Assert(*p.Secret, checker.Not(checker.Equals), "")
-	}
-
-	out, err = d.Cmd("swarm", "update", "--auto-accept", "none")
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
-
-	spec = getSpec()
-	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
-	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(11*time.Second))
-
-	c.Assert(spec.AcceptancePolicy.Policies, checker.HasLen, 2)
-
-	for _, p := range spec.AcceptancePolicy.Policies {
-		c.Assert(p.Autoaccept, checker.Equals, false)
-		// secret is still set
-		c.Assert(p.Secret, checker.NotNil)
-		c.Assert(*p.Secret, checker.Not(checker.Equals), "")
-	}
-
-	out, err = d.Cmd("swarm", "update", "--auto-accept", "manager", "--secret", "")
-	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
-
-	spec = getSpec()
-
-	c.Assert(spec.AcceptancePolicy.Policies, checker.HasLen, 2)
-
-	for _, p := range spec.AcceptancePolicy.Policies {
-		c.Assert(p.Autoaccept, checker.Equals, p.Role == swarm.NodeRoleManager)
-		// secret has been removed
-		c.Assert(p.Secret, checker.IsNil)
-	}
-
 	// setting anything under 30m for cert-expiry is not allowed
 	out, err = d.Cmd("swarm", "update", "--cert-expiry", "15m")
 	c.Assert(err, checker.NotNil)
@@ -89,37 +52,21 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
 		return sw[0].Spec
 	}
 
-	out, err := d.Cmd("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s", "--auto-accept", "manager", "--auto-accept", "worker", "--secret", "foo")
+	out, err := d.Cmd("swarm", "init", "--cert-expiry", "30h", "--dispatcher-heartbeat", "11s")
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
 
 	spec := getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
 	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(11*time.Second))
 
-	c.Assert(spec.AcceptancePolicy.Policies, checker.HasLen, 2)
-
-	for _, p := range spec.AcceptancePolicy.Policies {
-		c.Assert(p.Autoaccept, checker.Equals, true)
-		c.Assert(p.Secret, checker.NotNil)
-		c.Assert(*p.Secret, checker.Not(checker.Equals), "")
-	}
-
 	c.Assert(d.Leave(true), checker.IsNil)
 
-	out, err = d.Cmd("swarm", "init", "--auto-accept", "none", "--secret", "")
+	out, err = d.Cmd("swarm", "init")
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
 
 	spec = getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour)
 	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(5*time.Second))
-
-	c.Assert(spec.AcceptancePolicy.Policies, checker.HasLen, 2)
-
-	for _, p := range spec.AcceptancePolicy.Policies {
-		c.Assert(p.Autoaccept, checker.Equals, false)
-		c.Assert(p.Secret, checker.IsNil)
-	}
-
 }
 
 func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *check.C) {

+ 1 - 1
vendor/src/github.com/docker/engine-api/client/interface.go

@@ -115,7 +115,7 @@ type SwarmAPIClient interface {
 	SwarmJoin(ctx context.Context, req swarm.JoinRequest) error
 	SwarmLeave(ctx context.Context, force bool) error
 	SwarmInspect(ctx context.Context) (swarm.Swarm, error)
-	SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec) error
+	SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error
 }
 
 // SystemAPIClient defines API client methods for the system

+ 4 - 1
vendor/src/github.com/docker/engine-api/client/swarm_update.go

@@ -1,6 +1,7 @@
 package client
 
 import (
+	"fmt"
 	"net/url"
 	"strconv"
 
@@ -9,9 +10,11 @@ import (
 )
 
 // SwarmUpdate updates the Swarm.
-func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec) error {
+func (cli *Client) SwarmUpdate(ctx context.Context, version swarm.Version, swarm swarm.Spec, flags swarm.UpdateFlags) error {
 	query := url.Values{}
 	query.Set("version", strconv.FormatUint(version.Index, 10))
+	query.Set("rotate_worker_token", fmt.Sprintf("%v", flags.RotateWorkerToken))
+	query.Set("rotate_manager_token", fmt.Sprintf("%v", flags.RotateManagerToken))
 	resp, err := cli.post(ctx, "/swarm/update", query, swarm, nil)
 	ensureReaderClosed(resp)
 	return err

+ 1 - 1
vendor/src/github.com/docker/engine-api/client/transport/cancellable/cancellable.go

@@ -30,7 +30,7 @@ var (
 //
 // This function deviates from the upstream version in golang.org/x/net/context/ctxhttp by
 // taking a Sender interface rather than a *http.Client directly. That allow us to use
-// this funcion with mocked clients and hijacked connections.
+// this function with mocked clients and hijacked connections.
 func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http.Response, error) {
 	if client == nil {
 		client = http.DefaultClient

+ 2 - 2
vendor/src/github.com/docker/engine-api/types/configs.go

@@ -45,8 +45,8 @@ type ExecConfig struct {
 	Privileged   bool     // Is the container in privileged mode
 	Tty          bool     // Attach standard streams to a tty.
 	AttachStdin  bool     // Attach the standard input, makes possible user interaction
-	AttachStderr bool     // Attach the standard output
-	AttachStdout bool     // Attach the standard error
+	AttachStderr bool     // Attach the standard error
+	AttachStdout bool     // Attach the standard output
 	Detach       bool     // Execute in detach mode
 	DetachKeys   string   // Escape keys for detach
 	Cmd          []string // Execution commands and args

+ 0 - 11
vendor/src/github.com/docker/engine-api/types/swarm/node.go

@@ -15,7 +15,6 @@ type Node struct {
 type NodeSpec struct {
 	Annotations
 	Role         NodeRole         `json:",omitempty"`
-	Membership   NodeMembership   `json:",omitempty"`
 	Availability NodeAvailability `json:",omitempty"`
 }
 
@@ -29,16 +28,6 @@ const (
 	NodeRoleManager NodeRole = "manager"
 )
 
-// NodeMembership represents the membership of a node.
-type NodeMembership string
-
-const (
-	// NodeMembershipPending PENDING
-	NodeMembershipPending NodeMembership = "pending"
-	// NodeMembershipAccepted ACCEPTED
-	NodeMembershipAccepted NodeMembership = "accepted"
-)
-
 // NodeAvailability represents the availability of a node.
 type NodeAvailability string
 

+ 37 - 33
vendor/src/github.com/docker/engine-api/types/swarm/swarm.go

@@ -6,38 +6,25 @@ import "time"
 type Swarm struct {
 	ID string
 	Meta
-	Spec Spec
+	Spec       Spec
+	JoinTokens JoinTokens
+}
+
+// JoinTokens contains the tokens workers and managers need to join the swarm.
+type JoinTokens struct {
+	Worker  string
+	Manager string
 }
 
 // Spec represents the spec of a swarm.
 type Spec struct {
 	Annotations
 
-	AcceptancePolicy AcceptancePolicy    `json:",omitempty"`
-	Orchestration    OrchestrationConfig `json:",omitempty"`
-	Raft             RaftConfig          `json:",omitempty"`
-	Dispatcher       DispatcherConfig    `json:",omitempty"`
-	CAConfig         CAConfig            `json:",omitempty"`
-
-	// DefaultLogDriver sets the log driver to use at task creation time if
-	// unspecified by a task.
-	//
-	// Updating this value will only have an affect on new tasks. Old tasks
-	// will continue use their previously configured log driver until
-	// recreated.
-	DefaultLogDriver *Driver `json:",omitempty"`
-}
-
-// AcceptancePolicy represents the list of policies.
-type AcceptancePolicy struct {
-	Policies []Policy `json:",omitempty"`
-}
-
-// Policy represents a role, autoaccept and secret.
-type Policy struct {
-	Role       NodeRole
-	Autoaccept bool
-	Secret     *string `json:",omitempty"`
+	Orchestration OrchestrationConfig `json:",omitempty"`
+	Raft          RaftConfig          `json:",omitempty"`
+	Dispatcher    DispatcherConfig    `json:",omitempty"`
+	CAConfig      CAConfig            `json:",omitempty"`
+	TaskDefaults  TaskDefaults        `json:",omitempty"`
 }
 
 // OrchestrationConfig represents orchestration configuration.
@@ -45,6 +32,17 @@ type OrchestrationConfig struct {
 	TaskHistoryRetentionLimit int64 `json:",omitempty"`
 }
 
+// TaskDefaults parameterizes cluster-level task creation with default values.
+type TaskDefaults struct {
+	// LogDriver selects the log driver to use for tasks created in the
+	// orchestrator if unspecified by a service.
+	//
+	// Updating this value will only have an affect on new tasks. Old tasks
+	// will continue use their previously configured log driver until
+	// recreated.
+	LogDriver *Driver `json:",omitempty"`
+}
+
 // RaftConfig represents raft configuration.
 type RaftConfig struct {
 	SnapshotInterval           uint64 `json:",omitempty"`
@@ -81,17 +79,17 @@ type ExternalCA struct {
 // InitRequest is the request used to init a swarm.
 type InitRequest struct {
 	ListenAddr      string
+	AdvertiseAddr   string
 	ForceNewCluster bool
 	Spec            Spec
 }
 
 // JoinRequest is the request used to join a swarm.
 type JoinRequest struct {
-	ListenAddr  string
-	RemoteAddrs []string
-	Secret      string // accept by secret
-	CACertHash  string
-	Manager     bool
+	ListenAddr    string
+	AdvertiseAddr string
+	RemoteAddrs   []string
+	JoinToken     string // accept by secret
 }
 
 // LocalNodeState represents the state of the local node.
@@ -110,7 +108,8 @@ const (
 
 // Info represents generic information about swarm.
 type Info struct {
-	NodeID string
+	NodeID   string
+	NodeAddr string
 
 	LocalNodeState   LocalNodeState
 	ControlAvailable bool
@@ -119,7 +118,6 @@ type Info struct {
 	RemoteManagers []Peer
 	Nodes          int
 	Managers       int
-	CACertHash     string
 }
 
 // Peer represents a peer.
@@ -127,3 +125,9 @@ type Peer struct {
 	NodeID string
 	Addr   string
 }
+
+// UpdateFlags contains flags for SwarmUpdate.
+type UpdateFlags struct {
+	RotateWorkerToken  bool
+	RotateManagerToken bool
+}

+ 3 - 14
vendor/src/github.com/docker/swarmkit/agent/node.go

@@ -43,11 +43,8 @@ type NodeConfig struct {
 	// remote managers and certificates.
 	StateDir string
 
-	// CAHash to be used on the first certificate request.
-	CAHash string
-
-	// Secret to be used on the first certificate request.
-	Secret string
+	// JoinToken is the token to be used on the first certificate request.
+	JoinToken string
 
 	// ExternalCAs is a list of CAs to which a manager node
 	// will make certificate signing requests for node certificates.
@@ -73,9 +70,6 @@ type NodeConfig struct {
 	// HeartbeatTick defines the amount of ticks between each
 	// heartbeat sent to other members for health-check purposes
 	HeartbeatTick uint32
-
-	// todo: temporary to bypass promotion not working yet
-	IsManager bool
 }
 
 // Node implements the primary node functionality for a member of a swarm
@@ -193,11 +187,6 @@ func (n *Node) run(ctx context.Context) (err error) {
 		}
 	}
 
-	csrRole := n.role
-	if n.config.IsManager { // todo: temporary
-		csrRole = ca.ManagerRole
-	}
-
 	// Obtain new certs and setup TLS certificates renewal for this node:
 	// - We call LoadOrCreateSecurityConfig which blocks until a valid certificate has been issued
 	// - We retrieve the nodeID from LoadOrCreateSecurityConfig through the info channel. This allows
@@ -220,7 +209,7 @@ func (n *Node) run(ctx context.Context) (err error) {
 	}()
 
 	certDir := filepath.Join(n.config.StateDir, "certificates")
-	securityConfig, err := ca.LoadOrCreateSecurityConfig(ctx, certDir, n.config.CAHash, n.config.Secret, csrRole, picker.NewPicker(n.remotes), issueResponseChan)
+	securityConfig, err := ca.LoadOrCreateSecurityConfig(ctx, certDir, n.config.JoinToken, ca.ManagerRole, picker.NewPicker(n.remotes), issueResponseChan)
 	if err != nil {
 		return err
 	}

+ 14 - 1
vendor/src/github.com/docker/swarmkit/agent/task.go

@@ -93,7 +93,7 @@ func (tm *taskManager) run(ctx context.Context) {
 		case <-run:
 			// always check for shutdown before running.
 			select {
-			case <-shutdown:
+			case <-tm.shutdown:
 				continue // ignore run request and handle shutdown
 			case <-tm.closed:
 				continue
@@ -142,6 +142,13 @@ func (tm *taskManager) run(ctx context.Context) {
 			// goal is to decide whether or not we re-dispatch the operation.
 			cancel = nil
 
+			select {
+			case <-tm.shutdown:
+				shutdown = tm.shutdown // re-enable the shutdown branch
+				continue               // no dispatch if we are in shutdown.
+			default:
+			}
+
 			switch err {
 			case exec.ErrTaskNoop:
 				if !updated {
@@ -203,6 +210,12 @@ func (tm *taskManager) run(ctx context.Context) {
 			if cancel != nil {
 				// cancel outstanding operation.
 				cancel()
+
+				// subtle: after a cancellation, we want to avoid busy wait
+				// here. this gets renabled in the errs branch and we'll come
+				// back around and try shutdown again.
+				shutdown = nil // turn off this branch until op proceeds
+				continue       // wait until operation actually exits.
 			}
 
 			// TODO(stevvooe): This should be left for the repear.

+ 48 - 46
vendor/src/github.com/docker/swarmkit/api/ca.pb.go

@@ -51,11 +51,13 @@ func (*NodeCertificateStatusResponse) ProtoMessage()               {}
 func (*NodeCertificateStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorCa, []int{1} }
 
 type IssueNodeCertificateRequest struct {
+	// DEPRECATED: Role is now selected based on which secret is matched.
 	Role NodeRole `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
-	CSR  []byte   `protobuf:"bytes,2,opt,name=csr,proto3" json:"csr,omitempty"`
-	// Secret represents a user-provided string that is necessary for new
+	// CSR is the certificate signing request.
+	CSR []byte `protobuf:"bytes,2,opt,name=csr,proto3" json:"csr,omitempty"`
+	// Token represents a user-provided string that is necessary for new
 	// nodes to join the cluster
-	Secret string `protobuf:"bytes,3,opt,name=secret,proto3" json:"secret,omitempty"`
+	Token string `protobuf:"bytes,3,opt,name=token,proto3" json:"token,omitempty"`
 }
 
 func (m *IssueNodeCertificateRequest) Reset()                    { *m = IssueNodeCertificateRequest{} }
@@ -165,9 +167,9 @@ func (m *IssueNodeCertificateRequest) Copy() *IssueNodeCertificateRequest {
 	}
 
 	o := &IssueNodeCertificateRequest{
-		Role:   m.Role,
-		CSR:    m.CSR,
-		Secret: m.Secret,
+		Role:  m.Role,
+		CSR:   m.CSR,
+		Token: m.Token,
 	}
 
 	return o
@@ -241,7 +243,7 @@ func (this *IssueNodeCertificateRequest) GoString() string {
 	s = append(s, "&api.IssueNodeCertificateRequest{")
 	s = append(s, "Role: "+fmt.Sprintf("%#v", this.Role)+",\n")
 	s = append(s, "CSR: "+fmt.Sprintf("%#v", this.CSR)+",\n")
-	s = append(s, "Secret: "+fmt.Sprintf("%#v", this.Secret)+",\n")
+	s = append(s, "Token: "+fmt.Sprintf("%#v", this.Token)+",\n")
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
@@ -556,11 +558,11 @@ func (m *IssueNodeCertificateRequest) MarshalTo(data []byte) (int, error) {
 		i = encodeVarintCa(data, i, uint64(len(m.CSR)))
 		i += copy(data[i:], m.CSR)
 	}
-	if len(m.Secret) > 0 {
+	if len(m.Token) > 0 {
 		data[i] = 0x1a
 		i++
-		i = encodeVarintCa(data, i, uint64(len(m.Secret)))
-		i += copy(data[i:], m.Secret)
+		i = encodeVarintCa(data, i, uint64(len(m.Token)))
+		i += copy(data[i:], m.Token)
 	}
 	return i, nil
 }
@@ -836,7 +838,7 @@ func (m *IssueNodeCertificateRequest) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovCa(uint64(l))
 	}
-	l = len(m.Secret)
+	l = len(m.Token)
 	if l > 0 {
 		n += 1 + l + sovCa(uint64(l))
 	}
@@ -913,7 +915,7 @@ func (this *IssueNodeCertificateRequest) String() string {
 	s := strings.Join([]string{`&IssueNodeCertificateRequest{`,
 		`Role:` + fmt.Sprintf("%v", this.Role) + `,`,
 		`CSR:` + fmt.Sprintf("%v", this.CSR) + `,`,
-		`Secret:` + fmt.Sprintf("%v", this.Secret) + `,`,
+		`Token:` + fmt.Sprintf("%v", this.Token) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -1232,7 +1234,7 @@ func (m *IssueNodeCertificateRequest) Unmarshal(data []byte) error {
 			iNdEx = postIndex
 		case 3:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field Secret", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType)
 			}
 			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
@@ -1257,7 +1259,7 @@ func (m *IssueNodeCertificateRequest) Unmarshal(data []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			m.Secret = string(data[iNdEx:postIndex])
+			m.Token = string(data[iNdEx:postIndex])
 			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
@@ -1615,36 +1617,36 @@ var (
 )
 
 var fileDescriptorCa = []byte{
-	// 487 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x94, 0xcf, 0x6e, 0xd3, 0x40,
-	0x10, 0xc6, 0x59, 0x07, 0xa5, 0x65, 0x52, 0x05, 0xb4, 0x14, 0x14, 0x52, 0x37, 0xad, 0xcc, 0x01,
-	0x4e, 0x4e, 0x6a, 0x6e, 0x9c, 0x48, 0x8c, 0x84, 0x72, 0x00, 0xa1, 0xcd, 0x03, 0x20, 0xd7, 0x19,
-	0x82, 0xd5, 0x26, 0x6b, 0x76, 0x37, 0x20, 0x6e, 0x08, 0x24, 0x0e, 0xdc, 0x11, 0x9c, 0x78, 0x04,
-	0x9e, 0xa3, 0xe2, 0xc4, 0x91, 0x13, 0xa2, 0x7d, 0x00, 0xc4, 0x23, 0xb0, 0xbb, 0x71, 0x48, 0xff,
-	0xac, 0xa3, 0xf6, 0x30, 0x8a, 0x77, 0x76, 0xbe, 0x2f, 0xbf, 0x9d, 0xf1, 0x1a, 0x56, 0xd3, 0x24,
-	0xcc, 0x05, 0x57, 0x9c, 0xd2, 0x21, 0x4f, 0xf7, 0x50, 0x84, 0xf2, 0x75, 0x22, 0xc6, 0x7b, 0x99,
-	0x0a, 0x5f, 0xed, 0x34, 0x6b, 0xea, 0x4d, 0x8e, 0x72, 0x56, 0xd0, 0xac, 0xc9, 0x1c, 0xd3, 0xf9,
-	0x62, 0x7d, 0xc4, 0x47, 0xdc, 0x3e, 0xb6, 0xcd, 0x53, 0x91, 0xbd, 0x9e, 0xef, 0x4f, 0x47, 0xd9,
-	0xa4, 0x3d, 0xfb, 0x99, 0x25, 0x83, 0x18, 0xfc, 0x27, 0x7c, 0x88, 0x31, 0x0a, 0x95, 0x3d, 0xcf,
-	0xd2, 0x44, 0xe1, 0x40, 0x25, 0x6a, 0x2a, 0x19, 0xbe, 0x9c, 0xa2, 0x54, 0xf4, 0x36, 0xac, 0x4c,
-	0xf4, 0xfe, 0xb3, 0x6c, 0xd8, 0x20, 0xdb, 0xe4, 0xee, 0x95, 0x1e, 0x1c, 0xfd, 0xda, 0xaa, 0x1a,
-	0x49, 0xff, 0x21, 0xab, 0x9a, 0xad, 0xfe, 0x30, 0xf8, 0x4a, 0x60, 0xb3, 0xc4, 0x45, 0xe6, 0x7c,
-	0x22, 0x91, 0xde, 0x87, 0xaa, 0xb4, 0x19, 0xeb, 0x52, 0x8b, 0x82, 0xf0, 0xec, 0x81, 0xc2, 0xbe,
-	0x94, 0xd3, 0x64, 0x92, 0xce, 0xb5, 0x85, 0x82, 0x76, 0xa1, 0x96, 0x2e, 0x8c, 0x1b, 0x9e, 0x35,
-	0xd8, 0x72, 0x19, 0x1c, 0xfb, 0x7f, 0x76, 0x5c, 0x13, 0xbc, 0x23, 0xb0, 0x61, 0xdc, 0xf1, 0x14,
-	0xe5, 0xfc, 0x94, 0x1d, 0xb8, 0x2c, 0xf8, 0x3e, 0x5a, 0xb8, 0x7a, 0xe4, 0xbb, 0xbc, 0x8d, 0x92,
-	0xe9, 0x1a, 0x66, 0x2b, 0xe9, 0x2d, 0xa8, 0xa4, 0x52, 0x58, 0x98, 0xb5, 0xde, 0x8a, 0xee, 0x49,
-	0x25, 0x1e, 0x30, 0x66, 0x72, 0xf4, 0xa6, 0x3e, 0x2b, 0xa6, 0x02, 0x55, 0xa3, 0x62, 0x3a, 0xc6,
-	0x8a, 0x55, 0xf0, 0x89, 0x80, 0xef, 0x86, 0x28, 0x9a, 0x74, 0x9e, 0x5e, 0xd3, 0xa7, 0x70, 0xd5,
-	0x16, 0x8d, 0x71, 0xbc, 0x8b, 0x42, 0xbe, 0xc8, 0x72, 0x0b, 0x51, 0x8f, 0xee, 0x94, 0x51, 0x0f,
-	0xf4, 0x9b, 0x11, 0x3e, 0xfe, 0x5f, 0xce, 0xea, 0x46, 0xbf, 0x58, 0x07, 0x9b, 0xb0, 0xf1, 0x08,
-	0x15, 0xe3, 0x5c, 0xc5, 0xdd, 0xb3, 0xbd, 0x09, 0x1e, 0x80, 0xef, 0xde, 0x2e, 0xa8, 0xb7, 0x4f,
-	0x8e, 0xc7, 0x90, 0xaf, 0x9d, 0xe8, 0x7e, 0xf4, 0x91, 0x80, 0x17, 0x77, 0xe9, 0x7b, 0x02, 0xeb,
-	0x2e, 0x27, 0xda, 0x76, 0x91, 0x2f, 0x41, 0x6a, 0x76, 0xce, 0x2f, 0x98, 0x41, 0x06, 0xab, 0xdf,
-	0xbf, 0xfd, 0xf9, 0xe2, 0x79, 0xd7, 0x48, 0xf4, 0xd9, 0x03, 0xdb, 0xd2, 0x02, 0xc8, 0x35, 0x10,
-	0x37, 0xd0, 0x92, 0xf7, 0xc7, 0x0d, 0xb4, 0x6c, 0xd6, 0x0b, 0x20, 0xfa, 0x81, 0xc0, 0x0d, 0xe7,
-	0xe5, 0xa1, 0x9d, 0xb2, 0x89, 0x96, 0xdd, 0xd6, 0xe6, 0xce, 0x05, 0x14, 0xa7, 0x41, 0x7a, 0xfe,
-	0xc1, 0x61, 0xeb, 0xd2, 0x4f, 0x1d, 0x7f, 0x0f, 0x5b, 0xe4, 0xed, 0x51, 0x8b, 0x1c, 0xe8, 0xf8,
-	0xa1, 0xe3, 0xb7, 0x8e, 0xdd, 0xaa, 0xfd, 0x5e, 0xdc, 0xfb, 0x17, 0x00, 0x00, 0xff, 0xff, 0x72,
-	0xd0, 0xad, 0xdf, 0x94, 0x04, 0x00, 0x00,
+	// 490 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x94, 0xcf, 0x8e, 0xd3, 0x30,
+	0x10, 0xc6, 0x71, 0x0a, 0xdd, 0x65, 0xba, 0x2a, 0xc8, 0x14, 0xa9, 0x74, 0xb3, 0xdd, 0x95, 0x39,
+	0xc0, 0x29, 0xdd, 0x0d, 0x9c, 0x38, 0xd1, 0x06, 0x09, 0xf5, 0x00, 0x42, 0xee, 0x03, 0xa0, 0x6c,
+	0x6a, 0x4a, 0xd4, 0x6d, 0x1c, 0x62, 0x07, 0xc4, 0x0d, 0x09, 0xc4, 0x81, 0x3b, 0x82, 0x13, 0x8f,
+	0xc0, 0x73, 0xac, 0x38, 0x71, 0xe4, 0x84, 0xd8, 0x7d, 0x00, 0xc4, 0x23, 0x60, 0x3b, 0x29, 0xdd,
+	0x3f, 0x4e, 0x55, 0x0e, 0xa3, 0xc6, 0xe3, 0xf9, 0xbe, 0xfe, 0x32, 0x63, 0x07, 0xd6, 0xa3, 0xd0,
+	0x4b, 0x33, 0x2e, 0x39, 0xc6, 0x63, 0x1e, 0x4d, 0x59, 0xe6, 0x89, 0x57, 0x61, 0x36, 0x9b, 0xc6,
+	0xd2, 0x7b, 0xb9, 0xd7, 0x69, 0xc8, 0xd7, 0x29, 0x13, 0x45, 0x41, 0xa7, 0x21, 0x52, 0x16, 0xcd,
+	0x17, 0xad, 0x09, 0x9f, 0x70, 0xf3, 0xd8, 0xd3, 0x4f, 0x65, 0xf6, 0x5a, 0x7a, 0x90, 0x4f, 0xe2,
+	0xa4, 0x57, 0xfc, 0x14, 0x49, 0x12, 0x80, 0xfb, 0x98, 0x8f, 0x59, 0xc0, 0x32, 0x19, 0x3f, 0x8b,
+	0xa3, 0x50, 0xb2, 0x91, 0x0c, 0x65, 0x2e, 0x28, 0x7b, 0x91, 0x33, 0x21, 0xf1, 0x4d, 0x58, 0x4b,
+	0xd4, 0xfe, 0xd3, 0x78, 0xdc, 0x46, 0x3b, 0xe8, 0xf6, 0xe5, 0x01, 0x1c, 0xff, 0xdc, 0xae, 0x6b,
+	0xc9, 0xf0, 0x01, 0xad, 0xeb, 0xad, 0xe1, 0x98, 0x7c, 0x41, 0xb0, 0x55, 0xe1, 0x22, 0x52, 0x9e,
+	0x08, 0x86, 0xef, 0x41, 0x5d, 0x98, 0x8c, 0x71, 0x69, 0xf8, 0xc4, 0x3b, 0xff, 0x42, 0xde, 0x50,
+	0x88, 0x3c, 0x4c, 0xa2, 0xb9, 0xb6, 0x54, 0xe0, 0x3e, 0x34, 0xa2, 0x85, 0x71, 0xdb, 0x31, 0x06,
+	0xdb, 0x36, 0x83, 0x13, 0xff, 0x4f, 0x4f, 0x6a, 0xc8, 0x3b, 0x04, 0x9b, 0xda, 0x9d, 0x9d, 0xa1,
+	0x9c, 0xbf, 0xe5, 0x5d, 0xb8, 0x98, 0xf1, 0x03, 0x66, 0xe0, 0x9a, 0xbe, 0x6b, 0xf3, 0xd6, 0x4a,
+	0xaa, 0x6a, 0x06, 0x4e, 0x1b, 0x51, 0x53, 0x8d, 0x6f, 0x40, 0x2d, 0x12, 0x99, 0x01, 0xda, 0x18,
+	0xac, 0xa9, 0xbe, 0xd4, 0x82, 0x11, 0xa5, 0x3a, 0x87, 0x5b, 0x70, 0x49, 0xf2, 0x29, 0x4b, 0xda,
+	0x35, 0xdd, 0x34, 0x5a, 0x2c, 0xc8, 0x47, 0x04, 0xae, 0x1d, 0xa3, 0x6c, 0xd3, 0x2a, 0xdd, 0xc6,
+	0x4f, 0xe0, 0x8a, 0x29, 0x9a, 0xb1, 0xd9, 0x3e, 0xcb, 0xc4, 0xf3, 0x38, 0x35, 0x08, 0x4d, 0xff,
+	0x56, 0x15, 0xf7, 0x48, 0x9d, 0x0d, 0xef, 0xd1, 0xbf, 0x72, 0xda, 0xd4, 0xfa, 0xc5, 0x9a, 0x6c,
+	0xc1, 0xe6, 0x43, 0x26, 0x29, 0xe7, 0x32, 0xe8, 0x9f, 0xef, 0x0e, 0xb9, 0x0f, 0xae, 0x7d, 0xbb,
+	0xa4, 0xde, 0x39, 0x3d, 0x20, 0x4d, 0xbe, 0x71, 0xaa, 0xff, 0xfe, 0x07, 0x04, 0x4e, 0xd0, 0xc7,
+	0x6f, 0x11, 0xb4, 0x6c, 0x4e, 0xb8, 0x67, 0x23, 0x5f, 0x82, 0xd4, 0xd9, 0x5d, 0x5d, 0x50, 0x40,
+	0x92, 0xf5, 0x6f, 0x5f, 0x7f, 0x7f, 0x76, 0x9c, 0xab, 0xc8, 0xff, 0xe4, 0x80, 0x69, 0x69, 0x09,
+	0x64, 0x1b, 0x88, 0x1d, 0x68, 0xc9, 0x09, 0xb2, 0x03, 0x2d, 0x9b, 0xf5, 0x02, 0x08, 0xbf, 0x47,
+	0x70, 0xdd, 0x7a, 0x7d, 0xf0, 0x6e, 0xd5, 0x44, 0xab, 0xee, 0x6b, 0x67, 0xef, 0x3f, 0x14, 0x67,
+	0x41, 0x06, 0xee, 0xe1, 0x51, 0xf7, 0xc2, 0x0f, 0x15, 0x7f, 0x8e, 0xba, 0xe8, 0xcd, 0x71, 0x17,
+	0x1d, 0xaa, 0xf8, 0xae, 0xe2, 0x97, 0x8a, 0xfd, 0xba, 0xf9, 0x62, 0xdc, 0xf9, 0x1b, 0x00, 0x00,
+	0xff, 0xff, 0xb3, 0xf8, 0x41, 0xef, 0x96, 0x04, 0x00, 0x00,
 }

+ 7 - 3
vendor/src/github.com/docker/swarmkit/api/ca.proto

@@ -34,11 +34,15 @@ message NodeCertificateStatusResponse {
 }
 
 message IssueNodeCertificateRequest {
-	NodeRole role = 1;
+	// DEPRECATED: Role is now selected based on which secret is matched.
+	NodeRole role = 1 [deprecated=true];
+
+	// CSR is the certificate signing request.
 	bytes csr = 2 [(gogoproto.customname) = "CSR"];
-	// Secret represents a user-provided string that is necessary for new
+
+	// Token represents a user-provided string that is necessary for new
 	// nodes to join the cluster
-	string secret = 3;
+	string token = 3;
 }
 
 message IssueNodeCertificateResponse {

+ 332 - 94
vendor/src/github.com/docker/swarmkit/api/control.pb.go

@@ -403,6 +403,17 @@ func (m *ListClustersResponse) Reset()                    { *m = ListClustersRes
 func (*ListClustersResponse) ProtoMessage()               {}
 func (*ListClustersResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{35} }
 
+type JoinTokenRotation struct {
+	// RotateWorkerToken tells UpdateCluster to rotate the worker secret.
+	RotateWorkerToken bool `protobuf:"varint,1,opt,name=rotate_worker_token,json=rotateWorkerToken,proto3" json:"rotate_worker_token,omitempty"`
+	// RotateManagerSecret tells UpdateCluster to rotate the manager secret.
+	RotateManagerToken bool `protobuf:"varint,2,opt,name=rotate_manager_token,json=rotateManagerToken,proto3" json:"rotate_manager_token,omitempty"`
+}
+
+func (m *JoinTokenRotation) Reset()                    { *m = JoinTokenRotation{} }
+func (*JoinTokenRotation) ProtoMessage()               {}
+func (*JoinTokenRotation) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{36} }
+
 type UpdateClusterRequest struct {
 	// ClusterID is the cluster ID to update.
 	ClusterID string `protobuf:"bytes,1,opt,name=cluster_id,json=clusterId,proto3" json:"cluster_id,omitempty"`
@@ -410,11 +421,13 @@ type UpdateClusterRequest struct {
 	ClusterVersion *Version `protobuf:"bytes,2,opt,name=cluster_version,json=clusterVersion" json:"cluster_version,omitempty"`
 	// Spec is the new spec to apply to the cluster.
 	Spec *ClusterSpec `protobuf:"bytes,3,opt,name=spec" json:"spec,omitempty"`
+	// Rotation contains flags for join token rotation
+	Rotation JoinTokenRotation `protobuf:"bytes,4,opt,name=rotation" json:"rotation"`
 }
 
 func (m *UpdateClusterRequest) Reset()                    { *m = UpdateClusterRequest{} }
 func (*UpdateClusterRequest) ProtoMessage()               {}
-func (*UpdateClusterRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{36} }
+func (*UpdateClusterRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{37} }
 
 type UpdateClusterResponse struct {
 	Cluster *Cluster `protobuf:"bytes,1,opt,name=cluster" json:"cluster,omitempty"`
@@ -422,7 +435,7 @@ type UpdateClusterResponse struct {
 
 func (m *UpdateClusterResponse) Reset()                    { *m = UpdateClusterResponse{} }
 func (*UpdateClusterResponse) ProtoMessage()               {}
-func (*UpdateClusterResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{37} }
+func (*UpdateClusterResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{38} }
 
 func init() {
 	proto.RegisterType((*GetNodeRequest)(nil), "docker.swarmkit.v1.GetNodeRequest")
@@ -466,6 +479,7 @@ func init() {
 	proto.RegisterType((*ListClustersRequest)(nil), "docker.swarmkit.v1.ListClustersRequest")
 	proto.RegisterType((*ListClustersRequest_Filters)(nil), "docker.swarmkit.v1.ListClustersRequest.Filters")
 	proto.RegisterType((*ListClustersResponse)(nil), "docker.swarmkit.v1.ListClustersResponse")
+	proto.RegisterType((*JoinTokenRotation)(nil), "docker.swarmkit.v1.JoinTokenRotation")
 	proto.RegisterType((*UpdateClusterRequest)(nil), "docker.swarmkit.v1.UpdateClusterRequest")
 	proto.RegisterType((*UpdateClusterResponse)(nil), "docker.swarmkit.v1.UpdateClusterResponse")
 }
@@ -1314,6 +1328,19 @@ func (m *ListClustersResponse) Copy() *ListClustersResponse {
 	return o
 }
 
+func (m *JoinTokenRotation) Copy() *JoinTokenRotation {
+	if m == nil {
+		return nil
+	}
+
+	o := &JoinTokenRotation{
+		RotateWorkerToken:  m.RotateWorkerToken,
+		RotateManagerToken: m.RotateManagerToken,
+	}
+
+	return o
+}
+
 func (m *UpdateClusterRequest) Copy() *UpdateClusterRequest {
 	if m == nil {
 		return nil
@@ -1323,6 +1350,7 @@ func (m *UpdateClusterRequest) Copy() *UpdateClusterRequest {
 		ClusterID:      m.ClusterID,
 		ClusterVersion: m.ClusterVersion.Copy(),
 		Spec:           m.Spec.Copy(),
+		Rotation:       *m.Rotation.Copy(),
 	}
 
 	return o
@@ -1882,11 +1910,22 @@ func (this *ListClustersResponse) GoString() string {
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
+func (this *JoinTokenRotation) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 6)
+	s = append(s, "&api.JoinTokenRotation{")
+	s = append(s, "RotateWorkerToken: "+fmt.Sprintf("%#v", this.RotateWorkerToken)+",\n")
+	s = append(s, "RotateManagerToken: "+fmt.Sprintf("%#v", this.RotateManagerToken)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
 func (this *UpdateClusterRequest) GoString() string {
 	if this == nil {
 		return "nil"
 	}
-	s := make([]string, 0, 7)
+	s := make([]string, 0, 8)
 	s = append(s, "&api.UpdateClusterRequest{")
 	s = append(s, "ClusterID: "+fmt.Sprintf("%#v", this.ClusterID)+",\n")
 	if this.ClusterVersion != nil {
@@ -1895,6 +1934,7 @@ func (this *UpdateClusterRequest) GoString() string {
 	if this.Spec != nil {
 		s = append(s, "Spec: "+fmt.Sprintf("%#v", this.Spec)+",\n")
 	}
+	s = append(s, "Rotation: "+strings.Replace(this.Rotation.GoString(), `&`, ``, 1)+",\n")
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
@@ -4038,6 +4078,44 @@ func (m *ListClustersResponse) MarshalTo(data []byte) (int, error) {
 	return i, nil
 }
 
+func (m *JoinTokenRotation) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *JoinTokenRotation) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.RotateWorkerToken {
+		data[i] = 0x8
+		i++
+		if m.RotateWorkerToken {
+			data[i] = 1
+		} else {
+			data[i] = 0
+		}
+		i++
+	}
+	if m.RotateManagerToken {
+		data[i] = 0x10
+		i++
+		if m.RotateManagerToken {
+			data[i] = 1
+		} else {
+			data[i] = 0
+		}
+		i++
+	}
+	return i, nil
+}
+
 func (m *UpdateClusterRequest) Marshal() (data []byte, err error) {
 	size := m.Size()
 	data = make([]byte, size)
@@ -4079,6 +4157,14 @@ func (m *UpdateClusterRequest) MarshalTo(data []byte) (int, error) {
 		}
 		i += n22
 	}
+	data[i] = 0x22
+	i++
+	i = encodeVarintControl(data, i, uint64(m.Rotation.Size()))
+	n23, err := m.Rotation.MarshalTo(data[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n23
 	return i, nil
 }
 
@@ -4101,11 +4187,11 @@ func (m *UpdateClusterResponse) MarshalTo(data []byte) (int, error) {
 		data[i] = 0xa
 		i++
 		i = encodeVarintControl(data, i, uint64(m.Cluster.Size()))
-		n23, err := m.Cluster.MarshalTo(data[i:])
+		n24, err := m.Cluster.MarshalTo(data[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n23
+		i += n24
 	}
 	return i, nil
 }
@@ -5052,6 +5138,18 @@ func (m *ListClustersResponse) Size() (n int) {
 	return n
 }
 
+func (m *JoinTokenRotation) Size() (n int) {
+	var l int
+	_ = l
+	if m.RotateWorkerToken {
+		n += 2
+	}
+	if m.RotateManagerToken {
+		n += 2
+	}
+	return n
+}
+
 func (m *UpdateClusterRequest) Size() (n int) {
 	var l int
 	_ = l
@@ -5067,6 +5165,8 @@ func (m *UpdateClusterRequest) Size() (n int) {
 		l = m.Spec.Size()
 		n += 1 + l + sovControl(uint64(l))
 	}
+	l = m.Rotation.Size()
+	n += 1 + l + sovControl(uint64(l))
 	return n
 }
 
@@ -5575,6 +5675,17 @@ func (this *ListClustersResponse) String() string {
 	}, "")
 	return s
 }
+func (this *JoinTokenRotation) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&JoinTokenRotation{`,
+		`RotateWorkerToken:` + fmt.Sprintf("%v", this.RotateWorkerToken) + `,`,
+		`RotateManagerToken:` + fmt.Sprintf("%v", this.RotateManagerToken) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *UpdateClusterRequest) String() string {
 	if this == nil {
 		return "nil"
@@ -5583,6 +5694,7 @@ func (this *UpdateClusterRequest) String() string {
 		`ClusterID:` + fmt.Sprintf("%v", this.ClusterID) + `,`,
 		`ClusterVersion:` + strings.Replace(fmt.Sprintf("%v", this.ClusterVersion), "Version", "Version", 1) + `,`,
 		`Spec:` + strings.Replace(fmt.Sprintf("%v", this.Spec), "ClusterSpec", "ClusterSpec", 1) + `,`,
+		`Rotation:` + strings.Replace(strings.Replace(this.Rotation.String(), "JoinTokenRotation", "JoinTokenRotation", 1), `&`, ``, 1) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -9955,6 +10067,96 @@ func (m *ListClustersResponse) Unmarshal(data []byte) error {
 	}
 	return nil
 }
+func (m *JoinTokenRotation) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowControl
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: JoinTokenRotation: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: JoinTokenRotation: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field RotateWorkerToken", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				v |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.RotateWorkerToken = bool(v != 0)
+		case 2:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field RotateManagerToken", wireType)
+			}
+			var v int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				v |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.RotateManagerToken = bool(v != 0)
+		default:
+			iNdEx = preIndex
+			skippy, err := skipControl(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthControl
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *UpdateClusterRequest) Unmarshal(data []byte) error {
 	l := len(data)
 	iNdEx := 0
@@ -10079,6 +10281,36 @@ func (m *UpdateClusterRequest) Unmarshal(data []byte) error {
 				return err
 			}
 			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Rotation", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowControl
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthControl
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Rotation.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipControl(data[iNdEx:])
@@ -10289,93 +10521,99 @@ var (
 )
 
 var fileDescriptorControl = []byte{
-	// 1406 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x59, 0x4f, 0x6f, 0x1b, 0x45,
-	0x14, 0xc7, 0xce, 0x1f, 0xd7, 0xcf, 0xb1, 0xd3, 0x4c, 0x1d, 0x11, 0xb9, 0x21, 0x45, 0x5b, 0x48,
-	0x13, 0x29, 0x38, 0xe0, 0xa8, 0x22, 0x80, 0x04, 0x22, 0x09, 0x45, 0x16, 0x25, 0x54, 0x1b, 0x8a,
-	0xb8, 0x45, 0x8e, 0x3d, 0x0d, 0x4b, 0x6c, 0xaf, 0xd9, 0xdd, 0xa4, 0x8d, 0xb8, 0xc0, 0x81, 0xef,
-	0xc0, 0x95, 0x2b, 0x07, 0xbe, 0x02, 0xd7, 0x8a, 0x13, 0x17, 0x24, 0x4e, 0x15, 0xed, 0x89, 0x13,
-	0xe2, 0x13, 0x20, 0x66, 0x76, 0xde, 0xec, 0xae, 0xc7, 0xb3, 0x63, 0x3b, 0x49, 0x95, 0x1e, 0xac,
-	0xee, 0xce, 0xfc, 0xde, 0x9f, 0x99, 0xf7, 0x7b, 0x2f, 0xef, 0x6d, 0xa1, 0xd8, 0x74, 0xbb, 0x81,
-	0xe7, 0xb6, 0xab, 0x3d, 0xcf, 0x0d, 0x5c, 0x42, 0x5a, 0x6e, 0xf3, 0x88, 0x7a, 0x55, 0xff, 0x61,
-	0xc3, 0xeb, 0x1c, 0x39, 0x41, 0xf5, 0xe4, 0xad, 0x4a, 0xc1, 0xef, 0xd1, 0xa6, 0x2f, 0x00, 0x95,
-	0xa2, 0x7b, 0xf0, 0x35, 0x6d, 0x06, 0xf2, 0xb5, 0x10, 0x9c, 0xf6, 0xa8, 0x7c, 0x29, 0x1f, 0xba,
-	0x87, 0x6e, 0xf8, 0xb8, 0xce, 0x9f, 0x70, 0xf5, 0x5a, 0xaf, 0x7d, 0x7c, 0xe8, 0x74, 0xd7, 0xc5,
-	0x3f, 0x62, 0xd1, 0xba, 0x0d, 0xa5, 0x8f, 0x69, 0xb0, 0xeb, 0xb6, 0xa8, 0x4d, 0xbf, 0x39, 0xa6,
-	0x7e, 0x40, 0x6e, 0x42, 0xae, 0xcb, 0x5e, 0xf7, 0x9d, 0xd6, 0x42, 0xe6, 0xd5, 0xcc, 0x4a, 0x7e,
-	0x0b, 0x9e, 0x3d, 0xb9, 0x31, 0xcd, 0x11, 0xf5, 0x1d, 0x7b, 0x9a, 0x6f, 0xd5, 0x5b, 0xd6, 0x07,
-	0x30, 0x1b, 0x89, 0xf9, 0x3d, 0xb7, 0xeb, 0x53, 0xb2, 0x06, 0x93, 0x7c, 0x33, 0x14, 0x2a, 0xd4,
-	0x16, 0xaa, 0x83, 0x07, 0xa8, 0x86, 0xf8, 0x10, 0x65, 0x3d, 0x99, 0x80, 0xab, 0x77, 0x1d, 0x3f,
-	0x54, 0xe1, 0x4b, 0xd3, 0x77, 0x20, 0xf7, 0xc0, 0x69, 0x07, 0xd4, 0xf3, 0x51, 0xcb, 0x9a, 0x4e,
-	0x8b, 0x2a, 0x56, 0xbd, 0x23, 0x64, 0x6c, 0x29, 0x5c, 0xf9, 0x7e, 0x02, 0x72, 0xb8, 0x48, 0xca,
-	0x30, 0xd5, 0x6d, 0x74, 0x28, 0xd7, 0x38, 0xb1, 0x92, 0xb7, 0xc5, 0x0b, 0x59, 0x87, 0x82, 0xd3,
-	0xda, 0xef, 0x79, 0xf4, 0x81, 0xf3, 0x88, 0xed, 0x65, 0xf9, 0xde, 0x56, 0x89, 0x1d, 0x14, 0xea,
-	0x3b, 0xf7, 0x70, 0xd5, 0x06, 0xa7, 0x25, 0x9f, 0xc9, 0x3d, 0x98, 0x6e, 0x37, 0x0e, 0x68, 0xdb,
-	0x5f, 0x98, 0x60, 0xd8, 0x42, 0x6d, 0x73, 0x1c, 0xcf, 0xaa, 0x77, 0x43, 0xd1, 0x8f, 0x58, 0x80,
-	0x4f, 0x6d, 0xd4, 0x43, 0xea, 0x50, 0xe8, 0xd0, 0xce, 0x01, 0xdb, 0xfe, 0xca, 0xe9, 0xf9, 0x0b,
-	0x93, 0x4c, 0x6d, 0xa9, 0x76, 0x2b, 0xed, 0xda, 0xf6, 0x58, 0xe8, 0xab, 0x9f, 0x46, 0x78, 0x3b,
-	0x29, 0x4b, 0x6a, 0x30, 0xc5, 0x98, 0xc3, 0xce, 0x31, 0x15, 0x2a, 0x59, 0x4c, 0xbd, 0x7b, 0x06,
-	0xb2, 0x05, 0x94, 0x85, 0xb9, 0xc8, 0xaf, 0x22, 0xbe, 0x83, 0xe9, 0xf0, 0x7e, 0x66, 0xf8, 0xa2,
-	0x3c, 0x75, 0xe5, 0x1d, 0x28, 0x24, 0x5c, 0x27, 0x57, 0x61, 0xe2, 0x88, 0x9e, 0x0a, 0x5a, 0xd8,
-	0xfc, 0x91, 0xdf, 0xee, 0x49, 0xa3, 0x7d, 0x4c, 0xd9, 0x0d, 0xf2, 0x35, 0xf1, 0xf2, 0x6e, 0x76,
-	0x33, 0x63, 0x6d, 0xc3, 0x5c, 0xe2, 0x3a, 0x90, 0x23, 0x55, 0x16, 0x0c, 0xbe, 0x10, 0x06, 0xc3,
-	0x44, 0x12, 0x01, 0xb3, 0x7e, 0xce, 0xc0, 0xdc, 0xfd, 0x5e, 0xab, 0x11, 0xd0, 0x71, 0x19, 0x4a,
-	0xde, 0x87, 0x99, 0x10, 0x74, 0xc2, 0x2e, 0xc9, 0x71, 0xbb, 0xa1, 0x83, 0x85, 0xda, 0x75, 0x9d,
-	0xc5, 0x2f, 0x04, 0xc4, 0x2e, 0x70, 0x01, 0x7c, 0x21, 0x6f, 0xc2, 0x24, 0x4f, 0x37, 0x16, 0x6e,
-	0x2e, 0xb7, 0x68, 0x8a, 0x8b, 0x1d, 0x22, 0xad, 0x2d, 0x20, 0x49, 0x5f, 0xcf, 0x94, 0x16, 0x9b,
-	0x30, 0x67, 0xd3, 0x8e, 0x7b, 0x32, 0xf6, 0x79, 0xad, 0x32, 0x90, 0xa4, 0xa4, 0xb0, 0x8e, 0xe9,
-	0xfd, 0x79, 0xc3, 0x3f, 0x4a, 0x28, 0x0b, 0xd8, 0xab, 0xa2, 0x8c, 0x23, 0xb8, 0x32, 0xbe, 0x15,
-	0xa5, 0xb7, 0x10, 0x8b, 0xcf, 0xc1, 0x37, 0x4d, 0xe7, 0x08, 0xf1, 0x21, 0x2a, 0x3e, 0xc7, 0xd8,
-	0xa6, 0xa3, 0x73, 0x24, 0xad, 0x5b, 0xff, 0x61, 0xb9, 0xe0, 0x8b, 0x67, 0x28, 0x17, 0x49, 0xb1,
-	0xc1, 0x72, 0xf1, 0xd3, 0x25, 0x96, 0x0b, 0x9d, 0x67, 0xda, 0x72, 0xc1, 0x5c, 0xf0, 0xa9, 0x77,
-	0xe2, 0x34, 0x39, 0x0f, 0x44, 0xb9, 0x40, 0x17, 0xf6, 0xc4, 0x72, 0x7d, 0x87, 0xb9, 0x80, 0x90,
-	0x7a, 0xcb, 0x27, 0xcb, 0x70, 0x05, 0x59, 0x23, 0xea, 0x42, 0x7e, 0xab, 0xc0, 0xd0, 0x39, 0x41,
-	0x1b, 0x76, 0x7a, 0xc1, 0x1b, 0x9f, 0xec, 0x40, 0x89, 0xa5, 0x9a, 0xe3, 0xd1, 0xd6, 0xbe, 0x1f,
-	0x30, 0xf6, 0x8a, 0x4a, 0x50, 0xaa, 0xbd, 0x92, 0x16, 0xe2, 0x3d, 0x8e, 0xb2, 0x8b, 0x28, 0x14,
-	0xbe, 0x69, 0xca, 0x49, 0xee, 0xb9, 0x94, 0x13, 0xbc, 0xae, 0xb8, 0x9c, 0x70, 0xd6, 0x18, 0xcb,
-	0x49, 0x48, 0x23, 0x01, 0xb3, 0x3e, 0x81, 0xf2, 0xb6, 0x47, 0x99, 0xbf, 0x78, 0x65, 0x92, 0x48,
-	0x1b, 0x98, 0xeb, 0x82, 0x45, 0x37, 0x74, 0x6a, 0x50, 0x22, 0x91, 0xee, 0xbb, 0x30, 0xaf, 0x28,
-	0x43, 0xaf, 0x6e, 0x43, 0x0e, 0xc3, 0x80, 0x0a, 0xaf, 0x1b, 0x14, 0xda, 0x12, 0x6b, 0x7d, 0x08,
-	0x73, 0x2c, 0xe7, 0x14, 0xcf, 0xd6, 0x00, 0xe2, 0xa8, 0x63, 0xd6, 0x14, 0x59, 0x18, 0xf3, 0x51,
-	0xd0, 0xed, 0x7c, 0x14, 0x73, 0x76, 0x3e, 0x92, 0x54, 0x71, 0x3e, 0x7f, 0x7e, 0xcd, 0x40, 0x59,
-	0xd4, 0xb3, 0xf3, 0xf8, 0xc4, 0xe8, 0x35, 0x2b, 0xd1, 0x63, 0x94, 0xe2, 0x12, 0xca, 0xc8, 0x6a,
-	0xbc, 0xd1, 0x57, 0x8d, 0x47, 0x8f, 0x90, 0x72, 0x80, 0xf3, 0xdd, 0xc8, 0x0e, 0x94, 0x45, 0x69,
-	0x3a, 0x57, 0x90, 0x5e, 0x86, 0x79, 0x45, 0x0b, 0xd6, 0xb8, 0xbf, 0xb3, 0x70, 0x8d, 0x73, 0x1c,
-	0xd7, 0xa3, 0x32, 0x57, 0x57, 0xcb, 0xdc, 0x7a, 0x5a, 0x31, 0x51, 0x24, 0x07, 0x2b, 0xdd, 0x0f,
-	0xd9, 0x0b, 0xaf, 0x74, 0x7b, 0x4a, 0xa5, 0x7b, 0x6f, 0x4c, 0xe7, 0xb4, 0xc5, 0x6e, 0xa0, 0x9a,
-	0x4c, 0x5e, 0x6c, 0x35, 0xf9, 0x0c, 0xca, 0xfd, 0x2e, 0x21, 0x31, 0xde, 0x86, 0x2b, 0x18, 0x28,
-	0x59, 0x53, 0x8c, 0xcc, 0x88, 0xc0, 0x71, 0x65, 0xd9, 0xa5, 0xc1, 0x43, 0xd7, 0x3b, 0x1a, 0xa3,
-	0xb2, 0xa0, 0x84, 0xae, 0xb2, 0x44, 0xca, 0x62, 0xde, 0x76, 0xc5, 0x92, 0x89, 0xb7, 0x52, 0x4a,
-	0x62, 0xad, 0xfb, 0x61, 0x65, 0x51, 0x3c, 0x23, 0xac, 0x2f, 0x61, 0xb7, 0x89, 0xf7, 0x15, 0x3e,
-	0x73, 0x22, 0xa3, 0x0c, 0x27, 0x72, 0x36, 0x26, 0x32, 0xca, 0x72, 0x22, 0x23, 0x20, 0xaa, 0x36,
-	0x17, 0xe4, 0xe3, 0x97, 0x32, 0xb7, 0x2e, 0xdc, 0xcd, 0x28, 0xdf, 0x14, 0x4f, 0xa3, 0x7c, 0xc3,
-	0xf5, 0x33, 0xe4, 0x9b, 0x22, 0xf9, 0x62, 0xe5, 0x5b, 0x8a, 0x73, 0x97, 0x99, 0x6f, 0xb1, 0x4b,
-	0x71, 0xbe, 0x61, 0xa0, 0x8c, 0xf9, 0x26, 0x23, 0x17, 0x81, 0xf1, 0x8f, 0xe5, 0x76, 0xfb, 0xd8,
-	0x67, 0x67, 0x4a, 0xd4, 0xe1, 0xa6, 0x58, 0x51, 0xea, 0x30, 0xe2, 0x38, 0x2f, 0x10, 0x10, 0xd1,
-	0x37, 0x52, 0x11, 0xd3, 0x17, 0x21, 0x26, 0xfa, 0x4a, 0x29, 0x89, 0x8d, 0xb8, 0x84, 0x1b, 0x67,
-	0xe0, 0x92, 0x22, 0xf9, 0x62, 0x71, 0x29, 0xc5, 0xb9, 0xcb, 0xe4, 0x52, 0xec, 0x52, 0xcc, 0x25,
-	0x8c, 0x86, 0x91, 0x4b, 0x32, 0x74, 0x11, 0x38, 0xd1, 0xe8, 0x9c, 0x87, 0x4f, 0xbc, 0xd1, 0x91,
-	0xe8, 0x71, 0x1a, 0x1d, 0x94, 0x19, 0xa3, 0xd1, 0x41, 0xeb, 0xba, 0x46, 0xe7, 0x62, 0xd8, 0x5c,
-	0xfb, 0x63, 0x0e, 0x72, 0xdb, 0xe2, 0x73, 0x14, 0x71, 0x20, 0x87, 0x5f, 0x7a, 0x88, 0xa5, 0x13,
-	0xee, 0xff, 0x7a, 0x54, 0xb9, 0x69, 0xc4, 0x60, 0xe5, 0x9d, 0xff, 0xed, 0x97, 0x7f, 0x7e, 0xcc,
-	0xce, 0x42, 0x31, 0x04, 0xbd, 0xd1, 0x69, 0x74, 0x1b, 0x87, 0xd4, 0x23, 0x2e, 0xe4, 0xa3, 0x4f,
-	0x06, 0xe4, 0xb5, 0x51, 0x3e, 0xb0, 0x54, 0x5e, 0x1f, 0x82, 0x32, 0x1b, 0xf4, 0x00, 0xe2, 0x89,
-	0x9d, 0x68, 0x75, 0x0d, 0x7c, 0x7d, 0xa8, 0x2c, 0x0f, 0x83, 0x0d, 0xb5, 0x19, 0xcf, 0xe9, 0x7a,
-	0x9b, 0x03, 0x5f, 0x00, 0xf4, 0x36, 0x35, 0xe3, 0x7e, 0x8a, 0x4d, 0x11, 0x43, 0x3e, 0x09, 0xa5,
-	0xc6, 0x30, 0x31, 0xa7, 0xa7, 0xc6, 0xb0, 0x6f, 0x22, 0x37, 0xc7, 0x30, 0x9c, 0xd3, 0xd2, 0x63,
-	0x98, 0x9c, 0x7a, 0xd3, 0x63, 0xd8, 0x37, 0xec, 0x0d, 0xbd, 0xcf, 0xf0, 0x78, 0x86, 0xfb, 0x4c,
-	0x9e, 0x70, 0x79, 0x18, 0x6c, 0xa8, 0xcd, 0x78, 0xce, 0xd2, 0xdb, 0x1c, 0x18, 0xe5, 0xf4, 0x36,
-	0x07, 0xc7, 0xb5, 0x34, 0x9b, 0x8f, 0x60, 0x26, 0xd9, 0xb2, 0x92, 0x5b, 0x23, 0xf6, 0xd9, 0x95,
-	0x95, 0xe1, 0x40, 0xb3, 0xe5, 0x6f, 0xa1, 0xd8, 0x37, 0xe8, 0x12, 0xad, 0x46, 0xdd, 0x60, 0x5d,
-	0x59, 0x1d, 0x01, 0x39, 0xd4, 0x78, 0xdf, 0x0c, 0xa7, 0x37, 0xae, 0x9b, 0x53, 0xf5, 0xc6, 0xb5,
-	0x03, 0xa1, 0xc1, 0x78, 0xdf, 0xa8, 0xa6, 0x37, 0xae, 0x9b, 0x09, 0xf5, 0xc6, 0xf5, 0x73, 0x9f,
-	0x91, 0x64, 0xd8, 0xfa, 0xa4, 0x92, 0xac, 0xbf, 0x5d, 0x4e, 0x25, 0x99, 0xda, 0xfb, 0x9a, 0x49,
-	0x26, 0xfb, 0xb4, 0x74, 0x92, 0x29, 0xcd, 0x65, 0x3a, 0xc9, 0xd4, 0x96, 0x6f, 0x28, 0xc9, 0xe4,
-	0x81, 0x0d, 0x24, 0x53, 0xce, 0xbc, 0x3a, 0x02, 0x72, 0xc4, 0x38, 0x1b, 0x8d, 0xeb, 0xe6, 0x13,
-	0x53, 0x9c, 0x47, 0x34, 0x2e, 0xe2, 0x8c, 0x7f, 0x83, 0x53, 0xe3, 0xdc, 0xdf, 0x9a, 0xa4, 0xc6,
-	0x59, 0x69, 0x00, 0x86, 0xc4, 0x59, 0xf6, 0x50, 0xe9, 0x71, 0x56, 0x1a, 0xbf, 0xf4, 0x38, 0xab,
-	0xed, 0xd8, 0xd0, 0x7c, 0x96, 0x07, 0x36, 0xe4, 0xb3, 0x72, 0xe6, 0xd5, 0x11, 0x90, 0x46, 0xe3,
-	0x5b, 0x8b, 0x8f, 0x9f, 0x2e, 0xbd, 0xf4, 0x27, 0xfb, 0xfd, 0xfb, 0x74, 0x29, 0xf3, 0xdd, 0xb3,
-	0xa5, 0xcc, 0x63, 0xf6, 0xfb, 0x9d, 0xfd, 0xfe, 0x62, 0xbf, 0x83, 0xe9, 0xf0, 0x7f, 0xc4, 0x36,
-	0xfe, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x53, 0x9c, 0xb7, 0x2f, 0x8a, 0x1b, 0x00, 0x00,
+	// 1498 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x59, 0xcf, 0x6f, 0x1b, 0xc5,
+	0x17, 0xaf, 0x9d, 0x34, 0x8e, 0x9f, 0x6b, 0xb7, 0x9e, 0xba, 0xfa, 0x46, 0x6e, 0xbf, 0x09, 0xda,
+	0xd2, 0x34, 0x91, 0x82, 0x03, 0x8e, 0x2a, 0x02, 0x48, 0x20, 0x9c, 0xd0, 0xca, 0xd0, 0x86, 0x6a,
+	0xd3, 0x02, 0xb7, 0xc8, 0xb1, 0xa7, 0x61, 0xf1, 0x8f, 0x35, 0xbb, 0x9b, 0xb4, 0x11, 0x17, 0x38,
+	0x20, 0xf1, 0x27, 0x70, 0xe5, 0xca, 0x81, 0x7f, 0x81, 0x6b, 0xc4, 0x89, 0x0b, 0x12, 0xa7, 0x88,
+	0xf6, 0xc4, 0x09, 0xf1, 0x17, 0x20, 0xe6, 0xc7, 0x9b, 0xdd, 0xf5, 0x7a, 0x76, 0x6d, 0x27, 0x41,
+	0xe9, 0xc1, 0xca, 0xee, 0xcc, 0xe7, 0xfd, 0x98, 0x79, 0x9f, 0xf7, 0xf6, 0xcd, 0x04, 0xf2, 0x4d,
+	0xbb, 0xe7, 0x39, 0x76, 0xa7, 0xd2, 0x77, 0x6c, 0xcf, 0x26, 0xa4, 0x65, 0x37, 0xdb, 0xd4, 0xa9,
+	0xb8, 0x4f, 0x1b, 0x4e, 0xb7, 0x6d, 0x79, 0x95, 0x83, 0x37, 0xca, 0x39, 0xb7, 0x4f, 0x9b, 0xae,
+	0x04, 0x94, 0xf3, 0xf6, 0xee, 0x17, 0xb4, 0xe9, 0xa9, 0xd7, 0x9c, 0x77, 0xd8, 0xa7, 0xea, 0xa5,
+	0xb4, 0x67, 0xef, 0xd9, 0xe2, 0x71, 0x95, 0x3f, 0xe1, 0xe8, 0xd5, 0x7e, 0x67, 0x7f, 0xcf, 0xea,
+	0xad, 0xca, 0x3f, 0x72, 0xd0, 0xb8, 0x03, 0x85, 0x7b, 0xd4, 0xdb, 0xb2, 0x5b, 0xd4, 0xa4, 0x5f,
+	0xee, 0x53, 0xd7, 0x23, 0x37, 0x21, 0xd3, 0x63, 0xaf, 0x3b, 0x56, 0x6b, 0x2e, 0xf5, 0x4a, 0x6a,
+	0x29, 0x5b, 0x83, 0x17, 0xc7, 0x0b, 0x33, 0x1c, 0x51, 0xdf, 0x34, 0x67, 0xf8, 0x54, 0xbd, 0x65,
+	0xbc, 0x07, 0x97, 0x7d, 0x31, 0xb7, 0x6f, 0xf7, 0x5c, 0x4a, 0x56, 0x60, 0x9a, 0x4f, 0x0a, 0xa1,
+	0x5c, 0x75, 0xae, 0x32, 0xbc, 0x80, 0x8a, 0xc0, 0x0b, 0x94, 0x71, 0x3c, 0x05, 0x57, 0xee, 0x5b,
+	0xae, 0x50, 0xe1, 0x2a, 0xd3, 0x77, 0x21, 0xf3, 0xc4, 0xea, 0x78, 0xd4, 0x71, 0x51, 0xcb, 0x8a,
+	0x4e, 0x4b, 0x54, 0xac, 0x72, 0x57, 0xca, 0x98, 0x4a, 0xb8, 0xfc, 0xcd, 0x14, 0x64, 0x70, 0x90,
+	0x94, 0xe0, 0x62, 0xaf, 0xd1, 0xa5, 0x5c, 0xe3, 0xd4, 0x52, 0xd6, 0x94, 0x2f, 0x64, 0x15, 0x72,
+	0x56, 0x6b, 0xa7, 0xef, 0xd0, 0x27, 0xd6, 0x33, 0x36, 0x97, 0xe6, 0x73, 0xb5, 0x02, 0x5b, 0x28,
+	0xd4, 0x37, 0x1f, 0xe2, 0xa8, 0x09, 0x56, 0x4b, 0x3d, 0x93, 0x87, 0x30, 0xd3, 0x69, 0xec, 0xd2,
+	0x8e, 0x3b, 0x37, 0xc5, 0xb0, 0xb9, 0xea, 0xfa, 0x24, 0x9e, 0x55, 0xee, 0x0b, 0xd1, 0x0f, 0x58,
+	0x80, 0x0f, 0x4d, 0xd4, 0x43, 0xea, 0x90, 0xeb, 0xd2, 0xee, 0x2e, 0x9b, 0xfe, 0xdc, 0xea, 0xbb,
+	0x73, 0xd3, 0x4c, 0x6d, 0xa1, 0x7a, 0x3b, 0x6e, 0xdb, 0xb6, 0x59, 0xe8, 0x2b, 0x0f, 0x7c, 0xbc,
+	0x19, 0x96, 0x25, 0x55, 0xb8, 0xc8, 0x98, 0xc3, 0xd6, 0x71, 0x51, 0x28, 0xb9, 0x11, 0xbb, 0xf7,
+	0x0c, 0x64, 0x4a, 0x28, 0x0b, 0x73, 0x9e, 0x6f, 0x45, 0xb0, 0x07, 0x33, 0x62, 0x7f, 0x2e, 0xf1,
+	0x41, 0xb5, 0xea, 0xf2, 0x5b, 0x90, 0x0b, 0xb9, 0x4e, 0xae, 0xc0, 0x54, 0x9b, 0x1e, 0x4a, 0x5a,
+	0x98, 0xfc, 0x91, 0xef, 0xee, 0x41, 0xa3, 0xb3, 0x4f, 0xd9, 0x0e, 0xf2, 0x31, 0xf9, 0xf2, 0x76,
+	0x7a, 0x3d, 0x65, 0x6c, 0x40, 0x31, 0xb4, 0x1d, 0xc8, 0x91, 0x0a, 0x0b, 0x06, 0x1f, 0x10, 0xc1,
+	0x48, 0x22, 0x89, 0x84, 0x19, 0x3f, 0xa6, 0xa0, 0xf8, 0xb8, 0xdf, 0x6a, 0x78, 0x74, 0x52, 0x86,
+	0x92, 0x77, 0xe1, 0x92, 0x00, 0x1d, 0xb0, 0x4d, 0xb2, 0xec, 0x9e, 0x70, 0x30, 0x57, 0xbd, 0xae,
+	0xb3, 0xf8, 0x89, 0x84, 0x98, 0x39, 0x2e, 0x80, 0x2f, 0xe4, 0x75, 0x98, 0xe6, 0xe9, 0xc6, 0xc2,
+	0xcd, 0xe5, 0x6e, 0x24, 0xc5, 0xc5, 0x14, 0x48, 0xa3, 0x06, 0x24, 0xec, 0xeb, 0x89, 0xd2, 0x62,
+	0x1d, 0x8a, 0x26, 0xed, 0xda, 0x07, 0x13, 0xaf, 0xd7, 0x28, 0x01, 0x09, 0x4b, 0x4a, 0xeb, 0x98,
+	0xde, 0x8f, 0x1a, 0x6e, 0x3b, 0xa4, 0xcc, 0x63, 0xaf, 0x11, 0x65, 0x1c, 0xc1, 0x95, 0xf1, 0x29,
+	0x3f, 0xbd, 0xa5, 0x58, 0xb0, 0x0e, 0x3e, 0x99, 0xb4, 0x0e, 0x81, 0x17, 0xa8, 0x60, 0x1d, 0x13,
+	0x9b, 0xf6, 0xd7, 0x11, 0xb6, 0x6e, 0xfc, 0x83, 0xe5, 0x82, 0x0f, 0x9e, 0xa0, 0x5c, 0x84, 0xc5,
+	0x86, 0xcb, 0xc5, 0x0f, 0xe7, 0x58, 0x2e, 0x74, 0x9e, 0x69, 0xcb, 0x05, 0x73, 0xc1, 0xa5, 0xce,
+	0x81, 0xd5, 0xe4, 0x3c, 0x90, 0xe5, 0x02, 0x5d, 0xd8, 0x96, 0xc3, 0xf5, 0x4d, 0xe6, 0x02, 0x42,
+	0xea, 0x2d, 0x97, 0x2c, 0xc2, 0x2c, 0xb2, 0x46, 0xd6, 0x85, 0x6c, 0x2d, 0xc7, 0xd0, 0x19, 0x49,
+	0x1b, 0xb6, 0x7a, 0xc9, 0x1b, 0x97, 0x6c, 0x42, 0x81, 0xa5, 0x9a, 0xe5, 0xd0, 0xd6, 0x8e, 0xeb,
+	0x31, 0xf6, 0xca, 0x4a, 0x50, 0xa8, 0xfe, 0x3f, 0x2e, 0xc4, 0xdb, 0x1c, 0x65, 0xe6, 0x51, 0x48,
+	0xbc, 0x69, 0xca, 0x49, 0xe6, 0x3f, 0x29, 0x27, 0xb8, 0x5d, 0x41, 0x39, 0xe1, 0xac, 0x49, 0x2c,
+	0x27, 0x82, 0x46, 0x12, 0x66, 0x7c, 0x04, 0xa5, 0x0d, 0x87, 0x32, 0x7f, 0x71, 0xcb, 0x14, 0x91,
+	0xd6, 0x30, 0xd7, 0x25, 0x8b, 0x16, 0x74, 0x6a, 0x50, 0x22, 0x94, 0xee, 0x5b, 0x70, 0x2d, 0xa2,
+	0x0c, 0xbd, 0xba, 0x03, 0x19, 0x0c, 0x03, 0x2a, 0xbc, 0x9e, 0xa0, 0xd0, 0x54, 0x58, 0xe3, 0x7d,
+	0x28, 0xb2, 0x9c, 0x8b, 0x78, 0xb6, 0x02, 0x10, 0x44, 0x1d, 0xb3, 0x26, 0xcf, 0xc2, 0x98, 0xf5,
+	0x83, 0x6e, 0x66, 0xfd, 0x98, 0xb3, 0xf5, 0x91, 0xb0, 0x8a, 0xd3, 0xf9, 0xf3, 0x73, 0x0a, 0x4a,
+	0xb2, 0x9e, 0x9d, 0xc6, 0x27, 0x46, 0xaf, 0xcb, 0x0a, 0x3d, 0x41, 0x29, 0x2e, 0xa0, 0x8c, 0xaa,
+	0xc6, 0x6b, 0x03, 0xd5, 0x78, 0xfc, 0x08, 0x45, 0x16, 0x70, 0xba, 0x1d, 0xd9, 0x84, 0x92, 0x2c,
+	0x4d, 0xa7, 0x0a, 0xd2, 0xff, 0xe0, 0x5a, 0x44, 0x0b, 0xd6, 0xb8, 0x3f, 0xd3, 0x70, 0x95, 0x73,
+	0x1c, 0xc7, 0xfd, 0x32, 0x57, 0x8f, 0x96, 0xb9, 0xd5, 0xb8, 0x62, 0x12, 0x91, 0x1c, 0xae, 0x74,
+	0xdf, 0xa6, 0xcf, 0xbc, 0xd2, 0x6d, 0x47, 0x2a, 0xdd, 0x3b, 0x13, 0x3a, 0xa7, 0x2d, 0x76, 0x43,
+	0xd5, 0x64, 0xfa, 0x6c, 0xab, 0xc9, 0xc7, 0x50, 0x1a, 0x74, 0x09, 0x89, 0xf1, 0x26, 0xcc, 0x62,
+	0xa0, 0x54, 0x4d, 0x49, 0x64, 0x86, 0x0f, 0x0e, 0x2a, 0xcb, 0x16, 0xf5, 0x9e, 0xda, 0x4e, 0x7b,
+	0x82, 0xca, 0x82, 0x12, 0xba, 0xca, 0xe2, 0x2b, 0x0b, 0x78, 0xdb, 0x93, 0x43, 0x49, 0xbc, 0x55,
+	0x52, 0x0a, 0x6b, 0x3c, 0x16, 0x95, 0x25, 0xe2, 0x19, 0x61, 0x7d, 0x09, 0xdb, 0x4d, 0xdc, 0x2f,
+	0xf1, 0xcc, 0x89, 0x8c, 0x32, 0x9c, 0xc8, 0xe9, 0x80, 0xc8, 0x28, 0xcb, 0x89, 0x8c, 0x00, 0xbf,
+	0xda, 0x9c, 0x91, 0x8f, 0x9f, 0xa9, 0xdc, 0x3a, 0x73, 0x37, 0xfd, 0x7c, 0x8b, 0x78, 0xea, 0xe7,
+	0x1b, 0x8e, 0x9f, 0x20, 0xdf, 0x22, 0x92, 0x2f, 0x57, 0xbe, 0xc5, 0x38, 0x77, 0x9e, 0xf9, 0x16,
+	0xb8, 0x14, 0xe4, 0x1b, 0x06, 0x2a, 0x31, 0xdf, 0x54, 0xe4, 0x7c, 0x30, 0x7e, 0x2c, 0x37, 0x3a,
+	0xfb, 0x2e, 0x5b, 0x53, 0xa8, 0x0e, 0x37, 0xe5, 0x48, 0xa4, 0x0e, 0x23, 0x8e, 0xf3, 0x02, 0x01,
+	0x3e, 0x7d, 0x7d, 0x15, 0x01, 0x7d, 0x11, 0x92, 0x44, 0x5f, 0x25, 0xa5, 0xb0, 0x3e, 0x97, 0x70,
+	0xe2, 0x04, 0x5c, 0x8a, 0x48, 0xbe, 0x5c, 0x5c, 0x8a, 0x71, 0xee, 0x3c, 0xb9, 0x14, 0xb8, 0x14,
+	0x70, 0x09, 0xa3, 0x91, 0xc8, 0x25, 0x15, 0x3a, 0x1f, 0x6c, 0xec, 0x43, 0xf1, 0x43, 0xdb, 0xea,
+	0x3d, 0xb2, 0xdb, 0xb4, 0x67, 0xda, 0xac, 0x9d, 0xe5, 0x0d, 0x47, 0x05, 0xae, 0x3a, 0xfc, 0x99,
+	0xee, 0x70, 0xc2, 0x31, 0x46, 0x79, 0x7c, 0x5a, 0x78, 0x38, 0x6b, 0x16, 0xe5, 0xd4, 0xa7, 0x62,
+	0x46, 0xc8, 0xb1, 0xe3, 0x62, 0x09, 0xf1, 0xdd, 0x46, 0xaf, 0xb1, 0xe7, 0x0b, 0xa4, 0x85, 0x00,
+	0x91, 0x73, 0x0f, 0xe4, 0x94, 0x90, 0x30, 0xbe, 0x4b, 0xab, 0xfe, 0xea, 0x34, 0x34, 0xe6, 0xfd,
+	0x95, 0x42, 0x4f, 0xd2, 0x5f, 0xa1, 0xcc, 0x04, 0xfd, 0x15, 0x5a, 0x0f, 0xbe, 0x53, 0xe4, 0x1e,
+	0xcc, 0x3a, 0xb8, 0x5f, 0x2c, 0xc8, 0x5c, 0xf0, 0x96, 0x4e, 0x70, 0x68, 0x73, 0x6b, 0xd3, 0x47,
+	0xc7, 0x0b, 0x17, 0x4c, 0x5f, 0x38, 0x68, 0xd4, 0xce, 0x26, 0x1b, 0xab, 0xbf, 0x15, 0x21, 0xb3,
+	0x21, 0xaf, 0xd3, 0x88, 0x05, 0x19, 0xbc, 0xa9, 0x22, 0x86, 0x4e, 0x78, 0xf0, 0xf6, 0xab, 0x7c,
+	0x33, 0x11, 0x83, 0x5f, 0x8e, 0x6b, 0xbf, 0xfc, 0xf4, 0xd7, 0xf7, 0xe9, 0xcb, 0x90, 0x17, 0xa0,
+	0xd7, 0x30, 0xe2, 0xc4, 0x86, 0xac, 0x7f, 0xe5, 0x41, 0x5e, 0x1d, 0xe7, 0x82, 0xa8, 0x7c, 0x6b,
+	0x04, 0x2a, 0xd9, 0xa0, 0x03, 0x10, 0xdc, 0x38, 0x10, 0xad, 0xae, 0xa1, 0xdb, 0x93, 0xf2, 0xe2,
+	0x28, 0xd8, 0x48, 0x9b, 0xc1, 0x3d, 0x83, 0xde, 0xe6, 0xd0, 0x0d, 0x86, 0xde, 0xa6, 0xe6, 0xba,
+	0x22, 0xc6, 0xa6, 0x8c, 0x21, 0x3f, 0xc9, 0xc5, 0xc6, 0x30, 0x74, 0xcf, 0x10, 0x1b, 0xc3, 0x81,
+	0x1b, 0x85, 0xe4, 0x18, 0x8a, 0x73, 0x66, 0x7c, 0x0c, 0xc3, 0xa7, 0xf6, 0xf8, 0x18, 0x0e, 0x1c,
+	0x56, 0x47, 0xee, 0xa7, 0x58, 0x5e, 0xc2, 0x7e, 0x86, 0x57, 0xb8, 0x38, 0x0a, 0x36, 0xd2, 0x66,
+	0x70, 0x4e, 0xd4, 0xdb, 0x1c, 0x3a, 0x8a, 0xea, 0x6d, 0x0e, 0x1f, 0x37, 0xe3, 0x6c, 0x3e, 0x83,
+	0x4b, 0xe1, 0x96, 0x9b, 0xdc, 0x1e, 0xf3, 0x9c, 0x50, 0x5e, 0x1a, 0x0d, 0x4c, 0xb6, 0xfc, 0x15,
+	0xe4, 0x07, 0x0e, 0xea, 0x44, 0xab, 0x51, 0x77, 0x31, 0x50, 0x5e, 0x1e, 0x03, 0x39, 0xd2, 0xf8,
+	0xc0, 0x19, 0x54, 0x6f, 0x5c, 0x77, 0xce, 0xd6, 0x1b, 0xd7, 0x1e, 0x68, 0x13, 0x8c, 0x0f, 0x1c,
+	0x35, 0xf5, 0xc6, 0x75, 0x67, 0x5a, 0xbd, 0x71, 0xfd, 0xb9, 0x35, 0x91, 0x64, 0xd8, 0xba, 0xc5,
+	0x92, 0x6c, 0xb0, 0xdd, 0x8f, 0x25, 0x59, 0xb4, 0x77, 0x4f, 0x26, 0x99, 0xea, 0x33, 0xe3, 0x49,
+	0x16, 0x69, 0x8e, 0xe3, 0x49, 0x16, 0x6d, 0x59, 0x47, 0x92, 0x4c, 0x2d, 0x38, 0x81, 0x64, 0x91,
+	0x35, 0x2f, 0x8f, 0x81, 0x1c, 0x33, 0xce, 0x89, 0xc6, 0x75, 0xe7, 0xab, 0xa4, 0x38, 0x8f, 0x69,
+	0x5c, 0xc6, 0x19, 0xbf, 0xc1, 0xb1, 0x71, 0x1e, 0xec, 0x71, 0x62, 0xe3, 0x1c, 0x69, 0x00, 0x46,
+	0xc4, 0x59, 0xf5, 0x80, 0xf1, 0x71, 0x8e, 0x34, 0xae, 0xf1, 0x71, 0x8e, 0xb6, 0x93, 0x23, 0xf3,
+	0x59, 0x2d, 0x38, 0x21, 0x9f, 0x23, 0x6b, 0x5e, 0x1e, 0x03, 0x99, 0x68, 0xbc, 0x76, 0xe3, 0xe8,
+	0xf9, 0xfc, 0x85, 0xdf, 0xd9, 0xef, 0xef, 0xe7, 0xf3, 0xa9, 0xaf, 0x5f, 0xcc, 0xa7, 0x8e, 0xd8,
+	0xef, 0x57, 0xf6, 0xfb, 0x83, 0xfd, 0x76, 0x67, 0xc4, 0x7f, 0xf4, 0xd6, 0xfe, 0x0d, 0x00, 0x00,
+	0xff, 0xff, 0xf3, 0xcc, 0x22, 0xcd, 0x4a, 0x1c, 0x00, 0x00,
 }

+ 11 - 0
vendor/src/github.com/docker/swarmkit/api/control.proto

@@ -267,6 +267,14 @@ message ListClustersResponse {
 	repeated Cluster clusters = 1;
 }
 
+message JoinTokenRotation {
+	// RotateWorkerToken tells UpdateCluster to rotate the worker secret.
+	bool rotate_worker_token = 1;
+
+	// RotateManagerSecret tells UpdateCluster to rotate the manager secret.
+	bool rotate_manager_token = 2;
+}
+
 message UpdateClusterRequest {
 	// ClusterID is the cluster ID to update.
 	string cluster_id = 1 [(gogoproto.customname) = "ClusterID"];
@@ -276,6 +284,9 @@ message UpdateClusterRequest {
 
 	// Spec is the new spec to apply to the cluster.
 	ClusterSpec spec = 3;
+
+	// Rotation contains flags for join token rotation
+	JoinTokenRotation rotation = 4 [(gogoproto.nullable) = false];
 }
 
 message UpdateClusterResponse {

+ 103 - 113
vendor/src/github.com/docker/swarmkit/api/specs.pb.go

@@ -493,7 +493,9 @@ func (*NetworkSpec) Descriptor() ([]byte, []int) { return fileDescriptorSpecs, [
 // ClusterSpec specifies global cluster settings.
 type ClusterSpec struct {
 	Annotations Annotations `protobuf:"bytes,1,opt,name=annotations" json:"annotations"`
-	// AcceptancePolicy defines the certificate issuance policy.
+	// DEPRECATED: AcceptancePolicy defines the certificate issuance policy.
+	// Acceptance policy is no longer customizable, and secrets have been
+	// replaced with join tokens.
 	AcceptancePolicy AcceptancePolicy `protobuf:"bytes,2,opt,name=acceptance_policy,json=acceptancePolicy" json:"acceptance_policy"`
 	// Orchestration defines cluster-level orchestration settings.
 	Orchestration OrchestrationConfig `protobuf:"bytes,3,opt,name=orchestration" json:"orchestration"`
@@ -503,12 +505,8 @@ type ClusterSpec struct {
 	Dispatcher DispatcherConfig `protobuf:"bytes,5,opt,name=dispatcher" json:"dispatcher"`
 	// CAConfig defines cluster-level certificate authority settings.
 	CAConfig CAConfig `protobuf:"bytes,6,opt,name=ca_config,json=caConfig" json:"ca_config"`
-	// DefaultLogDriver specifies the log driver to use for the cluster if not
-	// specified for each task.
-	//
-	// If this is changed, only new tasks will pick up the new log driver.
-	// Existing tasks will continue to use the previous default until rescheduled.
-	DefaultLogDriver *Driver `protobuf:"bytes,7,opt,name=default_log_driver,json=defaultLogDriver" json:"default_log_driver,omitempty"`
+	// TaskDefaults specifies the default values to use for task creation.
+	TaskDefaults TaskDefaults `protobuf:"bytes,7,opt,name=task_defaults,json=taskDefaults" json:"task_defaults"`
 }
 
 func (m *ClusterSpec) Reset()                    { *m = ClusterSpec{} }
@@ -759,7 +757,7 @@ func (m *ClusterSpec) Copy() *ClusterSpec {
 		Raft:             *m.Raft.Copy(),
 		Dispatcher:       *m.Dispatcher.Copy(),
 		CAConfig:         *m.CAConfig.Copy(),
-		DefaultLogDriver: m.DefaultLogDriver.Copy(),
+		TaskDefaults:     *m.TaskDefaults.Copy(),
 	}
 
 	return o
@@ -969,9 +967,7 @@ func (this *ClusterSpec) GoString() string {
 	s = append(s, "Raft: "+strings.Replace(this.Raft.GoString(), `&`, ``, 1)+",\n")
 	s = append(s, "Dispatcher: "+strings.Replace(this.Dispatcher.GoString(), `&`, ``, 1)+",\n")
 	s = append(s, "CAConfig: "+strings.Replace(this.CAConfig.GoString(), `&`, ``, 1)+",\n")
-	if this.DefaultLogDriver != nil {
-		s = append(s, "DefaultLogDriver: "+fmt.Sprintf("%#v", this.DefaultLogDriver)+",\n")
-	}
+	s = append(s, "TaskDefaults: "+strings.Replace(this.TaskDefaults.GoString(), `&`, ``, 1)+",\n")
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
@@ -1621,16 +1617,14 @@ func (m *ClusterSpec) MarshalTo(data []byte) (int, error) {
 		return 0, err
 	}
 	i += n25
-	if m.DefaultLogDriver != nil {
-		data[i] = 0x3a
-		i++
-		i = encodeVarintSpecs(data, i, uint64(m.DefaultLogDriver.Size()))
-		n26, err := m.DefaultLogDriver.MarshalTo(data[i:])
-		if err != nil {
-			return 0, err
-		}
-		i += n26
+	data[i] = 0x3a
+	i++
+	i = encodeVarintSpecs(data, i, uint64(m.TaskDefaults.Size()))
+	n26, err := m.TaskDefaults.MarshalTo(data[i:])
+	if err != nil {
+		return 0, err
 	}
+	i += n26
 	return i, nil
 }
 
@@ -1909,10 +1903,8 @@ func (m *ClusterSpec) Size() (n int) {
 	n += 1 + l + sovSpecs(uint64(l))
 	l = m.CAConfig.Size()
 	n += 1 + l + sovSpecs(uint64(l))
-	if m.DefaultLogDriver != nil {
-		l = m.DefaultLogDriver.Size()
-		n += 1 + l + sovSpecs(uint64(l))
-	}
+	l = m.TaskDefaults.Size()
+	n += 1 + l + sovSpecs(uint64(l))
 	return n
 }
 
@@ -2106,7 +2098,7 @@ func (this *ClusterSpec) String() string {
 		`Raft:` + strings.Replace(strings.Replace(this.Raft.String(), "RaftConfig", "RaftConfig", 1), `&`, ``, 1) + `,`,
 		`Dispatcher:` + strings.Replace(strings.Replace(this.Dispatcher.String(), "DispatcherConfig", "DispatcherConfig", 1), `&`, ``, 1) + `,`,
 		`CAConfig:` + strings.Replace(strings.Replace(this.CAConfig.String(), "CAConfig", "CAConfig", 1), `&`, ``, 1) + `,`,
-		`DefaultLogDriver:` + strings.Replace(fmt.Sprintf("%v", this.DefaultLogDriver), "Driver", "Driver", 1) + `,`,
+		`TaskDefaults:` + strings.Replace(strings.Replace(this.TaskDefaults.String(), "TaskDefaults", "TaskDefaults", 1), `&`, ``, 1) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -3976,7 +3968,7 @@ func (m *ClusterSpec) Unmarshal(data []byte) error {
 			iNdEx = postIndex
 		case 7:
 			if wireType != 2 {
-				return fmt.Errorf("proto: wrong wireType = %d for field DefaultLogDriver", wireType)
+				return fmt.Errorf("proto: wrong wireType = %d for field TaskDefaults", wireType)
 			}
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
@@ -4000,10 +3992,7 @@ func (m *ClusterSpec) Unmarshal(data []byte) error {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 			}
-			if m.DefaultLogDriver == nil {
-				m.DefaultLogDriver = &Driver{}
-			}
-			if err := m.DefaultLogDriver.Unmarshal(data[iNdEx:postIndex]); err != nil {
+			if err := m.TaskDefaults.Unmarshal(data[iNdEx:postIndex]); err != nil {
 				return err
 			}
 			iNdEx = postIndex
@@ -4134,88 +4123,89 @@ var (
 )
 
 var fileDescriptorSpecs = []byte{
-	// 1320 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0xcd, 0x72, 0x1b, 0x45,
-	0x17, 0xf5, 0xcf, 0x58, 0x96, 0xee, 0xd8, 0x89, 0xd2, 0x95, 0x2f, 0x51, 0x94, 0x7c, 0xb6, 0x23,
-	0x02, 0x04, 0xaa, 0x90, 0x41, 0x50, 0xf9, 0xe1, 0xa7, 0x40, 0x96, 0x84, 0x63, 0x12, 0x3b, 0x53,
-	0xed, 0x24, 0x2c, 0x55, 0xed, 0x99, 0x8e, 0x3c, 0xe5, 0xd1, 0xcc, 0xd0, 0xd3, 0xa3, 0x94, 0x77,
-	0x2c, 0x53, 0x2c, 0xd8, 0xc1, 0x8e, 0x05, 0xc5, 0x3b, 0xf0, 0x0c, 0x59, 0xb2, 0xa1, 0x8a, 0x55,
-	0x8a, 0xe4, 0x09, 0xa8, 0xe2, 0x05, 0xb8, 0xdd, 0xd3, 0x92, 0x46, 0x64, 0x9c, 0xb0, 0xc8, 0x62,
-	0xaa, 0xba, 0x7b, 0xce, 0x39, 0xdd, 0x73, 0xef, 0xe9, 0x7b, 0x25, 0xb0, 0x93, 0x98, 0xbb, 0x49,
-	0x33, 0x16, 0x91, 0x8c, 0x08, 0xf1, 0x22, 0xf7, 0x88, 0x8b, 0x66, 0xf2, 0x88, 0x89, 0xe1, 0x91,
-	0x2f, 0x9b, 0xa3, 0x0f, 0xea, 0xb6, 0x3c, 0x8e, 0xb9, 0x01, 0xd4, 0xcf, 0x0e, 0xa2, 0x41, 0xa4,
-	0x87, 0x9b, 0x6a, 0x64, 0x56, 0xcf, 0x7b, 0xa9, 0x60, 0xd2, 0x8f, 0xc2, 0xcd, 0xf1, 0x20, 0x7b,
-	0xd1, 0xf8, 0xde, 0x82, 0xf2, 0x5e, 0xe4, 0xf1, 0x7d, 0xdc, 0x83, 0x6c, 0x83, 0xcd, 0xc2, 0x30,
-	0x92, 0x1a, 0x90, 0xd4, 0xe6, 0x37, 0xe6, 0xaf, 0xda, 0xad, 0xf5, 0xe6, 0x8b, 0x5b, 0x36, 0xdb,
-	0x53, 0xd8, 0x96, 0xf5, 0xe4, 0xe9, 0xfa, 0x1c, 0xcd, 0x33, 0xc9, 0xfb, 0x60, 0x89, 0x28, 0xe0,
-	0xb5, 0x05, 0x54, 0x38, 0xd5, 0xba, 0x54, 0xa4, 0xa0, 0x36, 0xa5, 0x88, 0xa1, 0x1a, 0x89, 0x5b,
-	0xc3, 0x90, 0x0f, 0x0f, 0xb8, 0x48, 0x0e, 0xfd, 0xb8, 0xb6, 0xa8, 0x79, 0x6f, 0x9f, 0xc4, 0x53,
-	0x87, 0x6d, 0xee, 0x4e, 0xe0, 0x34, 0x47, 0x25, 0xbb, 0xb0, 0xc2, 0x46, 0xcc, 0x0f, 0xd8, 0x81,
-	0x1f, 0xf8, 0xf2, 0xb8, 0x66, 0x69, 0xa9, 0x77, 0x5e, 0x2a, 0xd5, 0xce, 0x11, 0xe8, 0x0c, 0xbd,
-	0xe1, 0x01, 0x4c, 0x37, 0x22, 0x6f, 0xc1, 0xb2, 0xd3, 0xdb, 0xeb, 0xee, 0xec, 0x6d, 0x57, 0xe7,
-	0xea, 0x17, 0xbe, 0xfb, 0x69, 0xe3, 0x7f, 0x4a, 0x63, 0x0a, 0x70, 0x78, 0xe8, 0xf9, 0xe1, 0x80,
-	0x5c, 0x85, 0x72, 0xbb, 0xd3, 0xe9, 0x39, 0xf7, 0x7a, 0xdd, 0xea, 0x7c, 0xbd, 0x8e, 0xc0, 0x73,
-	0xb3, 0xc0, 0xb6, 0xeb, 0xf2, 0x58, 0x72, 0xaf, 0x6e, 0x3d, 0xfe, 0x65, 0x6d, 0xae, 0xf1, 0x78,
-	0x1e, 0x56, 0xf2, 0x87, 0xc0, 0x8d, 0x4a, 0xed, 0xce, 0xbd, 0x9d, 0x07, 0x3d, 0xdc, 0x67, 0x42,
-	0xcf, 0x23, 0xda, 0xae, 0xf4, 0x47, 0x9c, 0x5c, 0x81, 0x25, 0xa7, 0x7d, 0x7f, 0xbf, 0x87, 0xbb,
-	0x4c, 0x8e, 0x93, 0x87, 0x39, 0x2c, 0x4d, 0x34, 0xaa, 0x4b, 0xdb, 0x3b, 0x7b, 0xd5, 0x85, 0x62,
-	0x54, 0x57, 0x30, 0x3f, 0x34, 0x47, 0xf9, 0xd5, 0x02, 0x7b, 0x9f, 0x8b, 0x91, 0xef, 0xbe, 0x66,
-	0x4f, 0x5c, 0x03, 0x4b, 0xb2, 0xe4, 0x48, 0x7b, 0xc2, 0x2e, 0xf6, 0xc4, 0x3d, 0x7c, 0xaf, 0x36,
-	0x35, 0x74, 0x8d, 0x57, 0xce, 0x10, 0x3c, 0x0e, 0x7c, 0x97, 0x61, 0xbc, 0xb4, 0x33, 0xec, 0xd6,
-	0x9b, 0x45, 0x6c, 0x3a, 0x41, 0x99, 0xf3, 0xdf, 0x9a, 0xa3, 0x39, 0x2a, 0xf9, 0x04, 0x4a, 0x83,
-	0x20, 0x3a, 0x60, 0x81, 0xf6, 0x84, 0xdd, 0xba, 0x5c, 0x24, 0xb2, 0xad, 0x11, 0x53, 0x01, 0x43,
-	0x21, 0x37, 0xa0, 0x94, 0xc6, 0x1e, 0xea, 0xd4, 0x4a, 0x9a, 0xbc, 0x51, 0x44, 0xbe, 0xaf, 0x11,
-	0x9d, 0x28, 0x7c, 0xe8, 0x0f, 0xa8, 0xc1, 0x93, 0x7d, 0x28, 0x87, 0x5c, 0x3e, 0x8a, 0xc4, 0x51,
-	0x52, 0x5b, 0xde, 0x58, 0x44, 0xee, 0xf5, 0x22, 0x6e, 0x2e, 0xe6, 0xcd, 0xbd, 0x0c, 0xdf, 0x96,
-	0x92, 0xb9, 0x87, 0x43, 0x1e, 0x4a, 0x23, 0x39, 0x11, 0x22, 0x9f, 0x42, 0x19, 0xad, 0x16, 0x47,
-	0x7e, 0x28, 0x6b, 0xe5, 0x93, 0x0f, 0xd4, 0x33, 0x18, 0xa5, 0x4a, 0x27, 0x8c, 0xfa, 0x6d, 0x38,
-	0x7f, 0xc2, 0x16, 0xe4, 0x1c, 0x94, 0x24, 0x13, 0x03, 0x2e, 0x75, 0xa6, 0x2b, 0xd4, 0xcc, 0x48,
-	0x0d, 0x96, 0x59, 0xe0, 0xb3, 0x84, 0x27, 0x98, 0xc0, 0x45, 0x7c, 0x31, 0x9e, 0x6e, 0x95, 0xc0,
-	0x1a, 0xa2, 0x9f, 0x1a, 0x9b, 0x70, 0xe6, 0x85, 0x0c, 0x90, 0x3a, 0x94, 0x4d, 0x06, 0x32, 0xeb,
-	0x58, 0x74, 0x32, 0x6f, 0x9c, 0x86, 0xd5, 0x99, 0x68, 0x37, 0x7e, 0x5f, 0x80, 0xf2, 0xd8, 0x02,
-	0xa4, 0x0d, 0x15, 0x37, 0x0a, 0x25, 0x1a, 0x93, 0x0b, 0xe3, 0xba, 0xc2, 0x84, 0x75, 0xc6, 0x20,
-	0xc5, 0xc2, 0x84, 0x4d, 0x59, 0xe4, 0x4b, 0xa8, 0x08, 0x9e, 0x44, 0xa9, 0x70, 0xf5, 0xa9, 0x95,
-	0xc4, 0xd5, 0x62, 0xe3, 0x64, 0x20, 0xca, 0xbf, 0x49, 0x7d, 0xc1, 0x55, 0x34, 0x12, 0x3a, 0xa5,
-	0xa2, 0x71, 0x96, 0x71, 0x82, 0x81, 0x90, 0x2f, 0x73, 0x0e, 0xcd, 0x20, 0x4e, 0x84, 0x5f, 0x77,
-	0x4c, 0xc7, 0x0c, 0x24, 0x57, 0xe2, 0x80, 0xb9, 0x5a, 0xb5, 0xb6, 0xa4, 0xe9, 0xff, 0x2f, 0xa2,
-	0x3b, 0x63, 0x10, 0x9d, 0xe2, 0xc9, 0x4d, 0x80, 0x20, 0x1a, 0xf4, 0x3d, 0x81, 0x77, 0x5d, 0x18,
-	0xe7, 0xd5, 0x8b, 0xd8, 0x5d, 0x8d, 0xa0, 0x15, 0x44, 0x67, 0xc3, 0xad, 0x0a, 0x1e, 0x3a, 0x0d,
-	0xa5, 0x3f, 0xe4, 0x8d, 0x1f, 0x2d, 0x58, 0x9d, 0x09, 0x13, 0x39, 0x0b, 0x4b, 0xfe, 0x90, 0x0d,
-	0xb8, 0x49, 0x72, 0x36, 0x21, 0x3d, 0x28, 0x61, 0x45, 0xe0, 0x41, 0x96, 0x62, 0xbb, 0xf5, 0xde,
-	0x2b, 0xe3, 0xdd, 0xbc, 0xa3, 0xf1, 0xbd, 0x50, 0x8a, 0x63, 0x6a, 0xc8, 0xca, 0x2a, 0x6e, 0x34,
-	0x1c, 0xb2, 0x50, 0xdd, 0x56, 0x6d, 0x15, 0x33, 0x25, 0x04, 0x2c, 0x74, 0x53, 0x82, 0x51, 0x54,
-	0xcb, 0x7a, 0x4c, 0xaa, 0xb0, 0xc8, 0xc3, 0x11, 0x46, 0x46, 0x2d, 0xa9, 0xa1, 0x5a, 0xf1, 0xfc,
-	0xec, 0x6b, 0x71, 0x05, 0x87, 0x8a, 0x87, 0x65, 0x4c, 0xe0, 0xf5, 0x51, 0x4b, 0x7a, 0x4c, 0xae,
-	0x43, 0x69, 0x18, 0xe1, 0x07, 0x26, 0xe8, 0x7f, 0x75, 0xd8, 0x0b, 0x45, 0x87, 0xdd, 0x55, 0x08,
+	// 1332 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x57, 0x4f, 0x6f, 0x1b, 0x45,
+	0x14, 0x8f, 0x93, 0x8d, 0xe3, 0xbc, 0x75, 0xda, 0x74, 0x54, 0x5a, 0xd7, 0x2d, 0x49, 0x6a, 0x0a,
+	0x14, 0x24, 0x1c, 0x30, 0xa8, 0x7f, 0xf8, 0x23, 0x70, 0x6c, 0x93, 0x86, 0x92, 0x74, 0x35, 0x69,
+	0x2b, 0x71, 0xb2, 0x26, 0xbb, 0x53, 0x67, 0x95, 0xf5, 0xee, 0x32, 0x3b, 0xeb, 0x2a, 0x37, 0x8e,
+	0x15, 0x07, 0x6e, 0x70, 0xe3, 0x84, 0xc4, 0x47, 0xe0, 0x33, 0xf4, 0xc8, 0x05, 0x89, 0x53, 0x45,
+	0xfb, 0x09, 0x90, 0xf8, 0x02, 0xbc, 0x99, 0x1d, 0xdb, 0x6b, 0xba, 0x69, 0x39, 0xf4, 0x60, 0x69,
+	0xe6, 0xcd, 0xef, 0xf7, 0x66, 0xe6, 0xbd, 0xdf, 0xbc, 0xb7, 0x06, 0x3b, 0x89, 0xb9, 0x9b, 0x34,
+	0x63, 0x11, 0xc9, 0x88, 0x10, 0x2f, 0x72, 0x8f, 0xb8, 0x68, 0x26, 0x0f, 0x99, 0x18, 0x1e, 0xf9,
+	0xb2, 0x39, 0xfa, 0xa0, 0x6e, 0xcb, 0xe3, 0x98, 0x1b, 0x40, 0xfd, 0xec, 0x20, 0x1a, 0x44, 0x7a,
+	0xb8, 0xa9, 0x46, 0xc6, 0x7a, 0xde, 0x4b, 0x05, 0x93, 0x7e, 0x14, 0x6e, 0x8e, 0x07, 0xd9, 0x42,
+	0xe3, 0x07, 0x0b, 0x2a, 0x7b, 0x91, 0xc7, 0xf7, 0x71, 0x0f, 0xb2, 0x0d, 0x36, 0x0b, 0xc3, 0x48,
+	0x6a, 0x40, 0x52, 0x2b, 0x6d, 0x94, 0xae, 0xda, 0xad, 0xf5, 0xe6, 0xf3, 0x5b, 0x36, 0xdb, 0x53,
+	0xd8, 0x96, 0xf5, 0xf8, 0xc9, 0xfa, 0x1c, 0xcd, 0x33, 0xc9, 0xfb, 0x60, 0x89, 0x28, 0xe0, 0xb5,
+	0x79, 0xf4, 0x70, 0xaa, 0x75, 0xa9, 0xc8, 0x83, 0xda, 0x94, 0x22, 0x86, 0x6a, 0x24, 0x6e, 0x0d,
+	0x43, 0x3e, 0x3c, 0xe0, 0x22, 0x39, 0xf4, 0xe3, 0xda, 0x82, 0xe6, 0xbd, 0x7d, 0x12, 0x4f, 0x1d,
+	0xb6, 0xb9, 0x3b, 0x81, 0xd3, 0x1c, 0x95, 0xec, 0x42, 0x95, 0x8d, 0x98, 0x1f, 0xb0, 0x03, 0x3f,
+	0xf0, 0xe5, 0x71, 0xcd, 0xd2, 0xae, 0xde, 0x79, 0xa1, 0xab, 0x76, 0x8e, 0x40, 0x67, 0xe8, 0x0d,
+	0x0f, 0x60, 0xba, 0x11, 0x79, 0x0b, 0x96, 0x9c, 0xde, 0x5e, 0x77, 0x67, 0x6f, 0x7b, 0x75, 0xae,
+	0x7e, 0xe1, 0xfb, 0x9f, 0x37, 0x5e, 0x53, 0x3e, 0xa6, 0x00, 0x87, 0x87, 0x9e, 0x1f, 0x0e, 0xc8,
+	0x55, 0xa8, 0xb4, 0x3b, 0x9d, 0x9e, 0x73, 0xb7, 0xd7, 0x5d, 0x2d, 0xd5, 0xeb, 0x08, 0x3c, 0x37,
+	0x0b, 0x6c, 0xbb, 0x2e, 0x8f, 0x25, 0xf7, 0xea, 0xd6, 0xa3, 0x5f, 0xd6, 0xe6, 0x1a, 0x8f, 0x4a,
+	0x50, 0xcd, 0x1f, 0x02, 0x37, 0x2a, 0xb7, 0x3b, 0x77, 0x77, 0xee, 0xf7, 0x70, 0x9f, 0x09, 0x3d,
+	0x8f, 0x68, 0xbb, 0xd2, 0x1f, 0x71, 0x72, 0x05, 0x16, 0x9d, 0xf6, 0xbd, 0xfd, 0x1e, 0xee, 0x32,
+	0x39, 0x4e, 0x1e, 0xe6, 0xb0, 0x34, 0xd1, 0xa8, 0x2e, 0x6d, 0xef, 0xec, 0xad, 0xce, 0x17, 0xa3,
+	0xba, 0x82, 0xf9, 0xa1, 0x39, 0xca, 0x6f, 0x16, 0xd8, 0xfb, 0x5c, 0x8c, 0x7c, 0xf7, 0x15, 0x6b,
+	0xe2, 0x1a, 0x58, 0x92, 0x25, 0x47, 0x5a, 0x13, 0x76, 0xb1, 0x26, 0xee, 0xe2, 0xba, 0xda, 0xd4,
+	0xd0, 0x35, 0x5e, 0x29, 0x43, 0xf0, 0x38, 0xf0, 0x5d, 0x86, 0xf1, 0xd2, 0xca, 0xb0, 0x5b, 0x6f,
+	0x16, 0xb1, 0xe9, 0x04, 0x65, 0xce, 0x7f, 0x6b, 0x8e, 0xe6, 0xa8, 0xe4, 0x13, 0x28, 0x0f, 0x82,
+	0xe8, 0x80, 0x05, 0x5a, 0x13, 0x76, 0xeb, 0x72, 0x91, 0x93, 0x6d, 0x8d, 0x98, 0x3a, 0x30, 0x14,
+	0x72, 0x03, 0xca, 0x69, 0xec, 0xa1, 0x9f, 0x5a, 0x59, 0x93, 0x37, 0x8a, 0xc8, 0xf7, 0x34, 0xa2,
+	0x13, 0x85, 0x0f, 0xfc, 0x01, 0x35, 0x78, 0xb2, 0x0f, 0x95, 0x90, 0xcb, 0x87, 0x91, 0x38, 0x4a,
+	0x6a, 0x4b, 0x1b, 0x0b, 0xc8, 0xbd, 0x5e, 0xc4, 0xcd, 0xc5, 0xbc, 0xb9, 0x97, 0xe1, 0xdb, 0x52,
+	0x32, 0xf7, 0x70, 0xc8, 0x43, 0x69, 0x5c, 0x4e, 0x1c, 0x91, 0x4f, 0xa1, 0x82, 0x52, 0x8b, 0x23,
+	0x3f, 0x94, 0xb5, 0xca, 0xc9, 0x07, 0xea, 0x19, 0x8c, 0xf2, 0x4a, 0x27, 0x8c, 0xfa, 0x6d, 0x38,
+	0x7f, 0xc2, 0x16, 0xe4, 0x1c, 0x94, 0x25, 0x13, 0x03, 0x2e, 0x75, 0xa6, 0x97, 0xa9, 0x99, 0x91,
+	0x1a, 0x2c, 0xb1, 0xc0, 0x67, 0x09, 0x4f, 0x30, 0x81, 0x0b, 0xb8, 0x30, 0x9e, 0x6e, 0x95, 0xc1,
+	0x1a, 0xa2, 0x9e, 0x1a, 0x9b, 0x70, 0xe6, 0xb9, 0x0c, 0x90, 0x3a, 0x54, 0x4c, 0x06, 0x32, 0xe9,
+	0x58, 0x74, 0x32, 0x6f, 0x9c, 0x86, 0x95, 0x99, 0x68, 0x37, 0xfe, 0x98, 0x87, 0xca, 0x58, 0x02,
+	0xa4, 0x0d, 0xcb, 0x6e, 0x14, 0x4a, 0x14, 0x26, 0x17, 0x46, 0x75, 0x85, 0x09, 0xeb, 0x8c, 0x41,
+	0x8a, 0x85, 0x09, 0x9b, 0xb2, 0xc8, 0x97, 0xb0, 0x2c, 0x78, 0x12, 0xa5, 0xc2, 0xd5, 0xa7, 0x56,
+	0x2e, 0xae, 0x16, 0x0b, 0x27, 0x03, 0x51, 0xfe, 0x6d, 0xea, 0x0b, 0xae, 0xa2, 0x91, 0xd0, 0x29,
+	0x15, 0x85, 0xb3, 0x84, 0x13, 0x0c, 0x84, 0x7c, 0x91, 0x72, 0x68, 0x06, 0x71, 0x22, 0xbc, 0xdd,
+	0x31, 0x1d, 0x33, 0x90, 0xbc, 0x1c, 0x07, 0xcc, 0xd5, 0x5e, 0x6b, 0x8b, 0x9a, 0xfe, 0x7a, 0x11,
+	0xdd, 0x19, 0x83, 0xe8, 0x14, 0x4f, 0x6e, 0x02, 0x04, 0xd1, 0xa0, 0xef, 0x09, 0x7c, 0xeb, 0xc2,
+	0x28, 0xaf, 0x5e, 0xc4, 0xee, 0x6a, 0x04, 0x5d, 0x46, 0x74, 0x36, 0xdc, 0x5a, 0xc6, 0x43, 0xa7,
+	0xa1, 0xf4, 0x87, 0xbc, 0xf1, 0x93, 0x05, 0x2b, 0x33, 0x61, 0x22, 0x67, 0x61, 0xd1, 0x1f, 0xb2,
+	0x01, 0x37, 0x49, 0xce, 0x26, 0xa4, 0x07, 0x65, 0xac, 0x08, 0x3c, 0xc8, 0x52, 0x6c, 0xb7, 0xde,
+	0x7b, 0x69, 0xbc, 0x9b, 0x5f, 0x6b, 0x7c, 0x2f, 0x94, 0xe2, 0x98, 0x1a, 0xb2, 0x92, 0x8a, 0x1b,
+	0x0d, 0x87, 0x2c, 0x54, 0xaf, 0x55, 0x4b, 0xc5, 0x4c, 0x09, 0x01, 0x0b, 0xd5, 0x94, 0x60, 0x14,
+	0x95, 0x59, 0x8f, 0xc9, 0x2a, 0x2c, 0xf0, 0x70, 0x84, 0x91, 0x51, 0x26, 0x35, 0x54, 0x16, 0xcf,
+	0xcf, 0x6e, 0x8b, 0x16, 0x1c, 0x2a, 0x1e, 0x96, 0x31, 0x81, 0xcf, 0x47, 0x99, 0xf4, 0x98, 0x5c,
+	0x87, 0xf2, 0x30, 0xc2, 0x0b, 0x26, 0xa8, 0x7f, 0x75, 0xd8, 0x0b, 0x45, 0x87, 0xdd, 0x55, 0x08,
 	0x53, 0x4d, 0x0c, 0x9c, 0xdc, 0x82, 0x33, 0x89, 0x8c, 0xe2, 0xfe, 0x40, 0x60, 0x94, 0xfb, 0x31,
-	0x17, 0x7e, 0xe4, 0xd5, 0x2a, 0x27, 0x17, 0xa5, 0xae, 0x69, 0x98, 0xf4, 0xb4, 0xa2, 0x6d, 0x2b,
-	0x96, 0xa3, 0x49, 0xc4, 0x81, 0x95, 0x38, 0x0d, 0x82, 0x7e, 0x14, 0x67, 0xb5, 0x11, 0xb4, 0xc8,
-	0x7f, 0x88, 0x9a, 0x83, 0xac, 0xbb, 0x19, 0x89, 0xda, 0xf1, 0x74, 0x52, 0xbf, 0x09, 0x76, 0x2e,
-	0xa2, 0x2a, 0x12, 0x47, 0xfc, 0xd8, 0x24, 0x49, 0x0d, 0x55, 0xe2, 0x46, 0x2c, 0x48, 0xb3, 0xce,
-	0x8a, 0x89, 0xd3, 0x93, 0x8f, 0x17, 0x6e, 0xcc, 0xd7, 0x5b, 0x60, 0xe7, 0x64, 0xc9, 0x1b, 0xb0,
-	0x2a, 0xf8, 0xc0, 0x4f, 0x50, 0xa6, 0xcf, 0x52, 0x79, 0x58, 0xfb, 0x42, 0x13, 0x56, 0xc6, 0x8b,
-	0x6d, 0x5c, 0x6b, 0xfc, 0x8d, 0x6d, 0x27, 0x5f, 0x22, 0x48, 0x27, 0xbb, 0xcb, 0x7a, 0xc7, 0x53,
-	0xad, 0xcd, 0x57, 0x95, 0x14, 0x7d, 0x73, 0x82, 0x54, 0xed, 0xb8, 0xab, 0xda, 0xb9, 0x26, 0x93,
-	0x8f, 0x60, 0x29, 0x8e, 0x84, 0x1c, 0xbb, 0x68, 0xad, 0xd0, 0xed, 0x08, 0x30, 0x45, 0x2d, 0x03,
-	0x37, 0x0e, 0xe1, 0xd4, 0xac, 0x1a, 0x76, 0xad, 0xc5, 0x07, 0x3b, 0x0e, 0x36, 0xc0, 0x8b, 0xd8,
-	0xb3, 0xce, 0xcf, 0xbe, 0x7c, 0xe0, 0x0b, 0x99, 0xb2, 0x60, 0xc7, 0x21, 0xef, 0x62, 0x6f, 0xdb,
-	0xdb, 0xa7, 0x14, 0x3b, 0xe0, 0x3a, 0xe2, 0x2e, 0xce, 0xe2, 0xd4, 0x2b, 0x4c, 0xbb, 0x47, 0xa3,
-	0x83, 0x49, 0x87, 0xfb, 0x61, 0x01, 0x6c, 0x53, 0xfe, 0x5e, 0x6f, 0x87, 0xfb, 0x1c, 0x56, 0xb3,
-	0x9b, 0xda, 0x77, 0xf5, 0xa7, 0x99, 0x9a, 0xf3, 0xb2, 0x0b, 0xbb, 0x92, 0x11, 0x4c, 0xf1, 0xbd,
-	0x0c, 0x2b, 0x7e, 0x3c, 0xba, 0xd6, 0xe7, 0x21, 0x3b, 0x08, 0x4c, 0xb3, 0x2b, 0x53, 0x5b, 0xad,
-	0xf5, 0xb2, 0x25, 0x55, 0x50, 0x31, 0xf8, 0x5c, 0x84, 0xa6, 0x8d, 0x95, 0xe9, 0x64, 0x4e, 0x3e,
-	0x03, 0xcb, 0x8f, 0xd9, 0xd0, 0x54, 0x99, 0xc2, 0x2f, 0xd8, 0x71, 0xda, 0xbb, 0xc6, 0x22, 0x5b,
-	0xe5, 0xe7, 0x4f, 0xd7, 0x2d, 0xb5, 0x40, 0x35, 0xad, 0xf1, 0x33, 0x76, 0xfe, 0x4e, 0x90, 0x26,
-	0xd2, 0x14, 0x89, 0xd7, 0x16, 0x97, 0xaf, 0xe1, 0x0c, 0xd3, 0xbf, 0x77, 0x58, 0xa8, 0x6e, 0x9c,
-	0x2e, 0x90, 0x26, 0x36, 0x57, 0x0a, 0xe5, 0x26, 0xe0, 0xac, 0x98, 0x1a, 0xcd, 0x2a, 0xfb, 0xd7,
-	0x3a, 0xb6, 0xd6, 0xd5, 0x48, 0xb8, 0x87, 0x58, 0x69, 0xb3, 0x2b, 0x6a, 0x7e, 0x1d, 0x14, 0xfe,
-	0x6e, 0xbc, 0x9b, 0x07, 0x66, 0xf1, 0x36, 0xba, 0xb3, 0x1a, 0xd8, 0xe9, 0x2d, 0xc1, 0x1e, 0x8e,
-	0x4b, 0x7d, 0xa1, 0x7b, 0x29, 0xbe, 0x9f, 0x91, 0xd0, 0x0c, 0xf2, 0x15, 0x80, 0xe7, 0x27, 0x31,
-	0x93, 0x28, 0x27, 0x4c, 0x16, 0x0a, 0x3f, 0xb0, 0x3b, 0x41, 0xcd, 0xa8, 0xe4, 0xd8, 0xe4, 0x36,
-	0xb6, 0x3f, 0x36, 0xf6, 0x51, 0xe9, 0xe4, 0xea, 0xd4, 0x69, 0x1b, 0x89, 0xaa, 0x92, 0xc0, 0x8c,
-	0x96, 0xc7, 0x2b, 0xb4, 0xec, 0x32, 0xe3, 0xab, 0x5b, 0x40, 0x3c, 0xfe, 0x90, 0xa5, 0x81, 0xec,
-	0xe7, 0xda, 0xc9, 0xf2, 0x2b, 0xdd, 0x59, 0x35, 0xac, 0x3b, 0x93, 0xae, 0x72, 0xe9, 0xc9, 0xb3,
-	0xb5, 0xb9, 0x3f, 0xf0, 0xf9, 0xeb, 0xd9, 0xda, 0xfc, 0xb7, 0xcf, 0xd7, 0xe6, 0x9f, 0xe0, 0xf3,
-	0x1b, 0x3e, 0x7f, 0xe2, 0x73, 0x50, 0xd2, 0xff, 0x29, 0x3e, 0xfc, 0x27, 0x00, 0x00, 0xff, 0xff,
-	0xde, 0xdd, 0x4d, 0x58, 0xb2, 0x0c, 0x00, 0x00,
+	0x17, 0x7e, 0xe4, 0xd5, 0x96, 0x4f, 0x2e, 0x4a, 0x5d, 0xd3, 0x30, 0xe9, 0x69, 0x45, 0xdb, 0x56,
+	0x2c, 0x47, 0x93, 0x88, 0x03, 0xd5, 0x38, 0x0d, 0x82, 0x7e, 0x14, 0x67, 0xb5, 0x11, 0xb4, 0x93,
+	0xff, 0x11, 0x35, 0x07, 0x59, 0x77, 0x32, 0x12, 0xb5, 0xe3, 0xe9, 0xa4, 0x7e, 0x13, 0xec, 0x5c,
+	0x44, 0x55, 0x24, 0x8e, 0xf8, 0xb1, 0x49, 0x92, 0x1a, 0xaa, 0xc4, 0x8d, 0x58, 0x90, 0x66, 0x9d,
+	0x15, 0x13, 0xa7, 0x27, 0x1f, 0xcf, 0xdf, 0x28, 0xd5, 0x5b, 0x60, 0xe7, 0xdc, 0x92, 0x37, 0x60,
+	0x45, 0xf0, 0x81, 0x9f, 0xa0, 0x9b, 0x3e, 0x4b, 0xe5, 0x61, 0xed, 0x0b, 0x4d, 0xa8, 0x8e, 0x8d,
+	0x6d, 0xb4, 0x35, 0xfe, 0xc1, 0xb6, 0x93, 0x2f, 0x11, 0xa4, 0x93, 0xbd, 0x65, 0xbd, 0xe3, 0xa9,
+	0xd6, 0xe6, 0xcb, 0x4a, 0x8a, 0x7e, 0x39, 0x41, 0xaa, 0x76, 0xdc, 0x55, 0xed, 0x5c, 0x93, 0xc9,
+	0x47, 0xb0, 0x18, 0x47, 0x42, 0x8e, 0x55, 0xb4, 0x56, 0xa8, 0x76, 0x04, 0x98, 0xa2, 0x96, 0x81,
+	0x1b, 0x87, 0x70, 0x6a, 0xd6, 0x1b, 0x76, 0xad, 0x85, 0xfb, 0x3b, 0x0e, 0x36, 0xc0, 0x8b, 0xd8,
+	0xb3, 0xce, 0xcf, 0x2e, 0xde, 0xf7, 0x85, 0x4c, 0x59, 0xb0, 0xe3, 0x90, 0x77, 0xb1, 0xb7, 0xed,
+	0xed, 0x53, 0x8a, 0x1d, 0x70, 0x1d, 0x71, 0x17, 0x67, 0x71, 0x6a, 0x09, 0xd3, 0xee, 0xd1, 0xe8,
+	0x60, 0xd2, 0xe1, 0x7e, 0x9c, 0x07, 0xdb, 0x94, 0xbf, 0x57, 0xdb, 0xe1, 0x3e, 0x87, 0x95, 0xec,
+	0xa5, 0xf6, 0x5d, 0x7d, 0x35, 0x53, 0x73, 0x5e, 0xf4, 0x60, 0xab, 0x19, 0xc1, 0x14, 0xdf, 0xcb,
+	0x50, 0xf5, 0xe3, 0xd1, 0xb5, 0x3e, 0x0f, 0xd9, 0x41, 0x60, 0x9a, 0x5d, 0x85, 0xda, 0xca, 0xd6,
+	0xcb, 0x4c, 0xaa, 0xa0, 0x62, 0xf0, 0xb9, 0x08, 0x4d, 0x1b, 0xab, 0xd0, 0xc9, 0x9c, 0x7c, 0x06,
+	0x96, 0x1f, 0xb3, 0xa1, 0xa9, 0x32, 0x85, 0x37, 0xd8, 0x71, 0xda, 0xbb, 0x46, 0x22, 0x5b, 0x95,
+	0x67, 0x4f, 0xd6, 0x2d, 0x65, 0xa0, 0x9a, 0xd6, 0xf8, 0x15, 0x3b, 0x7f, 0x27, 0x48, 0x13, 0x69,
+	0x8a, 0xc4, 0x2b, 0x8b, 0xcb, 0x37, 0x70, 0x86, 0xe9, 0xef, 0x1d, 0x16, 0xaa, 0x17, 0xa7, 0x0b,
+	0xa4, 0x89, 0xcd, 0x95, 0x42, 0x77, 0x13, 0x70, 0x56, 0x4c, 0xb7, 0xca, 0xca, 0x67, 0xad, 0x44,
+	0x57, 0xd9, 0x7f, 0x56, 0xb0, 0xb9, 0xae, 0x44, 0xc2, 0x3d, 0xc4, 0x5a, 0x9b, 0x3d, 0x52, 0xf3,
+	0x7d, 0x50, 0xf8, 0xe5, 0x78, 0x27, 0x0f, 0xcc, 0x22, 0x6e, 0x4e, 0x3b, 0xeb, 0x03, 0x7b, 0xbd,
+	0x25, 0xd8, 0x83, 0x71, 0xb1, 0x2f, 0xd4, 0x2f, 0xc5, 0xf5, 0x19, 0x17, 0x9a, 0x41, 0xbe, 0x02,
+	0xf0, 0xfc, 0x24, 0x66, 0x12, 0xdd, 0x09, 0x93, 0x87, 0xc2, 0x2b, 0x76, 0x27, 0xa8, 0x19, 0x2f,
+	0x39, 0x36, 0xb9, 0x8d, 0x0d, 0x90, 0x8d, 0x95, 0x54, 0x3e, 0xb9, 0x3e, 0x75, 0xda, 0xc6, 0xc5,
+	0xaa, 0x72, 0x81, 0x39, 0xad, 0x8c, 0x2d, 0xb4, 0xe2, 0x32, 0xa3, 0xac, 0xdb, 0xb0, 0xa2, 0x3e,
+	0xa6, 0xfa, 0x1e, 0x7f, 0xc0, 0xd2, 0x40, 0x26, 0xba, 0x94, 0x9e, 0xf0, 0xd1, 0xa0, 0x5a, 0x70,
+	0xd7, 0xe0, 0xcc, 0xb9, 0xaa, 0x32, 0x6f, 0xbb, 0xf4, 0xf8, 0xe9, 0xda, 0xdc, 0x9f, 0xf8, 0xfb,
+	0xfb, 0xe9, 0x5a, 0xe9, 0xbb, 0x67, 0x6b, 0xa5, 0xc7, 0xf8, 0xfb, 0x1d, 0x7f, 0x7f, 0xe1, 0xef,
+	0xa0, 0xac, 0xff, 0x58, 0x7c, 0xf8, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcc, 0x10, 0x79, 0x5b,
+	0xb7, 0x0c, 0x00, 0x00,
 }

+ 6 - 8
vendor/src/github.com/docker/swarmkit/api/specs.proto

@@ -233,8 +233,10 @@ message NetworkSpec {
 message ClusterSpec {
 	Annotations annotations = 1 [(gogoproto.nullable) = false];
 
-	// AcceptancePolicy defines the certificate issuance policy.
-	AcceptancePolicy acceptance_policy = 2 [(gogoproto.nullable) = false];
+	// DEPRECATED: AcceptancePolicy defines the certificate issuance policy.
+	// Acceptance policy is no longer customizable, and secrets have been
+	// replaced with join tokens.
+	AcceptancePolicy acceptance_policy = 2 [deprecated=true, (gogoproto.nullable) = false];
 
 	// Orchestration defines cluster-level orchestration settings.
 	OrchestrationConfig orchestration = 3 [(gogoproto.nullable) = false];
@@ -248,10 +250,6 @@ message ClusterSpec {
 	// CAConfig defines cluster-level certificate authority settings.
 	CAConfig ca_config = 6 [(gogoproto.nullable) = false, (gogoproto.customname) = "CAConfig"];
 
-	// DefaultLogDriver specifies the log driver to use for the cluster if not
-	// specified for each task.
-	//
-	// If this is changed, only new tasks will pick up the new log driver.
-	// Existing tasks will continue to use the previous default until rescheduled.
-	Driver default_log_driver = 7;
+	// TaskDefaults specifies the default values to use for task creation.
+	TaskDefaults task_defaults = 7 [(gogoproto.nullable) = false];
 }

+ 632 - 209
vendor/src/github.com/docker/swarmkit/api/types.pb.go

@@ -44,9 +44,11 @@
 		ExternalCA
 		CAConfig
 		OrchestrationConfig
+		TaskDefaults
 		DispatcherConfig
 		RaftConfig
 		Placement
+		JoinTokens
 		RootCA
 		Certificate
 		EncryptionKey
@@ -104,6 +106,7 @@
 		GetClusterResponse
 		ListClustersRequest
 		ListClustersResponse
+		JoinTokenRotation
 		UpdateClusterRequest
 		UpdateClusterResponse
 		SessionRequest
@@ -509,7 +512,7 @@ func (x EncryptionKey_Algorithm) String() string {
 	return proto.EnumName(EncryptionKey_Algorithm_name, int32(x))
 }
 func (EncryptionKey_Algorithm) EnumDescriptor() ([]byte, []int) {
-	return fileDescriptorTypes, []int{32, 0}
+	return fileDescriptorTypes, []int{34, 0}
 }
 
 // Version tracks the last time an object in the store was updated.
@@ -1048,6 +1051,20 @@ func (m *OrchestrationConfig) Reset()                    { *m = OrchestrationCon
 func (*OrchestrationConfig) ProtoMessage()               {}
 func (*OrchestrationConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} }
 
+// TaskDefaults specifies default values for task creation.
+type TaskDefaults struct {
+	// LogDriver specifies the log driver to use for the cluster if not
+	// specified for each task.
+	//
+	// If this is changed, only new tasks will pick up the new log driver.
+	// Existing tasks will continue to use the previous default until rescheduled.
+	LogDriver *Driver `protobuf:"bytes,1,opt,name=log_driver,json=logDriver" json:"log_driver,omitempty"`
+}
+
+func (m *TaskDefaults) Reset()                    { *m = TaskDefaults{} }
+func (*TaskDefaults) ProtoMessage()               {}
+func (*TaskDefaults) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} }
+
 // DispatcherConfig defines cluster-level dispatcher settings.
 type DispatcherConfig struct {
 	// HeartbeatPeriod defines how often agent should send heartbeats to
@@ -1057,7 +1074,7 @@ type DispatcherConfig struct {
 
 func (m *DispatcherConfig) Reset()                    { *m = DispatcherConfig{} }
 func (*DispatcherConfig) ProtoMessage()               {}
-func (*DispatcherConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{27} }
+func (*DispatcherConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} }
 
 // RaftConfig defines raft settings for the cluster.
 type RaftConfig struct {
@@ -1079,7 +1096,7 @@ type RaftConfig struct {
 
 func (m *RaftConfig) Reset()                    { *m = RaftConfig{} }
 func (*RaftConfig) ProtoMessage()               {}
-func (*RaftConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{28} }
+func (*RaftConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} }
 
 // Placement specifies task distribution constraints.
 type Placement struct {
@@ -1089,7 +1106,19 @@ type Placement struct {
 
 func (m *Placement) Reset()                    { *m = Placement{} }
 func (*Placement) ProtoMessage()               {}
-func (*Placement) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{29} }
+func (*Placement) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
+
+// JoinToken contains the join tokens for workers and managers.
+type JoinTokens struct {
+	// Worker is the join token workers may use to join the swarm.
+	Worker string `protobuf:"bytes,1,opt,name=worker,proto3" json:"worker,omitempty"`
+	// Manager is the join token workers may use to join the swarm.
+	Manager string `protobuf:"bytes,2,opt,name=manager,proto3" json:"manager,omitempty"`
+}
+
+func (m *JoinTokens) Reset()                    { *m = JoinTokens{} }
+func (*JoinTokens) ProtoMessage()               {}
+func (*JoinTokens) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} }
 
 type RootCA struct {
 	// CAKey is the root CA private key.
@@ -1098,11 +1127,13 @@ type RootCA struct {
 	CACert []byte `protobuf:"bytes,2,opt,name=ca_cert,json=caCert,proto3" json:"ca_cert,omitempty"`
 	// CACertHash is the digest of the CA Certificate.
 	CACertHash string `protobuf:"bytes,3,opt,name=ca_cert_hash,json=caCertHash,proto3" json:"ca_cert_hash,omitempty"`
+	// JoinTokens contains the join tokens for workers and managers.
+	JoinTokens JoinTokens `protobuf:"bytes,4,opt,name=join_tokens,json=joinTokens" json:"join_tokens"`
 }
 
 func (m *RootCA) Reset()                    { *m = RootCA{} }
 func (*RootCA) ProtoMessage()               {}
-func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
+func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
 
 type Certificate struct {
 	Role        NodeRole       `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
@@ -1115,7 +1146,7 @@ type Certificate struct {
 
 func (m *Certificate) Reset()                    { *m = Certificate{} }
 func (*Certificate) ProtoMessage()               {}
-func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{31} }
+func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
 
 // Symmetric keys to encrypt inter-agent communication.
 type EncryptionKey struct {
@@ -1131,7 +1162,7 @@ type EncryptionKey struct {
 
 func (m *EncryptionKey) Reset()                    { *m = EncryptionKey{} }
 func (*EncryptionKey) ProtoMessage()               {}
-func (*EncryptionKey) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
+func (*EncryptionKey) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{34} }
 
 // ManagerStatus provides informations about the state of a manager in the cluster.
 type ManagerStatus struct {
@@ -1148,7 +1179,7 @@ type ManagerStatus struct {
 
 func (m *ManagerStatus) Reset()                    { *m = ManagerStatus{} }
 func (*ManagerStatus) ProtoMessage()               {}
-func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
+func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{35} }
 
 func init() {
 	proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
@@ -1183,9 +1214,11 @@ func init() {
 	proto.RegisterType((*ExternalCA)(nil), "docker.swarmkit.v1.ExternalCA")
 	proto.RegisterType((*CAConfig)(nil), "docker.swarmkit.v1.CAConfig")
 	proto.RegisterType((*OrchestrationConfig)(nil), "docker.swarmkit.v1.OrchestrationConfig")
+	proto.RegisterType((*TaskDefaults)(nil), "docker.swarmkit.v1.TaskDefaults")
 	proto.RegisterType((*DispatcherConfig)(nil), "docker.swarmkit.v1.DispatcherConfig")
 	proto.RegisterType((*RaftConfig)(nil), "docker.swarmkit.v1.RaftConfig")
 	proto.RegisterType((*Placement)(nil), "docker.swarmkit.v1.Placement")
+	proto.RegisterType((*JoinTokens)(nil), "docker.swarmkit.v1.JoinTokens")
 	proto.RegisterType((*RootCA)(nil), "docker.swarmkit.v1.RootCA")
 	proto.RegisterType((*Certificate)(nil), "docker.swarmkit.v1.Certificate")
 	proto.RegisterType((*EncryptionKey)(nil), "docker.swarmkit.v1.EncryptionKey")
@@ -1705,6 +1738,18 @@ func (m *OrchestrationConfig) Copy() *OrchestrationConfig {
 	return o
 }
 
+func (m *TaskDefaults) Copy() *TaskDefaults {
+	if m == nil {
+		return nil
+	}
+
+	o := &TaskDefaults{
+		LogDriver: m.LogDriver.Copy(),
+	}
+
+	return o
+}
+
 func (m *DispatcherConfig) Copy() *DispatcherConfig {
 	if m == nil {
 		return nil
@@ -1750,6 +1795,19 @@ func (m *Placement) Copy() *Placement {
 	return o
 }
 
+func (m *JoinTokens) Copy() *JoinTokens {
+	if m == nil {
+		return nil
+	}
+
+	o := &JoinTokens{
+		Worker:  m.Worker,
+		Manager: m.Manager,
+	}
+
+	return o
+}
+
 func (m *RootCA) Copy() *RootCA {
 	if m == nil {
 		return nil
@@ -1759,6 +1817,7 @@ func (m *RootCA) Copy() *RootCA {
 		CAKey:      m.CAKey,
 		CACert:     m.CACert,
 		CACertHash: m.CACertHash,
+		JoinTokens: *m.JoinTokens.Copy(),
 	}
 
 	return o
@@ -2302,6 +2361,18 @@ func (this *OrchestrationConfig) GoString() string {
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
+func (this *TaskDefaults) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 5)
+	s = append(s, "&api.TaskDefaults{")
+	if this.LogDriver != nil {
+		s = append(s, "LogDriver: "+fmt.Sprintf("%#v", this.LogDriver)+",\n")
+	}
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
 func (this *DispatcherConfig) GoString() string {
 	if this == nil {
 		return "nil"
@@ -2338,15 +2409,27 @@ func (this *Placement) GoString() string {
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
+func (this *JoinTokens) GoString() string {
+	if this == nil {
+		return "nil"
+	}
+	s := make([]string, 0, 6)
+	s = append(s, "&api.JoinTokens{")
+	s = append(s, "Worker: "+fmt.Sprintf("%#v", this.Worker)+",\n")
+	s = append(s, "Manager: "+fmt.Sprintf("%#v", this.Manager)+",\n")
+	s = append(s, "}")
+	return strings.Join(s, "")
+}
 func (this *RootCA) GoString() string {
 	if this == nil {
 		return "nil"
 	}
-	s := make([]string, 0, 7)
+	s := make([]string, 0, 8)
 	s = append(s, "&api.RootCA{")
 	s = append(s, "CAKey: "+fmt.Sprintf("%#v", this.CAKey)+",\n")
 	s = append(s, "CACert: "+fmt.Sprintf("%#v", this.CACert)+",\n")
 	s = append(s, "CACertHash: "+fmt.Sprintf("%#v", this.CACertHash)+",\n")
+	s = append(s, "JoinTokens: "+strings.Replace(this.JoinTokens.GoString(), `&`, ``, 1)+",\n")
 	s = append(s, "}")
 	return strings.Join(s, "")
 }
@@ -3646,6 +3729,34 @@ func (m *OrchestrationConfig) MarshalTo(data []byte) (int, error) {
 	return i, nil
 }
 
+func (m *TaskDefaults) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *TaskDefaults) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if m.LogDriver != nil {
+		data[i] = 0xa
+		i++
+		i = encodeVarintTypes(data, i, uint64(m.LogDriver.Size()))
+		n20, err := m.LogDriver.MarshalTo(data[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n20
+	}
+	return i, nil
+}
+
 func (m *DispatcherConfig) Marshal() (data []byte, err error) {
 	size := m.Size()
 	data = make([]byte, size)
@@ -3665,11 +3776,11 @@ func (m *DispatcherConfig) MarshalTo(data []byte) (int, error) {
 		data[i] = 0xa
 		i++
 		i = encodeVarintTypes(data, i, uint64(m.HeartbeatPeriod.Size()))
-		n20, err := m.HeartbeatPeriod.MarshalTo(data[i:])
+		n21, err := m.HeartbeatPeriod.MarshalTo(data[i:])
 		if err != nil {
 			return 0, err
 		}
-		i += n20
+		i += n21
 	}
 	return i, nil
 }
@@ -3750,6 +3861,36 @@ func (m *Placement) MarshalTo(data []byte) (int, error) {
 	return i, nil
 }
 
+func (m *JoinTokens) Marshal() (data []byte, err error) {
+	size := m.Size()
+	data = make([]byte, size)
+	n, err := m.MarshalTo(data)
+	if err != nil {
+		return nil, err
+	}
+	return data[:n], nil
+}
+
+func (m *JoinTokens) MarshalTo(data []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Worker) > 0 {
+		data[i] = 0xa
+		i++
+		i = encodeVarintTypes(data, i, uint64(len(m.Worker)))
+		i += copy(data[i:], m.Worker)
+	}
+	if len(m.Manager) > 0 {
+		data[i] = 0x12
+		i++
+		i = encodeVarintTypes(data, i, uint64(len(m.Manager)))
+		i += copy(data[i:], m.Manager)
+	}
+	return i, nil
+}
+
 func (m *RootCA) Marshal() (data []byte, err error) {
 	size := m.Size()
 	data = make([]byte, size)
@@ -3783,6 +3924,14 @@ func (m *RootCA) MarshalTo(data []byte) (int, error) {
 		i = encodeVarintTypes(data, i, uint64(len(m.CACertHash)))
 		i += copy(data[i:], m.CACertHash)
 	}
+	data[i] = 0x22
+	i++
+	i = encodeVarintTypes(data, i, uint64(m.JoinTokens.Size()))
+	n22, err := m.JoinTokens.MarshalTo(data[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n22
 	return i, nil
 }
 
@@ -3815,11 +3964,11 @@ func (m *Certificate) MarshalTo(data []byte) (int, error) {
 	data[i] = 0x1a
 	i++
 	i = encodeVarintTypes(data, i, uint64(m.Status.Size()))
-	n21, err := m.Status.MarshalTo(data[i:])
+	n23, err := m.Status.MarshalTo(data[i:])
 	if err != nil {
 		return 0, err
 	}
-	i += n21
+	i += n23
 	if len(m.Certificate) > 0 {
 		data[i] = 0x22
 		i++
@@ -4477,6 +4626,16 @@ func (m *OrchestrationConfig) Size() (n int) {
 	return n
 }
 
+func (m *TaskDefaults) Size() (n int) {
+	var l int
+	_ = l
+	if m.LogDriver != nil {
+		l = m.LogDriver.Size()
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+
 func (m *DispatcherConfig) Size() (n int) {
 	var l int
 	_ = l
@@ -4520,6 +4679,20 @@ func (m *Placement) Size() (n int) {
 	return n
 }
 
+func (m *JoinTokens) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Worker)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	l = len(m.Manager)
+	if l > 0 {
+		n += 1 + l + sovTypes(uint64(l))
+	}
+	return n
+}
+
 func (m *RootCA) Size() (n int) {
 	var l int
 	_ = l
@@ -4535,6 +4708,8 @@ func (m *RootCA) Size() (n int) {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 	}
+	l = m.JoinTokens.Size()
+	n += 1 + l + sovTypes(uint64(l))
 	return n
 }
 
@@ -5053,6 +5228,16 @@ func (this *OrchestrationConfig) String() string {
 	}, "")
 	return s
 }
+func (this *TaskDefaults) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&TaskDefaults{`,
+		`LogDriver:` + strings.Replace(fmt.Sprintf("%v", this.LogDriver), "Driver", "Driver", 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *DispatcherConfig) String() string {
 	if this == nil {
 		return "nil"
@@ -5087,6 +5272,17 @@ func (this *Placement) String() string {
 	}, "")
 	return s
 }
+func (this *JoinTokens) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&JoinTokens{`,
+		`Worker:` + fmt.Sprintf("%v", this.Worker) + `,`,
+		`Manager:` + fmt.Sprintf("%v", this.Manager) + `,`,
+		`}`,
+	}, "")
+	return s
+}
 func (this *RootCA) String() string {
 	if this == nil {
 		return "nil"
@@ -5095,6 +5291,7 @@ func (this *RootCA) String() string {
 		`CAKey:` + fmt.Sprintf("%v", this.CAKey) + `,`,
 		`CACert:` + fmt.Sprintf("%v", this.CACert) + `,`,
 		`CACertHash:` + fmt.Sprintf("%v", this.CACertHash) + `,`,
+		`JoinTokens:` + strings.Replace(strings.Replace(this.JoinTokens.String(), "JoinTokens", "JoinTokens", 1), `&`, ``, 1) + `,`,
 		`}`,
 	}, "")
 	return s
@@ -9419,6 +9616,89 @@ func (m *OrchestrationConfig) Unmarshal(data []byte) error {
 	}
 	return nil
 }
+func (m *TaskDefaults) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: TaskDefaults: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: TaskDefaults: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LogDriver", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.LogDriver == nil {
+				m.LogDriver = &Driver{}
+			}
+			if err := m.LogDriver.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *DispatcherConfig) Unmarshal(data []byte) error {
 	l := len(data)
 	iNdEx := 0
@@ -9726,6 +10006,114 @@ func (m *Placement) Unmarshal(data []byte) error {
 	}
 	return nil
 }
+func (m *JoinTokens) Unmarshal(data []byte) error {
+	l := len(data)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowTypes
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := data[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: JoinTokens: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: JoinTokens: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Worker", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Worker = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Manager", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Manager = string(data[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipTypes(data[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthTypes
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
 func (m *RootCA) Unmarshal(data []byte) error {
 	l := len(data)
 	iNdEx := 0
@@ -9846,6 +10234,36 @@ func (m *RootCA) Unmarshal(data []byte) error {
 			}
 			m.CACertHash = string(data[iNdEx:postIndex])
 			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field JoinTokens", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowTypes
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := data[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthTypes
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.JoinTokens.Unmarshal(data[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
 		default:
 			iNdEx = preIndex
 			skippy, err := skipTypes(data[iNdEx:])
@@ -10448,201 +10866,206 @@ var (
 )
 
 var fileDescriptorTypes = []byte{
-	// 3132 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x58, 0xcb, 0x6f, 0x1b, 0xd7,
-	0xd5, 0x37, 0x9f, 0x22, 0x0f, 0x29, 0x89, 0x1e, 0x3b, 0x8e, 0xcc, 0x28, 0xb2, 0xbf, 0x49, 0x9c,
-	0x38, 0x8f, 0x8f, 0x89, 0x95, 0x7c, 0x1f, 0xdc, 0x04, 0xad, 0x33, 0x7c, 0xc8, 0x62, 0x2d, 0x91,
-	0xc4, 0x25, 0x25, 0x23, 0x28, 0x50, 0x62, 0x34, 0xbc, 0x12, 0x27, 0x1a, 0xce, 0xb0, 0x33, 0x43,
-	0xc9, 0x6c, 0x51, 0xc0, 0xe9, 0xa6, 0x45, 0x56, 0xdd, 0x17, 0x41, 0x50, 0xb4, 0xe8, 0xae, 0xeb,
+	// 3210 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xac, 0x59, 0xcb, 0x6f, 0x1b, 0xd7,
+	0xd5, 0x17, 0x9f, 0x22, 0x0f, 0x29, 0x89, 0x1e, 0x3b, 0x8e, 0xcc, 0x28, 0xb2, 0xbe, 0x49, 0x9c,
+	0x38, 0x8f, 0x8f, 0x89, 0x95, 0x7c, 0x1f, 0x9c, 0x04, 0x8d, 0x33, 0x7c, 0xc8, 0x62, 0x2c, 0x91,
+	0xc4, 0x25, 0x25, 0x23, 0x28, 0x50, 0x62, 0x34, 0xbc, 0x12, 0xc7, 0x1a, 0xce, 0xb0, 0x33, 0x43,
+	0xc9, 0x6c, 0x51, 0xc0, 0xed, 0xa6, 0x45, 0x56, 0xdd, 0x17, 0x41, 0x50, 0xb4, 0xe8, 0xae, 0xeb,
 	0x02, 0x5d, 0x79, 0xe9, 0x65, 0x8a, 0x02, 0x45, 0xd0, 0x02, 0x41, 0x93, 0xfe, 0x03, 0x01, 0xba,
-	0xc8, 0xa2, 0x5d, 0xf4, 0xdc, 0xc7, 0x0c, 0x87, 0xf4, 0x58, 0x71, 0x9a, 0x2c, 0x08, 0xce, 0x3d,
-	0xe7, 0x77, 0xce, 0xbd, 0xf7, 0xdc, 0x73, 0xcf, 0xe3, 0x42, 0xc1, 0x9f, 0x8e, 0xa9, 0x57, 0x19,
-	0xbb, 0x8e, 0xef, 0x28, 0xca, 0xc0, 0x31, 0x8e, 0xa9, 0x5b, 0xf1, 0x4e, 0x75, 0x77, 0x74, 0x6c,
-	0xfa, 0x95, 0x93, 0x1b, 0xe5, 0xcb, 0xbe, 0x39, 0xa2, 0x9e, 0xaf, 0x8f, 0xc6, 0xaf, 0x85, 0x5f,
-	0x02, 0x5e, 0x7e, 0x7a, 0x30, 0x71, 0x75, 0xdf, 0x74, 0xec, 0xd7, 0x82, 0x0f, 0xc9, 0xb8, 0x78,
-	0xe4, 0x1c, 0x39, 0xfc, 0xf3, 0x35, 0xf6, 0x25, 0xa8, 0xea, 0x15, 0x58, 0xda, 0xa7, 0xae, 0x87,
-	0x30, 0xe5, 0x22, 0x64, 0x4c, 0x7b, 0x40, 0xef, 0xad, 0x25, 0xae, 0x26, 0xae, 0xa7, 0x89, 0x18,
-	0xa8, 0xbf, 0x4e, 0x40, 0x41, 0xb3, 0x6d, 0xc7, 0xe7, 0xba, 0x3c, 0x45, 0x81, 0xb4, 0xad, 0x8f,
-	0x28, 0x07, 0xe5, 0x09, 0xff, 0x56, 0x6a, 0x90, 0xb5, 0xf4, 0x03, 0x6a, 0x79, 0x6b, 0xc9, 0xab,
-	0xa9, 0xeb, 0x85, 0xcd, 0x57, 0x2a, 0x8f, 0xae, 0xb9, 0x12, 0x51, 0x52, 0xd9, 0xe1, 0xe8, 0x86,
-	0xed, 0xbb, 0x53, 0x22, 0x45, 0xcb, 0xdf, 0x81, 0x42, 0x84, 0xac, 0x94, 0x20, 0x75, 0x4c, 0xa7,
-	0x72, 0x1a, 0xf6, 0xc9, 0xd6, 0x77, 0xa2, 0x5b, 0x13, 0x8a, 0x93, 0x30, 0x9a, 0x18, 0xbc, 0x95,
-	0xbc, 0x99, 0x50, 0xdf, 0x85, 0x3c, 0xa1, 0x9e, 0x33, 0x71, 0x0d, 0xea, 0x29, 0x2f, 0x41, 0xde,
-	0xd6, 0x6d, 0xa7, 0x6f, 0x8c, 0x27, 0x1e, 0x17, 0x4f, 0x55, 0x8b, 0x9f, 0x7f, 0x7a, 0x25, 0xd7,
-	0x42, 0x62, 0xad, 0xb3, 0xe7, 0x91, 0x1c, 0x63, 0xd7, 0x90, 0xab, 0xfc, 0x0f, 0x14, 0x47, 0x74,
-	0xe4, 0xb8, 0xd3, 0xfe, 0xc1, 0xd4, 0xa7, 0x1e, 0x57, 0x9c, 0x22, 0x05, 0x41, 0xab, 0x32, 0x92,
-	0xfa, 0xcb, 0x04, 0x5c, 0x0c, 0x74, 0x13, 0xfa, 0xa3, 0x89, 0xe9, 0xd2, 0x11, 0xb5, 0x7d, 0x4f,
-	0xf9, 0x3f, 0xdc, 0xb3, 0x39, 0x32, 0x7d, 0x31, 0x47, 0x61, 0xf3, 0xd9, 0xb8, 0x3d, 0x87, 0xab,
-	0x22, 0x12, 0xac, 0x68, 0x50, 0x74, 0xa9, 0x47, 0xdd, 0x13, 0x61, 0x09, 0x3e, 0xe5, 0x57, 0x0a,
-	0xcf, 0x89, 0xa8, 0x5b, 0x90, 0xeb, 0x58, 0xba, 0x7f, 0xe8, 0xb8, 0x23, 0x45, 0x85, 0xa2, 0xee,
-	0x1a, 0x43, 0xd3, 0xa7, 0x86, 0x3f, 0x71, 0x83, 0x53, 0x99, 0xa3, 0x29, 0x97, 0x20, 0xe9, 0x88,
-	0x89, 0xf2, 0xd5, 0x2c, 0x5a, 0x22, 0xd9, 0xee, 0x12, 0xa4, 0xa8, 0x6f, 0xc3, 0xf9, 0x8e, 0x35,
-	0x39, 0x32, 0xed, 0x3a, 0xf5, 0x0c, 0xd7, 0x1c, 0x33, 0xed, 0xec, 0x78, 0x99, 0xf3, 0x05, 0xc7,
-	0xcb, 0xbe, 0xc3, 0x23, 0x4f, 0xce, 0x8e, 0x5c, 0xfd, 0x79, 0x12, 0xce, 0x37, 0x6c, 0x14, 0xa6,
-	0x51, 0xe9, 0x6b, 0xb0, 0x42, 0x39, 0xb1, 0x7f, 0x22, 0x9c, 0x4a, 0xea, 0x59, 0x16, 0xd4, 0xc0,
-	0xd3, 0x9a, 0x0b, 0xfe, 0x72, 0x23, 0x6e, 0xfb, 0x8f, 0x68, 0x8f, 0xf3, 0x1a, 0xa5, 0x01, 0x4b,
-	0x63, 0xbe, 0x09, 0x6f, 0x2d, 0xc5, 0x75, 0x5d, 0x8b, 0xd3, 0xf5, 0xc8, 0x3e, 0xab, 0xe9, 0x87,
-	0x9f, 0x5e, 0x39, 0x47, 0x02, 0xd9, 0x6f, 0xe2, 0x7c, 0xff, 0x48, 0xc0, 0x6a, 0xcb, 0x19, 0xcc,
-	0xd9, 0xa1, 0x0c, 0xb9, 0xa1, 0xe3, 0xf9, 0x91, 0x8b, 0x12, 0x8e, 0x95, 0x9b, 0x90, 0x1b, 0xcb,
-	0xe3, 0x93, 0xa7, 0xbf, 0x1e, 0xbf, 0x64, 0x81, 0x21, 0x21, 0x5a, 0x79, 0x1b, 0xf2, 0x6e, 0xe0,
-	0x13, 0xb8, 0xdb, 0x27, 0x70, 0x9c, 0x19, 0x5e, 0xf9, 0x2e, 0x64, 0xc5, 0x21, 0xac, 0xa5, 0xb9,
-	0xe4, 0xb5, 0x27, 0xb2, 0x39, 0x91, 0x42, 0xea, 0x27, 0x09, 0x28, 0x11, 0xfd, 0xd0, 0xdf, 0xa5,
-	0xa3, 0x03, 0xea, 0x76, 0xf1, 0x22, 0xe3, 0xfd, 0xb9, 0x84, 0xe7, 0x48, 0xf5, 0x01, 0x75, 0xf9,
-	0x26, 0x73, 0x44, 0x8e, 0x94, 0x3d, 0xe6, 0xe4, 0xba, 0x31, 0xd4, 0x0f, 0x4c, 0xcb, 0xf4, 0xa7,
-	0x7c, 0x9b, 0x2b, 0xf1, 0xa7, 0xbc, 0xa8, 0x13, 0x17, 0x3f, 0x13, 0x24, 0x73, 0x6a, 0x94, 0x35,
-	0x58, 0xc2, 0x58, 0xe7, 0xe9, 0x47, 0x94, 0xef, 0x3e, 0x4f, 0x82, 0x21, 0xba, 0x72, 0x31, 0x2a,
-	0xa7, 0x14, 0x60, 0x69, 0xaf, 0x75, 0xa7, 0xd5, 0xbe, 0xdb, 0x2a, 0x9d, 0x53, 0x56, 0xa1, 0xb0,
-	0xd7, 0x22, 0x0d, 0xad, 0xb6, 0xad, 0x55, 0x77, 0x1a, 0xa5, 0x84, 0xb2, 0x8c, 0xe1, 0x22, 0x1c,
-	0x26, 0xd5, 0x8f, 0x12, 0x00, 0xec, 0x00, 0xe5, 0xa6, 0xde, 0x82, 0x0c, 0xc6, 0x53, 0x5f, 0x1c,
-	0xdc, 0xca, 0xe6, 0xf3, 0x71, 0xab, 0x9e, 0xc1, 0x2b, 0xec, 0x8f, 0x12, 0x21, 0x12, 0x5d, 0x61,
-	0x72, 0x71, 0x85, 0x19, 0x8e, 0x9c, 0x5f, 0x5a, 0x0e, 0xd2, 0x75, 0xf6, 0x95, 0x50, 0xf2, 0x90,
-	0xc1, 0x35, 0xd5, 0xdf, 0x2d, 0x25, 0xd1, 0xf9, 0x8a, 0xf5, 0x66, 0xb7, 0xd6, 0x6e, 0xb5, 0x1a,
-	0xb5, 0x5e, 0xa3, 0x5e, 0x4a, 0xa9, 0xd7, 0x20, 0xd3, 0x1c, 0xa1, 0x16, 0x65, 0x9d, 0x79, 0xc0,
-	0x21, 0x75, 0xa9, 0x6d, 0x04, 0x8e, 0x35, 0x23, 0xa8, 0x1f, 0xa3, 0x92, 0x5d, 0x67, 0x62, 0xfb,
-	0xca, 0x66, 0xe4, 0x16, 0xaf, 0x6c, 0x6e, 0xc4, 0x6d, 0x81, 0x03, 0x2b, 0x3d, 0x44, 0xc9, 0x5b,
-	0x8e, 0x87, 0x29, 0x7c, 0x45, 0x2e, 0x5d, 0x8e, 0x18, 0xdd, 0xd7, 0xdd, 0x23, 0xea, 0x4b, 0xa3,
-	0xcb, 0x91, 0x72, 0x1d, 0x72, 0x78, 0x3a, 0x03, 0xc7, 0xb6, 0xa6, 0xdc, 0xa5, 0x72, 0x22, 0xcc,
-	0xe2, 0x39, 0x0c, 0xda, 0x48, 0x23, 0x21, 0x57, 0xd9, 0x86, 0xe2, 0x01, 0x26, 0x93, 0xbe, 0x33,
-	0x16, 0x31, 0x2f, 0xf3, 0x78, 0x07, 0x14, 0xab, 0xaa, 0x22, 0xba, 0x2d, 0xc0, 0xa4, 0x70, 0x30,
-	0x1b, 0x28, 0x2d, 0x58, 0x39, 0x71, 0xac, 0xc9, 0x88, 0x86, 0xba, 0xb2, 0x5c, 0xd7, 0x8b, 0x8f,
-	0xd7, 0xb5, 0xcf, 0xf1, 0x81, 0xb6, 0xe5, 0x93, 0xe8, 0x50, 0xb9, 0x03, 0xcb, 0xfe, 0x68, 0x7c,
-	0xe8, 0x85, 0xea, 0x96, 0xb8, 0xba, 0x17, 0xce, 0x30, 0x18, 0x83, 0x07, 0xda, 0x8a, 0x7e, 0x64,
-	0x54, 0xfe, 0x59, 0x0a, 0x0a, 0x91, 0x95, 0x2b, 0x5d, 0x28, 0x60, 0x8e, 0x1d, 0xeb, 0x47, 0x3c,
-	0x6e, 0xcb, 0xb3, 0xb8, 0xf1, 0x44, 0xbb, 0xae, 0x74, 0x66, 0x82, 0x24, 0xaa, 0x45, 0xfd, 0x30,
-	0x09, 0x85, 0x08, 0x53, 0x79, 0x19, 0x72, 0xa4, 0x43, 0x9a, 0xfb, 0x5a, 0xaf, 0x51, 0x3a, 0x57,
-	0x5e, 0xff, 0xe0, 0xc3, 0xab, 0x6b, 0x5c, 0x5b, 0x54, 0x41, 0xc7, 0x35, 0x4f, 0x98, 0xeb, 0x5d,
-	0x87, 0xa5, 0x00, 0x9a, 0x28, 0x3f, 0x83, 0xd0, 0xa7, 0x17, 0xa1, 0x11, 0x24, 0xe9, 0x6e, 0x6b,
-	0x04, 0xbd, 0x2f, 0x19, 0x8f, 0x24, 0xdd, 0xa1, 0xee, 0xd2, 0x81, 0xf2, 0x02, 0x64, 0x25, 0x30,
-	0x55, 0x2e, 0x23, 0xf0, 0xd2, 0x22, 0x70, 0x86, 0x23, 0xdd, 0x1d, 0x6d, 0xbf, 0x51, 0x4a, 0xc7,
-	0xe3, 0x48, 0xd7, 0xd2, 0x4f, 0xa8, 0xf2, 0x3c, 0xde, 0x13, 0x0e, 0xcb, 0x94, 0x2f, 0x23, 0xec,
-	0xa9, 0x47, 0xd4, 0x31, 0x54, 0x79, 0xed, 0x17, 0xbf, 0xd9, 0x38, 0xf7, 0xc7, 0xdf, 0x6e, 0x94,
-	0x16, 0xd9, 0xe5, 0x7f, 0x27, 0x60, 0x79, 0xee, 0xc8, 0x31, 0x45, 0x66, 0x6d, 0xc7, 0x70, 0xc6,
-	0x22, 0x9c, 0xe7, 0xaa, 0x80, 0x5e, 0x9a, 0x6d, 0x39, 0x35, 0xa4, 0x10, 0xc9, 0x41, 0x3f, 0x98,
-	0x4f, 0x48, 0x6f, 0x3c, 0xa1, 0x3f, 0xc5, 0xa6, 0xa4, 0x5b, 0xb0, 0x3c, 0x40, 0x3b, 0x52, 0xb7,
-	0x6f, 0x38, 0xf6, 0xa1, 0x79, 0x24, 0x43, 0x75, 0x39, 0x4e, 0x67, 0x9d, 0x03, 0x49, 0x51, 0x08,
-	0xd4, 0x38, 0xfe, 0x1b, 0x24, 0xa3, 0xf2, 0x3e, 0x14, 0xa3, 0x1e, 0xaa, 0x3c, 0x0b, 0xe0, 0x99,
-	0x3f, 0xa6, 0xb2, 0xbe, 0xe1, 0xd5, 0x10, 0xc9, 0x33, 0x0a, 0xaf, 0x6e, 0x94, 0x17, 0x21, 0x3d,
-	0xc2, 0x50, 0xc6, 0xf5, 0x64, 0xaa, 0x17, 0x58, 0x4e, 0xfc, 0xeb, 0xa7, 0x57, 0x0a, 0x8e, 0x57,
-	0xd9, 0x32, 0x2d, 0xba, 0x8b, 0x2c, 0xc2, 0x01, 0xea, 0x09, 0xa4, 0x59, 0xa8, 0x50, 0x9e, 0x81,
-	0x74, 0xb5, 0xd9, 0xaa, 0xa3, 0xab, 0x9d, 0xc7, 0xd3, 0x59, 0xe6, 0x26, 0x61, 0x0c, 0xe6, 0xbb,
-	0xca, 0x15, 0xc8, 0xee, 0xb7, 0x77, 0xf6, 0x76, 0x99, 0x7b, 0x5d, 0x40, 0xf6, 0x6a, 0xc8, 0x16,
-	0x46, 0xc3, 0xd5, 0x64, 0x7a, 0xbb, 0x9d, 0xad, 0x2e, 0x3a, 0x95, 0x82, 0xfc, 0x95, 0x90, 0xcf,
-	0xd7, 0x5c, 0x3e, 0x2f, 0x4f, 0x35, 0x1f, 0xd2, 0xd5, 0x7f, 0x25, 0x61, 0x99, 0xb0, 0xfa, 0xd6,
-	0xf5, 0x3b, 0x8e, 0x65, 0x1a, 0x53, 0xa5, 0x03, 0x79, 0x34, 0xeb, 0xc0, 0x8c, 0xdc, 0xa9, 0xcd,
-	0xc7, 0x24, 0xc1, 0x99, 0x54, 0x30, 0xaa, 0x05, 0x92, 0x64, 0xa6, 0x04, 0x83, 0x65, 0x66, 0x40,
-	0x2d, 0x7d, 0x7a, 0x56, 0x36, 0xae, 0xcb, 0x5a, 0x9a, 0x08, 0x28, 0xaf, 0x1c, 0xf5, 0x7b, 0x7d,
-	0xdd, 0xf7, 0xe9, 0x68, 0xec, 0x8b, 0x6c, 0x9c, 0xc6, 0xca, 0x51, 0xbf, 0xa7, 0x49, 0x92, 0xf2,
-	0x26, 0x64, 0x4f, 0xd1, 0x2a, 0xce, 0xa9, 0x4c, 0xb8, 0x67, 0xeb, 0x95, 0x58, 0xf5, 0x03, 0x96,
-	0x67, 0x17, 0x16, 0xcb, 0xac, 0xde, 0x6a, 0xb7, 0x1a, 0x81, 0xd5, 0x25, 0xbf, 0x6d, 0xb7, 0x1c,
-	0x9b, 0xdd, 0x18, 0x68, 0xb7, 0xfa, 0x5b, 0x5a, 0x73, 0x67, 0x8f, 0x30, 0xcb, 0x5f, 0x44, 0x48,
-	0x29, 0x84, 0x6c, 0xe9, 0xa6, 0xc5, 0x8a, 0xc0, 0xcb, 0x90, 0xd2, 0x5a, 0x98, 0x5d, 0xca, 0x25,
-	0x64, 0x17, 0x43, 0xb6, 0x66, 0x4f, 0x67, 0x97, 0x69, 0x71, 0x5e, 0xf5, 0x3d, 0x28, 0xee, 0x8d,
-	0x07, 0x18, 0x10, 0x84, 0x63, 0x2a, 0x57, 0x31, 0xa2, 0xe9, 0xae, 0x6e, 0x59, 0xd4, 0x32, 0xbd,
-	0x91, 0xec, 0x13, 0xa2, 0x24, 0x2c, 0x6e, 0x9e, 0xdc, 0x96, 0xb2, 0x06, 0x13, 0x02, 0xea, 0x4f,
-	0x61, 0x15, 0x67, 0xf1, 0x75, 0x2c, 0x36, 0x82, 0xf2, 0x62, 0x13, 0x8a, 0x46, 0x40, 0xea, 0x9b,
-	0x03, 0x71, 0x03, 0xaa, 0xab, 0x78, 0x7f, 0x0b, 0x21, 0xb4, 0x59, 0x27, 0x85, 0x10, 0xd4, 0x1c,
-	0xb0, 0x7d, 0x8e, 0x11, 0x2a, 0x1c, 0x7a, 0x09, 0xa1, 0xa9, 0x0e, 0x42, 0x18, 0x0d, 0xad, 0x98,
-	0xa7, 0xf7, 0x4c, 0x1f, 0x6f, 0xe5, 0x40, 0x14, 0x10, 0x19, 0x92, 0x63, 0x84, 0x1a, 0x73, 0xf0,
-	0xf7, 0x93, 0x00, 0x3d, 0xdd, 0x3b, 0x96, 0x53, 0x63, 0xa9, 0x15, 0x36, 0x56, 0x67, 0x15, 0xf8,
-	0xbd, 0x00, 0x44, 0x66, 0x78, 0xe5, 0x8d, 0xa0, 0x82, 0x10, 0x75, 0x4f, 0xbc, 0xa0, 0x9c, 0x2b,
-	0xae, 0x74, 0x98, 0x2f, 0x6e, 0xd8, 0xfd, 0xa7, 0xae, 0xcb, 0xbd, 0x08, 0xef, 0x3f, 0x7e, 0x62,
-	0xbf, 0x95, 0x0f, 0xf7, 0x2c, 0xb3, 0xe9, 0x73, 0x71, 0x93, 0x2c, 0x18, 0x74, 0xfb, 0x1c, 0x99,
-	0xc9, 0x55, 0x4b, 0xb0, 0xe2, 0xe2, 0x35, 0xc3, 0x55, 0xf7, 0x3d, 0xce, 0x56, 0xff, 0x8c, 0x36,
-	0x68, 0x76, 0xb4, 0x5d, 0x79, 0xda, 0x75, 0xc8, 0x1e, 0xea, 0x23, 0xd3, 0x9a, 0xca, 0x6b, 0xf6,
-	0x6a, 0xdc, 0x14, 0x33, 0x7c, 0x45, 0x1b, 0x0c, 0xb0, 0xdc, 0xf4, 0xb6, 0xb8, 0x0c, 0x91, 0xb2,
-	0xbc, 0xac, 0x98, 0x1c, 0xd8, 0x58, 0x3e, 0x04, 0x65, 0x05, 0x1f, 0xb1, 0x18, 0xe6, 0xea, 0x76,
-	0xb8, 0x5b, 0x31, 0x60, 0x56, 0xc0, 0x40, 0x4e, 0x4f, 0xf5, 0xa9, 0xdc, 0x6f, 0x30, 0xc4, 0x22,
-	0x22, 0x27, 0xba, 0x20, 0x3a, 0xc0, 0x2d, 0xb3, 0x20, 0xfd, 0x55, 0xeb, 0x21, 0x12, 0x2e, 0xa2,
-	0x73, 0x28, 0x5d, 0x7e, 0x9b, 0x87, 0x94, 0x19, 0xeb, 0x6b, 0x55, 0xfb, 0xaf, 0xc3, 0xf2, 0xdc,
-	0x3e, 0x1f, 0xa9, 0xe7, 0x9a, 0x9d, 0xfd, 0x37, 0x4b, 0x69, 0xf9, 0xf5, 0xff, 0xa5, 0xac, 0xfa,
-	0x4f, 0x2c, 0x2f, 0x3b, 0x0e, 0xbf, 0x56, 0xcc, 0xaa, 0xf1, 0xfd, 0x73, 0x8e, 0x77, 0xe3, 0x86,
-	0x63, 0x49, 0x9f, 0x89, 0x2d, 0x68, 0x66, 0x5a, 0x58, 0x7d, 0xc0, 0xe1, 0x24, 0x14, 0xc4, 0xe8,
-	0x5b, 0x10, 0x95, 0x59, 0x7f, 0x8c, 0x38, 0x6e, 0xd6, 0x65, 0x02, 0x82, 0xc4, 0x24, 0x59, 0x73,
-	0x36, 0x9e, 0x1c, 0xe0, 0x35, 0x1d, 0xd2, 0x81, 0xc0, 0xa4, 0x39, 0x66, 0x39, 0xa4, 0x32, 0x98,
-	0x5a, 0xc7, 0xf6, 0x32, 0xd0, 0xb9, 0x06, 0xa9, 0x5e, 0xad, 0x83, 0x71, 0x67, 0x15, 0xa3, 0x46,
-	0x21, 0x20, 0x23, 0x89, 0x71, 0xf6, 0xea, 0x1d, 0x0c, 0x37, 0x73, 0x1c, 0x24, 0x95, 0xd3, 0x2c,
-	0x9c, 0xa8, 0xbf, 0x4a, 0x40, 0x56, 0x24, 0xb7, 0xd8, 0x1d, 0x6b, 0xb0, 0x14, 0x94, 0x5c, 0x22,
-	0xe3, 0xbe, 0xf8, 0xf8, 0xec, 0x58, 0x91, 0xc9, 0x4c, 0x9c, 0x63, 0x20, 0x57, 0x7e, 0x0b, 0x8a,
-	0x51, 0xc6, 0xd7, 0x3a, 0xc5, 0x9f, 0x40, 0x81, 0x39, 0x4a, 0x90, 0x25, 0x37, 0x21, 0x2b, 0x12,
-	0xb0, 0xbc, 0xea, 0x67, 0xa5, 0x6a, 0x89, 0xc4, 0x48, 0xb7, 0x24, 0xd2, 0x7b, 0xd0, 0x78, 0x6e,
-	0x9c, 0xed, 0x8e, 0x24, 0x80, 0xab, 0xb7, 0x20, 0xdd, 0xa1, 0xa8, 0xe1, 0x39, 0x58, 0xb2, 0x31,
-	0xf4, 0xcc, 0x22, 0x9b, 0xac, 0x4c, 0x06, 0x14, 0x23, 0x56, 0x96, 0xb1, 0x30, 0x9e, 0xa1, 0xf1,
-	0x74, 0xf4, 0xb7, 0xa0, 0xf7, 0x66, 0xdf, 0x6a, 0x0f, 0x8a, 0x77, 0xa9, 0x79, 0x34, 0xf4, 0xf1,
-	0xc4, 0x98, 0xa2, 0x57, 0x21, 0x3d, 0xa6, 0xe1, 0xe2, 0xd7, 0x62, 0x5d, 0x07, 0xf9, 0x84, 0xa3,
-	0xd8, 0x85, 0x3c, 0xe5, 0xd2, 0xf2, 0xb9, 0x43, 0x8e, 0xd4, 0xdf, 0x27, 0x61, 0xa5, 0xe9, 0x79,
-	0x13, 0x1d, 0x5b, 0x09, 0x19, 0x05, 0xbf, 0x37, 0xdf, 0x0a, 0x5d, 0x8f, 0xdd, 0xe1, 0x9c, 0xc8,
-	0x7c, 0x3b, 0x24, 0x23, 0x57, 0x32, 0x8c, 0x5c, 0xea, 0xc3, 0x44, 0xd0, 0x07, 0x5d, 0x8b, 0xdc,
-	0x9b, 0xf2, 0x1a, 0x3a, 0xd1, 0xc5, 0xa8, 0x26, 0xba, 0x67, 0x1f, 0xdb, 0xce, 0xa9, 0x8d, 0x89,
-	0x16, 0xfb, 0xa2, 0x56, 0xe3, 0x2e, 0x7a, 0xda, 0x25, 0x04, 0x29, 0x73, 0x20, 0x42, 0x6d, 0x7a,
-	0xca, 0x34, 0x75, 0x1a, 0xad, 0x7a, 0xb3, 0x75, 0x1b, 0xd3, 0xdb, 0xa3, 0x9a, 0x3a, 0x14, 0xd3,
-	0x99, 0x7d, 0x84, 0xe6, 0xce, 0x36, 0xbb, 0xdd, 0x3d, 0x5e, 0xa9, 0x3e, 0x8d, 0xa8, 0x0b, 0x73,
-	0x28, 0x36, 0xc0, 0x32, 0x15, 0x41, 0x2c, 0x93, 0x22, 0x28, 0x1d, 0x03, 0x62, 0xc9, 0x14, 0x03,
-	0x88, 0xf0, 0xf0, 0xbf, 0x25, 0xa1, 0xa4, 0x19, 0x06, 0x1d, 0xfb, 0x8c, 0x2f, 0xab, 0x93, 0x1e,
-	0xde, 0x64, 0xf6, 0x65, 0xf2, 0x6a, 0x8b, 0xb9, 0xc5, 0xcd, 0xd8, 0xb7, 0xb0, 0x05, 0xb9, 0x0a,
-	0x71, 0x2c, 0xaa, 0x0d, 0x46, 0xa6, 0xc7, 0xde, 0x47, 0x04, 0x8d, 0x84, 0x9a, 0xca, 0x5f, 0x24,
-	0xe0, 0x42, 0x0c, 0x42, 0x79, 0x1d, 0xd2, 0x2e, 0x92, 0xe5, 0xf1, 0xac, 0x3f, 0xae, 0x53, 0x65,
-	0xa2, 0x84, 0x23, 0x95, 0x0d, 0x00, 0x7d, 0xe2, 0x3b, 0x3a, 0x9f, 0x9f, 0x1f, 0x4c, 0x8e, 0x44,
-	0x28, 0xca, 0x5d, 0x8c, 0xd6, 0xd4, 0x70, 0x65, 0xb3, 0x57, 0xd8, 0xbc, 0xf5, 0xdf, 0xae, 0xbe,
-	0xd2, 0xe5, 0x6a, 0x88, 0x54, 0x57, 0xae, 0x60, 0x9f, 0xc0, 0xbf, 0x98, 0x47, 0x63, 0x49, 0xa1,
-	0xf3, 0x45, 0x17, 0x09, 0xff, 0x66, 0x8e, 0xa2, 0x5b, 0x47, 0x81, 0xa3, 0xe0, 0xa7, 0xfa, 0x11,
-	0xe6, 0xa2, 0xc6, 0x3d, 0x9f, 0xba, 0xb6, 0x6e, 0xd5, 0x34, 0xa5, 0x11, 0x89, 0x90, 0x62, 0xb7,
-	0x2f, 0xc5, 0xbe, 0x5f, 0x84, 0x12, 0x95, 0x9a, 0x16, 0x13, 0x23, 0xb1, 0x3a, 0x98, 0xb8, 0x96,
-	0x7c, 0x0b, 0xe3, 0xd5, 0xc1, 0x1e, 0xd9, 0x21, 0x8c, 0xc6, 0x1e, 0x92, 0x82, 0x88, 0x94, 0x7a,
-	0xfc, 0x23, 0x66, 0x64, 0x82, 0x6f, 0x3f, 0x2a, 0xbd, 0x0a, 0x30, 0x5b, 0x35, 0x1e, 0x55, 0xa6,
-	0xb6, 0xd5, 0xed, 0xee, 0xe0, 0xf5, 0xe0, 0xc5, 0xf4, 0x8c, 0xc5, 0xc9, 0xea, 0xef, 0x12, 0x90,
-	0xab, 0x69, 0x32, 0xab, 0x6c, 0x41, 0x89, 0xc7, 0x12, 0x83, 0xba, 0x7e, 0x9f, 0xde, 0x1b, 0x9b,
-	0xee, 0x54, 0x86, 0x83, 0xb3, 0xcb, 0xce, 0x15, 0x26, 0x55, 0x43, 0xa1, 0x06, 0x97, 0x51, 0x08,
-	0x14, 0xa9, 0xdc, 0x62, 0xdf, 0xd0, 0x83, 0xe0, 0xbc, 0x71, 0xb6, 0x29, 0x44, 0x49, 0x36, 0x1b,
-	0x63, 0xd3, 0x1e, 0x28, 0xa9, 0xe9, 0x9e, 0xba, 0x0f, 0x17, 0xda, 0xae, 0x31, 0xc4, 0xe2, 0x48,
-	0x4c, 0x2a, 0x97, 0x7c, 0x0b, 0xd6, 0x7d, 0x2c, 0x82, 0xfa, 0x43, 0xd3, 0xf3, 0xd9, 0x13, 0x2c,
-	0xfa, 0x06, 0xb5, 0x19, 0xbf, 0xcf, 0x9f, 0x4a, 0x65, 0xb3, 0x72, 0x99, 0x61, 0xb6, 0x05, 0x84,
-	0x04, 0x88, 0x1d, 0x06, 0x50, 0x7f, 0x00, 0xa5, 0xba, 0xe9, 0x8d, 0x75, 0x1f, 0x75, 0xcb, 0xd6,
-	0x49, 0xb9, 0x0d, 0xa5, 0x21, 0xc5, 0x1a, 0xf6, 0x80, 0xea, 0x98, 0x07, 0xa9, 0x6b, 0x3a, 0x83,
-	0x27, 0xb2, 0xc3, 0x6a, 0x28, 0xd5, 0xe1, 0x42, 0xea, 0x97, 0x98, 0xb5, 0xd9, 0xdb, 0x94, 0xd4,
-	0xfb, 0x0a, 0x9c, 0xf7, 0x6c, 0x7d, 0xec, 0x0d, 0x1d, 0xbf, 0x6f, 0xda, 0x3e, 0x7b, 0x8c, 0xb5,
-	0x64, 0xfd, 0x5b, 0x0a, 0x18, 0x4d, 0x49, 0xc7, 0x78, 0xac, 0x1c, 0x53, 0x3a, 0xee, 0x3b, 0xd6,
-	0xa0, 0x1f, 0x30, 0xc5, 0x03, 0x2c, 0xa2, 0x19, 0xa7, 0x6d, 0x0d, 0xba, 0x01, 0x5d, 0xa9, 0xc2,
-	0x86, 0xe5, 0x1c, 0xf5, 0x71, 0x67, 0x2e, 0xde, 0xf5, 0xfe, 0xa1, 0xe3, 0xf6, 0x3d, 0xcb, 0x39,
-	0xc5, 0x0f, 0x0b, 0xff, 0xa8, 0x1b, 0x34, 0x17, 0x65, 0x44, 0x35, 0x04, 0x68, 0xcb, 0x71, 0xbb,
-	0xc8, 0xdb, 0x0a, 0x10, 0x2c, 0xb5, 0xcf, 0xb6, 0xed, 0x9b, 0xc6, 0x71, 0x90, 0xda, 0x43, 0x6a,
-	0x0f, 0x89, 0x18, 0xdd, 0x96, 0xa9, 0x45, 0x0d, 0x6e, 0x64, 0x8e, 0xca, 0x70, 0x54, 0x31, 0x20,
-	0x32, 0x90, 0xfa, 0xbf, 0x90, 0xef, 0x58, 0xba, 0xc1, 0x9f, 0xb9, 0x59, 0xc5, 0x8f, 0x69, 0x8b,
-	0x9d, 0x1c, 0xee, 0x5a, 0x84, 0xb4, 0x3c, 0x89, 0x92, 0xd4, 0xf7, 0x31, 0xd1, 0x13, 0xc7, 0xf1,
-	0xf1, 0x92, 0x5e, 0x85, 0xac, 0xa1, 0xf7, 0x03, 0x77, 0x2f, 0x56, 0xf3, 0xe8, 0x16, 0x99, 0x9a,
-	0x76, 0x87, 0x4e, 0x49, 0xc6, 0xd0, 0xf1, 0x8f, 0xa5, 0x3c, 0x44, 0x30, 0x27, 0xe5, 0xe6, 0x28,
-	0x8a, 0x94, 0x87, 0x5e, 0x8c, 0x14, 0x82, 0xc2, 0xec, 0x1f, 0xa3, 0x5a, 0x51, 0x82, 0xfa, 0x43,
-	0xdd, 0x1b, 0x8a, 0x02, 0xb1, 0xba, 0x82, 0x48, 0x10, 0xc8, 0x6d, 0xa4, 0x12, 0x10, 0x68, 0xf6,
-	0xad, 0xfe, 0x25, 0x01, 0x05, 0x36, 0x30, 0x0f, 0x4d, 0x83, 0xe5, 0x96, 0xaf, 0x1f, 0x17, 0x31,
-	0x30, 0x18, 0x9e, 0x2b, 0x17, 0xc5, 0x03, 0x43, 0xad, 0x4b, 0x08, 0xa3, 0x29, 0xef, 0x60, 0x48,
-	0xe4, 0xb9, 0x4d, 0x86, 0x44, 0xf5, 0xab, 0xb3, 0xa0, 0xec, 0x6c, 0xa4, 0x1c, 0x37, 0xe2, 0x6c,
-	0x75, 0xfc, 0x68, 0x8a, 0x24, 0x4a, 0x62, 0x4f, 0xf4, 0x86, 0xcd, 0x4f, 0x43, 0x3e, 0xd1, 0xd7,
-	0x5a, 0x04, 0x29, 0xea, 0x9f, 0x12, 0xb0, 0xdc, 0xb0, 0x0d, 0x77, 0xca, 0x43, 0x0a, 0xb3, 0xe0,
-	0x3a, 0xe4, 0xb1, 0x80, 0xf6, 0xa6, 0x1e, 0x76, 0x99, 0xc1, 0x0b, 0x60, 0x48, 0x50, 0x9a, 0x90,
-	0xc7, 0xe0, 0xe9, 0xb8, 0xa6, 0x3f, 0x1c, 0xc9, 0x4a, 0x32, 0x3e, 0x8c, 0x45, 0x75, 0x56, 0xb4,
-	0x40, 0x84, 0xcc, 0xa4, 0x83, 0xc0, 0x95, 0xe2, 0x8b, 0xe5, 0x81, 0x0b, 0x7b, 0x5e, 0x0b, 0xdb,
-	0x1b, 0xac, 0x11, 0xfb, 0xac, 0x6b, 0xe0, 0xfb, 0xc0, 0xf6, 0x4f, 0xd2, 0x58, 0x27, 0xa4, 0xaa,
-	0x90, 0x0f, 0x95, 0xb1, 0x77, 0x57, 0xad, 0xd1, 0xed, 0xdf, 0xd8, 0xbc, 0xd9, 0xbf, 0x5d, 0xdb,
-	0xc5, 0x30, 0x26, 0xf2, 0xe6, 0x1f, 0x70, 0x4f, 0xbb, 0xba, 0x8d, 0x9d, 0x4d, 0xd0, 0xe7, 0xa1,
-	0x57, 0xb8, 0x78, 0xd5, 0x82, 0x42, 0x28, 0x2d, 0xbc, 0x82, 0xdd, 0x3e, 0x56, 0x08, 0x31, 0x56,
-	0x7c, 0x21, 0x14, 0x79, 0x7f, 0x4e, 0x9d, 0xf9, 0xfe, 0x9c, 0xfe, 0x56, 0xde, 0x9f, 0x5f, 0xfe,
-	0x32, 0x05, 0xf9, 0xb0, 0x6f, 0x63, 0x2e, 0xc3, 0xea, 0x92, 0x73, 0xa2, 0xa3, 0x0e, 0xe9, 0x2d,
-	0x5e, 0x91, 0xe4, 0xb5, 0x9d, 0x9d, 0x76, 0x4d, 0x63, 0xcf, 0xb7, 0xef, 0x88, 0xc2, 0x25, 0x04,
-	0x68, 0x78, 0x69, 0xd9, 0xa1, 0x0f, 0x14, 0x75, 0x56, 0xb8, 0xdc, 0x97, 0x7d, 0x7b, 0x88, 0x0a,
-	0xaa, 0x96, 0xe7, 0x21, 0xa7, 0x75, 0xbb, 0xcd, 0xdb, 0x2d, 0xd4, 0xf4, 0x20, 0x51, 0x7e, 0x0a,
-	0x41, 0xe7, 0x67, 0xaa, 0x30, 0xe1, 0x1e, 0xd9, 0xa8, 0x89, 0xa1, 0x6a, 0xb5, 0x46, 0x87, 0xcd,
-	0x77, 0x3f, 0xb9, 0x88, 0xe2, 0xe9, 0x9a, 0xbf, 0xc1, 0xe5, 0x3b, 0xa4, 0xd1, 0xd1, 0x08, 0x9b,
-	0xf1, 0x41, 0x72, 0x61, 0x5d, 0x1d, 0x97, 0x62, 0x27, 0xcf, 0xe6, 0xdc, 0x08, 0xde, 0xa2, 0xef,
-	0xa7, 0xc4, 0x3b, 0xcd, 0xac, 0x59, 0x45, 0xfb, 0x4e, 0xd9, 0x6c, 0xdd, 0x9e, 0x46, 0x7a, 0x5c,
-	0x4d, 0x6a, 0x61, 0xb6, 0x2e, 0x7b, 0x42, 0x60, 0x5a, 0x70, 0x77, 0x64, 0xaf, 0xd5, 0xe2, 0xbb,
-	0x4b, 0x2f, 0xec, 0x8e, 0x4c, 0x6c, 0x9b, 0x61, 0xae, 0x61, 0x0a, 0x6b, 0xef, 0x76, 0x76, 0x1a,
-	0xbd, 0x46, 0xe9, 0x41, 0x7a, 0x61, 0x41, 0x35, 0x67, 0x34, 0xb6, 0xa8, 0x2f, 0xb6, 0xd7, 0xdd,
-	0xde, 0xeb, 0xf1, 0xa7, 0xf2, 0xfb, 0x99, 0xc5, 0x09, 0x87, 0x13, 0x7f, 0xc0, 0x4a, 0xc5, 0xab,
-	0x61, 0xed, 0xf6, 0x20, 0x23, 0x52, 0x66, 0x88, 0x11, 0x85, 0x1b, 0xd3, 0x43, 0x1a, 0xdf, 0x17,
-	0xaf, 0xea, 0xf7, 0xb3, 0x0b, 0x7a, 0x08, 0x7d, 0x0f, 0xa3, 0x20, 0x96, 0x77, 0xe1, 0x33, 0x54,
-	0xc8, 0x7a, 0xf9, 0x87, 0x90, 0x0b, 0x02, 0x06, 0x5a, 0x27, 0x7b, 0xb7, 0x4d, 0xee, 0x34, 0x08,
-	0x1e, 0x3d, 0xb7, 0x4e, 0xc0, 0xb9, 0xeb, 0xb8, 0xe8, 0x5d, 0xb8, 0x8c, 0xa5, 0x5d, 0xad, 0xa5,
-	0xdd, 0x46, 0x80, 0x7c, 0x06, 0x0b, 0x00, 0xd2, 0xeb, 0xcb, 0x25, 0x39, 0x41, 0xa8, 0xb3, 0xba,
-	0xfe, 0xf0, 0xb3, 0x8d, 0x73, 0x9f, 0xe0, 0xef, 0x8b, 0xcf, 0x36, 0x12, 0xf7, 0x3f, 0xdf, 0x48,
-	0x3c, 0xc4, 0xdf, 0xc7, 0xf8, 0xfb, 0x3b, 0xfe, 0x0e, 0xb2, 0xbc, 0x7e, 0x79, 0xe3, 0x3f, 0x01,
-	0x00, 0x00, 0xff, 0xff, 0x24, 0xa1, 0x77, 0xb8, 0x17, 0x1e, 0x00, 0x00,
+	0xc8, 0xa2, 0x5d, 0xf4, 0xdc, 0xc7, 0x0c, 0x1f, 0x1e, 0x2b, 0x4a, 0x93, 0x85, 0xc0, 0xb9, 0xe7,
+	0xfe, 0xce, 0xb9, 0xaf, 0x73, 0xcf, 0xf9, 0x9d, 0x2b, 0xc8, 0xf9, 0xe3, 0x21, 0xf5, 0x4a, 0x43,
+	0xd7, 0xf1, 0x1d, 0x45, 0xe9, 0x39, 0xc6, 0x31, 0x75, 0x4b, 0xde, 0xa9, 0xee, 0x0e, 0x8e, 0x4d,
+	0xbf, 0x74, 0x72, 0xa3, 0x78, 0xc5, 0x37, 0x07, 0xd4, 0xf3, 0xf5, 0xc1, 0xf0, 0xb5, 0xf0, 0x4b,
+	0xc0, 0x8b, 0x4f, 0xf7, 0x46, 0xae, 0xee, 0x9b, 0x8e, 0xfd, 0x5a, 0xf0, 0x21, 0x3b, 0x2e, 0x1d,
+	0x39, 0x47, 0x0e, 0xff, 0x7c, 0x8d, 0x7d, 0x09, 0xa9, 0x7a, 0x15, 0x16, 0xf7, 0xa9, 0xeb, 0x21,
+	0x4c, 0xb9, 0x04, 0x29, 0xd3, 0xee, 0xd1, 0xfb, 0xab, 0xb1, 0x8d, 0xd8, 0xf5, 0x24, 0x11, 0x0d,
+	0xf5, 0xd7, 0x31, 0xc8, 0x69, 0xb6, 0xed, 0xf8, 0xdc, 0x96, 0xa7, 0x28, 0x90, 0xb4, 0xf5, 0x01,
+	0xe5, 0xa0, 0x2c, 0xe1, 0xdf, 0x4a, 0x05, 0xd2, 0x96, 0x7e, 0x40, 0x2d, 0x6f, 0x35, 0xbe, 0x91,
+	0xb8, 0x9e, 0xdb, 0x7c, 0xa5, 0xf4, 0xf8, 0x9c, 0x4b, 0x53, 0x46, 0x4a, 0x3b, 0x1c, 0x5d, 0xb3,
+	0x7d, 0x77, 0x4c, 0xa4, 0x6a, 0xf1, 0x2d, 0xc8, 0x4d, 0x89, 0x95, 0x02, 0x24, 0x8e, 0xe9, 0x58,
+	0x0e, 0xc3, 0x3e, 0xd9, 0xfc, 0x4e, 0x74, 0x6b, 0x44, 0x71, 0x10, 0x26, 0x13, 0x8d, 0xb7, 0xe3,
+	0x37, 0x63, 0xea, 0x07, 0x90, 0x25, 0xd4, 0x73, 0x46, 0xae, 0x41, 0x3d, 0xe5, 0x25, 0xc8, 0xda,
+	0xba, 0xed, 0x74, 0x8d, 0xe1, 0xc8, 0xe3, 0xea, 0x89, 0x72, 0xfe, 0x8b, 0xcf, 0xae, 0x66, 0x1a,
+	0x28, 0xac, 0xb4, 0xf6, 0x3c, 0x92, 0x61, 0xdd, 0x15, 0xec, 0x55, 0xfe, 0x07, 0xf2, 0x03, 0x3a,
+	0x70, 0xdc, 0x71, 0xf7, 0x60, 0xec, 0x53, 0x8f, 0x1b, 0x4e, 0x90, 0x9c, 0x90, 0x95, 0x99, 0x48,
+	0xfd, 0x65, 0x0c, 0x2e, 0x05, 0xb6, 0x09, 0xfd, 0xe1, 0xc8, 0x74, 0xe9, 0x80, 0xda, 0xbe, 0xa7,
+	0xfc, 0x1f, 0xae, 0xd9, 0x1c, 0x98, 0xbe, 0x18, 0x23, 0xb7, 0xf9, 0x6c, 0xd4, 0x9a, 0xc3, 0x59,
+	0x11, 0x09, 0x56, 0x34, 0xc8, 0xbb, 0xd4, 0xa3, 0xee, 0x89, 0xd8, 0x09, 0x3e, 0xe4, 0xd7, 0x2a,
+	0xcf, 0xa8, 0xa8, 0x5b, 0x90, 0x69, 0x59, 0xba, 0x7f, 0xe8, 0xb8, 0x03, 0x45, 0x85, 0xbc, 0xee,
+	0x1a, 0x7d, 0xd3, 0xa7, 0x86, 0x3f, 0x72, 0x83, 0x53, 0x99, 0x91, 0x29, 0x97, 0x21, 0xee, 0x88,
+	0x81, 0xb2, 0xe5, 0x34, 0xee, 0x44, 0xbc, 0xd9, 0x26, 0x28, 0x51, 0xdf, 0x81, 0x0b, 0x2d, 0x6b,
+	0x74, 0x64, 0xda, 0x55, 0xea, 0x19, 0xae, 0x39, 0x64, 0xd6, 0xd9, 0xf1, 0x32, 0xe7, 0x0b, 0x8e,
+	0x97, 0x7d, 0x87, 0x47, 0x1e, 0x9f, 0x1c, 0xb9, 0xfa, 0xf3, 0x38, 0x5c, 0xa8, 0xd9, 0xa8, 0x4c,
+	0xa7, 0xb5, 0xaf, 0xc1, 0x32, 0xe5, 0xc2, 0xee, 0x89, 0x70, 0x2a, 0x69, 0x67, 0x49, 0x48, 0x03,
+	0x4f, 0xab, 0xcf, 0xf9, 0xcb, 0x8d, 0xa8, 0xe5, 0x3f, 0x66, 0x3d, 0xca, 0x6b, 0x94, 0x1a, 0x2c,
+	0x0e, 0xf9, 0x22, 0xbc, 0xd5, 0x04, 0xb7, 0x75, 0x2d, 0xca, 0xd6, 0x63, 0xeb, 0x2c, 0x27, 0x1f,
+	0x7d, 0x76, 0x75, 0x81, 0x04, 0xba, 0xdf, 0xc6, 0xf9, 0xfe, 0x11, 0x83, 0x95, 0x86, 0xd3, 0x9b,
+	0xd9, 0x87, 0x22, 0x64, 0xfa, 0x8e, 0xe7, 0x4f, 0x5d, 0x94, 0xb0, 0xad, 0xdc, 0x84, 0xcc, 0x50,
+	0x1e, 0x9f, 0x3c, 0xfd, 0xb5, 0xe8, 0x29, 0x0b, 0x0c, 0x09, 0xd1, 0xca, 0x3b, 0x90, 0x75, 0x03,
+	0x9f, 0xc0, 0xd5, 0x9e, 0xc3, 0x71, 0x26, 0x78, 0xe5, 0x7b, 0x90, 0x16, 0x87, 0xb0, 0x9a, 0xe4,
+	0x9a, 0xd7, 0xce, 0xb5, 0xe7, 0x44, 0x2a, 0xa9, 0x9f, 0xc6, 0xa0, 0x40, 0xf4, 0x43, 0x7f, 0x97,
+	0x0e, 0x0e, 0xa8, 0xdb, 0xc6, 0x8b, 0x8c, 0xf7, 0xe7, 0x32, 0x9e, 0x23, 0xd5, 0x7b, 0xd4, 0xe5,
+	0x8b, 0xcc, 0x10, 0xd9, 0x52, 0xf6, 0x98, 0x93, 0xeb, 0x46, 0x5f, 0x3f, 0x30, 0x2d, 0xd3, 0x1f,
+	0xf3, 0x65, 0x2e, 0x47, 0x9f, 0xf2, 0xbc, 0x4d, 0x9c, 0xfc, 0x44, 0x91, 0xcc, 0x98, 0x51, 0x56,
+	0x61, 0x11, 0x63, 0x9d, 0xa7, 0x1f, 0x51, 0xbe, 0xfa, 0x2c, 0x09, 0x9a, 0xe8, 0xca, 0xf9, 0x69,
+	0x3d, 0x25, 0x07, 0x8b, 0x7b, 0x8d, 0x3b, 0x8d, 0xe6, 0xdd, 0x46, 0x61, 0x41, 0x59, 0x81, 0xdc,
+	0x5e, 0x83, 0xd4, 0xb4, 0xca, 0xb6, 0x56, 0xde, 0xa9, 0x15, 0x62, 0xca, 0x12, 0x86, 0x8b, 0xb0,
+	0x19, 0x57, 0x3f, 0x8e, 0x01, 0xb0, 0x03, 0x94, 0x8b, 0x7a, 0x1b, 0x52, 0x18, 0x4f, 0x7d, 0x71,
+	0x70, 0xcb, 0x9b, 0xcf, 0x47, 0xcd, 0x7a, 0x02, 0x2f, 0xb1, 0x1f, 0x4a, 0x84, 0xca, 0xf4, 0x0c,
+	0xe3, 0xf3, 0x33, 0x4c, 0x71, 0xe4, 0xec, 0xd4, 0x32, 0x90, 0xac, 0xb2, 0xaf, 0x98, 0x92, 0x85,
+	0x14, 0xce, 0xa9, 0xfa, 0x41, 0x21, 0x8e, 0xce, 0x97, 0xaf, 0xd6, 0xdb, 0x95, 0x66, 0xa3, 0x51,
+	0xab, 0x74, 0x6a, 0xd5, 0x42, 0x42, 0xbd, 0x06, 0xa9, 0xfa, 0x00, 0xad, 0x28, 0x6b, 0xcc, 0x03,
+	0x0e, 0xa9, 0x4b, 0x6d, 0x23, 0x70, 0xac, 0x89, 0x40, 0xfd, 0x04, 0x8d, 0xec, 0x3a, 0x23, 0xdb,
+	0x57, 0x36, 0xa7, 0x6e, 0xf1, 0xf2, 0xe6, 0x7a, 0xd4, 0x12, 0x38, 0xb0, 0xd4, 0x41, 0x94, 0xbc,
+	0xe5, 0x78, 0x98, 0xc2, 0x57, 0xe4, 0xd4, 0x65, 0x8b, 0xc9, 0x7d, 0xdd, 0x3d, 0xa2, 0xbe, 0xdc,
+	0x74, 0xd9, 0x52, 0xae, 0x43, 0x06, 0x4f, 0xa7, 0xe7, 0xd8, 0xd6, 0x98, 0xbb, 0x54, 0x46, 0x84,
+	0x59, 0x3c, 0x87, 0x5e, 0x13, 0x65, 0x24, 0xec, 0x55, 0xb6, 0x21, 0x7f, 0x80, 0xc9, 0xa4, 0xeb,
+	0x0c, 0x45, 0xcc, 0x4b, 0x3d, 0xd9, 0x01, 0xc5, 0xac, 0xca, 0x88, 0x6e, 0x0a, 0x30, 0xc9, 0x1d,
+	0x4c, 0x1a, 0x4a, 0x03, 0x96, 0x4f, 0x1c, 0x6b, 0x34, 0xa0, 0xa1, 0xad, 0x34, 0xb7, 0xf5, 0xe2,
+	0x93, 0x6d, 0xed, 0x73, 0x7c, 0x60, 0x6d, 0xe9, 0x64, 0xba, 0xa9, 0xdc, 0x81, 0x25, 0x7f, 0x30,
+	0x3c, 0xf4, 0x42, 0x73, 0x8b, 0xdc, 0xdc, 0x0b, 0x67, 0x6c, 0x18, 0x83, 0x07, 0xd6, 0xf2, 0xfe,
+	0x54, 0xab, 0xf8, 0xb3, 0x04, 0xe4, 0xa6, 0x66, 0xae, 0xb4, 0x21, 0x87, 0x39, 0x76, 0xa8, 0x1f,
+	0xf1, 0xb8, 0x2d, 0xcf, 0xe2, 0xc6, 0xb9, 0x56, 0x5d, 0x6a, 0x4d, 0x14, 0xc9, 0xb4, 0x15, 0xf5,
+	0xa3, 0x38, 0xe4, 0xa6, 0x3a, 0x95, 0x97, 0x21, 0x43, 0x5a, 0xa4, 0xbe, 0xaf, 0x75, 0x6a, 0x85,
+	0x85, 0xe2, 0xda, 0x87, 0x1f, 0x6d, 0xac, 0x72, 0x6b, 0xd3, 0x06, 0x5a, 0xae, 0x79, 0xc2, 0x5c,
+	0xef, 0x3a, 0x2c, 0x06, 0xd0, 0x58, 0xf1, 0x19, 0x84, 0x3e, 0x3d, 0x0f, 0x9d, 0x42, 0x92, 0xf6,
+	0xb6, 0x46, 0xd0, 0xfb, 0xe2, 0xd1, 0x48, 0xd2, 0xee, 0xeb, 0x2e, 0xed, 0x29, 0x2f, 0x40, 0x5a,
+	0x02, 0x13, 0xc5, 0x22, 0x02, 0x2f, 0xcf, 0x03, 0x27, 0x38, 0xd2, 0xde, 0xd1, 0xf6, 0x6b, 0x85,
+	0x64, 0x34, 0x8e, 0xb4, 0x2d, 0xfd, 0x84, 0x2a, 0xcf, 0xe3, 0x3d, 0xe1, 0xb0, 0x54, 0xf1, 0x0a,
+	0xc2, 0x9e, 0x7a, 0xcc, 0x1c, 0x43, 0x15, 0x57, 0x7f, 0xf1, 0x9b, 0xf5, 0x85, 0x3f, 0xfe, 0x76,
+	0xbd, 0x30, 0xdf, 0x5d, 0xfc, 0x77, 0x0c, 0x96, 0x66, 0x8e, 0x1c, 0x53, 0x64, 0xda, 0x76, 0x0c,
+	0x67, 0x28, 0xc2, 0x79, 0xa6, 0x0c, 0xe8, 0xa5, 0xe9, 0x86, 0x53, 0x41, 0x09, 0x91, 0x3d, 0xe8,
+	0x07, 0xb3, 0x09, 0xe9, 0x8d, 0x73, 0xfa, 0x53, 0x64, 0x4a, 0xba, 0x05, 0x4b, 0x3d, 0xdc, 0x47,
+	0xea, 0x76, 0x0d, 0xc7, 0x3e, 0x34, 0x8f, 0x64, 0xa8, 0x2e, 0x46, 0xd9, 0xac, 0x72, 0x20, 0xc9,
+	0x0b, 0x85, 0x0a, 0xc7, 0x7f, 0x8b, 0x64, 0x54, 0xdc, 0x87, 0xfc, 0xb4, 0x87, 0x2a, 0xcf, 0x02,
+	0x78, 0xe6, 0x8f, 0xa8, 0xe4, 0x37, 0x9c, 0x0d, 0x91, 0x2c, 0x93, 0x70, 0x76, 0xa3, 0xbc, 0x08,
+	0xc9, 0x01, 0x86, 0x32, 0x6e, 0x27, 0x55, 0xbe, 0xc8, 0x72, 0xe2, 0x5f, 0x3f, 0xbb, 0x9a, 0x73,
+	0xbc, 0xd2, 0x96, 0x69, 0xd1, 0x5d, 0xec, 0x22, 0x1c, 0xa0, 0x9e, 0x40, 0x92, 0x85, 0x0a, 0xe5,
+	0x19, 0x48, 0x96, 0xeb, 0x8d, 0x2a, 0xba, 0xda, 0x05, 0x3c, 0x9d, 0x25, 0xbe, 0x25, 0xac, 0x83,
+	0xf9, 0xae, 0x72, 0x15, 0xd2, 0xfb, 0xcd, 0x9d, 0xbd, 0x5d, 0xe6, 0x5e, 0x17, 0xb1, 0x7b, 0x25,
+	0xec, 0x16, 0x9b, 0x86, 0xb3, 0x49, 0x75, 0x76, 0x5b, 0x5b, 0x6d, 0x74, 0x2a, 0x05, 0xfb, 0x97,
+	0xc3, 0x7e, 0x3e, 0xe7, 0xe2, 0x05, 0x79, 0xaa, 0xd9, 0x50, 0xae, 0xfe, 0x2b, 0x0e, 0x4b, 0x84,
+	0xf1, 0x5b, 0xd7, 0x6f, 0x39, 0x96, 0x69, 0x8c, 0x95, 0x16, 0x64, 0x71, 0x5b, 0x7b, 0xe6, 0xd4,
+	0x9d, 0xda, 0x7c, 0x42, 0x12, 0x9c, 0x68, 0x05, 0xad, 0x4a, 0xa0, 0x49, 0x26, 0x46, 0x30, 0x58,
+	0xa6, 0x7a, 0xd4, 0xd2, 0xc7, 0x67, 0x65, 0xe3, 0xaa, 0xe4, 0xd2, 0x44, 0x40, 0x39, 0x73, 0xd4,
+	0xef, 0x77, 0x75, 0xdf, 0xa7, 0x83, 0xa1, 0x2f, 0xb2, 0x71, 0x12, 0x99, 0xa3, 0x7e, 0x5f, 0x93,
+	0x22, 0xe5, 0x4d, 0x48, 0x9f, 0xe2, 0xae, 0x38, 0xa7, 0x32, 0xe1, 0x9e, 0x6d, 0x57, 0x62, 0xd5,
+	0x0f, 0x59, 0x9e, 0x9d, 0x9b, 0x2c, 0xdb, 0xf5, 0x46, 0xb3, 0x51, 0x0b, 0x76, 0x5d, 0xf6, 0x37,
+	0xed, 0x86, 0x63, 0xb3, 0x1b, 0x03, 0xcd, 0x46, 0x77, 0x4b, 0xab, 0xef, 0xec, 0x11, 0xb6, 0xf3,
+	0x97, 0x10, 0x52, 0x08, 0x21, 0x5b, 0xba, 0x69, 0x31, 0x12, 0x78, 0x05, 0x12, 0x5a, 0x03, 0xb3,
+	0x4b, 0xb1, 0x80, 0xdd, 0xf9, 0xb0, 0x5b, 0xb3, 0xc7, 0x93, 0xcb, 0x34, 0x3f, 0xae, 0x7a, 0x0f,
+	0xf2, 0x7b, 0xc3, 0x1e, 0x06, 0x04, 0xe1, 0x98, 0xca, 0x06, 0x46, 0x34, 0xdd, 0xd5, 0x2d, 0x8b,
+	0x5a, 0xa6, 0x37, 0x90, 0x75, 0xc2, 0xb4, 0x08, 0xc9, 0xcd, 0xf9, 0xf7, 0x52, 0x72, 0x30, 0xa1,
+	0xa0, 0xfe, 0x04, 0x56, 0x70, 0x14, 0x5f, 0x47, 0xb2, 0x11, 0xd0, 0x8b, 0x4d, 0xc8, 0x1b, 0x81,
+	0xa8, 0x6b, 0xf6, 0xc4, 0x0d, 0x28, 0xaf, 0xe0, 0xfd, 0xcd, 0x85, 0xd0, 0x7a, 0x95, 0xe4, 0x42,
+	0x50, 0xbd, 0xc7, 0xd6, 0x39, 0x44, 0xa8, 0x70, 0xe8, 0x45, 0x84, 0x26, 0x5a, 0x08, 0x61, 0x32,
+	0xdc, 0xc5, 0x2c, 0xbd, 0x6f, 0xfa, 0x78, 0x2b, 0x7b, 0x82, 0x40, 0xa4, 0x48, 0x86, 0x09, 0x2a,
+	0xcc, 0xc1, 0x7f, 0x1a, 0x07, 0xe8, 0xe8, 0xde, 0xb1, 0x1c, 0x1a, 0xa9, 0x56, 0x58, 0x58, 0x9d,
+	0x45, 0xf0, 0x3b, 0x01, 0x88, 0x4c, 0xf0, 0xca, 0x1b, 0x01, 0x83, 0x10, 0xbc, 0x27, 0x5a, 0x51,
+	0x8e, 0x15, 0x45, 0x1d, 0x66, 0xc9, 0x0d, 0xbb, 0xff, 0xd4, 0x75, 0xb9, 0x17, 0xe1, 0xfd, 0xc7,
+	0x4f, 0xac, 0xb7, 0xb2, 0xe1, 0x9a, 0x65, 0x36, 0x7d, 0x2e, 0x6a, 0x90, 0xb9, 0x0d, 0xdd, 0x5e,
+	0x20, 0x13, 0xbd, 0x72, 0x01, 0x96, 0x5d, 0xbc, 0x66, 0x38, 0xeb, 0xae, 0xc7, 0xbb, 0xd5, 0x3f,
+	0xe3, 0x1e, 0xd4, 0x5b, 0xda, 0xae, 0x3c, 0xed, 0x2a, 0xa4, 0x0f, 0xf5, 0x81, 0x69, 0x8d, 0xe5,
+	0x35, 0x7b, 0x35, 0x6a, 0x88, 0x09, 0xbe, 0xa4, 0xf5, 0x7a, 0x48, 0x37, 0xbd, 0x2d, 0xae, 0x43,
+	0xa4, 0x2e, 0xa7, 0x15, 0xa3, 0x03, 0x1b, 0xe9, 0x43, 0x40, 0x2b, 0x78, 0x8b, 0xc5, 0x30, 0x57,
+	0xb7, 0xc3, 0xd5, 0x8a, 0x06, 0xdb, 0x05, 0x0c, 0xe4, 0xf4, 0x54, 0x1f, 0xcb, 0xf5, 0x06, 0x4d,
+	0x24, 0x11, 0x19, 0x51, 0x05, 0xd1, 0x1e, 0x2e, 0x99, 0x05, 0xe9, 0xaf, 0x9b, 0x0f, 0x91, 0x70,
+	0x11, 0x9d, 0x43, 0xed, 0xe2, 0x3b, 0x3c, 0xa4, 0x4c, 0xba, 0xbe, 0x11, 0xdb, 0x7f, 0x1d, 0x96,
+	0x66, 0xd6, 0xf9, 0x18, 0x9f, 0xab, 0xb7, 0xf6, 0xdf, 0x2c, 0x24, 0xe5, 0xd7, 0xff, 0x17, 0xd2,
+	0xea, 0x3f, 0x91, 0x5e, 0xb6, 0x1c, 0x7e, 0xad, 0xd8, 0xae, 0x46, 0xd7, 0xcf, 0x19, 0x5e, 0x8d,
+	0x1b, 0x8e, 0x25, 0x7d, 0x26, 0x92, 0xd0, 0x4c, 0xac, 0x30, 0x7e, 0xc0, 0xe1, 0x24, 0x54, 0xc4,
+	0xe8, 0x9b, 0x13, 0xcc, 0xac, 0x3b, 0x44, 0x1c, 0xdf, 0xd6, 0x25, 0x02, 0x42, 0xc4, 0x34, 0x59,
+	0x71, 0x36, 0x1c, 0x1d, 0xe0, 0x35, 0xed, 0xd3, 0x9e, 0xc0, 0x24, 0x39, 0x66, 0x29, 0x94, 0x32,
+	0x98, 0x5a, 0xc5, 0xf2, 0x32, 0xb0, 0xb9, 0x0a, 0x89, 0x4e, 0xa5, 0x85, 0x71, 0x67, 0x05, 0xa3,
+	0x46, 0x2e, 0x10, 0xa3, 0x88, 0xf5, 0xec, 0x55, 0x5b, 0x18, 0x6e, 0x66, 0x7a, 0x50, 0x54, 0x4c,
+	0xb2, 0x70, 0xa2, 0xfe, 0x2a, 0x06, 0x69, 0x91, 0xdc, 0x22, 0x57, 0xac, 0xc1, 0x62, 0x40, 0xb9,
+	0x44, 0xc6, 0x7d, 0xf1, 0xc9, 0xd9, 0xb1, 0x24, 0x93, 0x99, 0x38, 0xc7, 0x40, 0xaf, 0xf8, 0x36,
+	0xe4, 0xa7, 0x3b, 0xbe, 0xd1, 0x29, 0xfe, 0x18, 0x72, 0xcc, 0x51, 0x82, 0x2c, 0xb9, 0x09, 0x69,
+	0x91, 0x80, 0xe5, 0x55, 0x3f, 0x2b, 0x55, 0x4b, 0x24, 0x46, 0xba, 0x45, 0x91, 0xde, 0x83, 0xc2,
+	0x73, 0xfd, 0x6c, 0x77, 0x24, 0x01, 0x5c, 0xbd, 0x05, 0xc9, 0x16, 0x45, 0x0b, 0xcf, 0xc1, 0xa2,
+	0x8d, 0xa1, 0x67, 0x12, 0xd9, 0x24, 0x33, 0xe9, 0x51, 0x8c, 0x58, 0x69, 0xd6, 0x85, 0xf1, 0x0c,
+	0x37, 0x4f, 0x47, 0x7f, 0x0b, 0x6a, 0x6f, 0xf6, 0xad, 0x76, 0x20, 0x7f, 0x97, 0x9a, 0x47, 0x7d,
+	0x1f, 0x4f, 0x8c, 0x19, 0x7a, 0x15, 0x92, 0x43, 0x1a, 0x4e, 0x7e, 0x35, 0xd2, 0x75, 0xb0, 0x9f,
+	0x70, 0x14, 0xbb, 0x90, 0xa7, 0x5c, 0x5b, 0x3e, 0x77, 0xc8, 0x96, 0xfa, 0xfb, 0x38, 0x2c, 0xd7,
+	0x3d, 0x6f, 0xa4, 0x63, 0x29, 0x21, 0xa3, 0xe0, 0xbb, 0xb3, 0xa5, 0xd0, 0xf5, 0xc8, 0x15, 0xce,
+	0xa8, 0xcc, 0x96, 0x43, 0x32, 0x72, 0xc5, 0xc3, 0xc8, 0xa5, 0x3e, 0x8a, 0x05, 0x75, 0xd0, 0xb5,
+	0xa9, 0x7b, 0x53, 0x5c, 0x45, 0x27, 0xba, 0x34, 0x6d, 0x89, 0xee, 0xd9, 0xc7, 0xb6, 0x73, 0x6a,
+	0x63, 0xa2, 0xc5, 0xba, 0xa8, 0x51, 0xbb, 0x8b, 0x9e, 0x76, 0x19, 0x41, 0xca, 0x0c, 0x88, 0x50,
+	0x9b, 0x9e, 0x32, 0x4b, 0xad, 0x5a, 0xa3, 0x5a, 0x6f, 0xdc, 0xc6, 0xf4, 0xf6, 0xb8, 0xa5, 0x16,
+	0xc5, 0x74, 0x66, 0x1f, 0xe1, 0x76, 0xa7, 0xeb, 0xed, 0xf6, 0x1e, 0x67, 0xaa, 0x4f, 0x23, 0xea,
+	0xe2, 0x0c, 0x8a, 0x35, 0x90, 0xa6, 0x22, 0x88, 0x65, 0x52, 0x04, 0x25, 0x23, 0x40, 0x2c, 0x99,
+	0x62, 0x00, 0x11, 0x1e, 0xfe, 0xb7, 0x38, 0x14, 0x34, 0xc3, 0xa0, 0x43, 0x9f, 0xf5, 0x4b, 0x76,
+	0xd2, 0xc1, 0x9b, 0xcc, 0xbe, 0x4c, 0xce, 0xb6, 0x98, 0x5b, 0xdc, 0x8c, 0x7c, 0x0b, 0x9b, 0xd3,
+	0x2b, 0x11, 0xc7, 0xa2, 0x5a, 0x6f, 0x60, 0x7a, 0xec, 0x7d, 0x44, 0xc8, 0x48, 0x68, 0xa9, 0xf8,
+	0x65, 0x0c, 0x2e, 0x46, 0x20, 0x94, 0xd7, 0x21, 0xe9, 0xa2, 0x58, 0x1e, 0xcf, 0xda, 0x93, 0x2a,
+	0x55, 0xa6, 0x4a, 0x38, 0x52, 0x59, 0x07, 0xd0, 0x47, 0xbe, 0xa3, 0xf3, 0xf1, 0xf9, 0xc1, 0x64,
+	0xc8, 0x94, 0x44, 0xb9, 0x8b, 0xd1, 0x9a, 0x1a, 0xae, 0x2c, 0xf6, 0x72, 0x9b, 0xb7, 0xfe, 0xdb,
+	0xd9, 0x97, 0xda, 0xdc, 0x0c, 0x91, 0xe6, 0x8a, 0x25, 0xac, 0x13, 0xf8, 0x17, 0xf3, 0x68, 0xa4,
+	0x14, 0x3a, 0x9f, 0x74, 0x9e, 0xf0, 0x6f, 0xe6, 0x28, 0xba, 0x75, 0x14, 0x38, 0x0a, 0x7e, 0xaa,
+	0x1f, 0x63, 0x2e, 0xaa, 0xdd, 0xf7, 0xa9, 0x6b, 0xeb, 0x56, 0x45, 0x53, 0x6a, 0x53, 0x11, 0x52,
+	0xac, 0xf6, 0xa5, 0xc8, 0xf7, 0x8b, 0x50, 0xa3, 0x54, 0xd1, 0x22, 0x62, 0x24, 0xb2, 0x83, 0x91,
+	0x6b, 0xc9, 0xb7, 0x30, 0xce, 0x0e, 0xf6, 0xc8, 0x0e, 0x61, 0x32, 0xf6, 0x90, 0x14, 0x44, 0xa4,
+	0xc4, 0x93, 0x1f, 0x31, 0xa7, 0x06, 0xf8, 0xee, 0xa3, 0xd2, 0xab, 0x00, 0x93, 0x59, 0xe3, 0x51,
+	0xa5, 0x2a, 0x5b, 0xed, 0xf6, 0x0e, 0x5e, 0x0f, 0x4e, 0xa6, 0x27, 0x5d, 0x5c, 0xac, 0xfe, 0x2e,
+	0x06, 0x99, 0x8a, 0x26, 0xb3, 0xca, 0x16, 0x14, 0x78, 0x2c, 0x31, 0xa8, 0xeb, 0x77, 0xe9, 0xfd,
+	0xa1, 0xe9, 0x8e, 0x65, 0x38, 0x38, 0x9b, 0x76, 0x2e, 0x33, 0xad, 0x0a, 0x2a, 0xd5, 0xb8, 0x8e,
+	0x42, 0x20, 0x4f, 0xe5, 0x12, 0xbb, 0x86, 0x1e, 0x04, 0xe7, 0xf5, 0xb3, 0xb7, 0x42, 0x50, 0xb2,
+	0x49, 0x1b, 0x8b, 0xf6, 0xc0, 0x48, 0x45, 0xf7, 0xd4, 0x7d, 0xb8, 0xd8, 0x74, 0x8d, 0x3e, 0x92,
+	0x23, 0x31, 0xa8, 0x9c, 0xf2, 0x2d, 0x58, 0xf3, 0x91, 0x04, 0x75, 0xfb, 0xa6, 0xe7, 0xb3, 0x27,
+	0x58, 0xf4, 0x0d, 0x6a, 0xb3, 0xfe, 0x2e, 0x7f, 0x2a, 0x95, 0xc5, 0xca, 0x15, 0x86, 0xd9, 0x16,
+	0x10, 0x12, 0x20, 0x76, 0x18, 0x40, 0xad, 0x63, 0xad, 0x83, 0x9d, 0x55, 0x7a, 0xa8, 0x8f, 0x2c,
+	0x24, 0xdc, 0x6f, 0x01, 0x58, 0xce, 0x51, 0xf7, 0xdc, 0x91, 0x3c, 0x8b, 0x68, 0xf1, 0xa9, 0x7e,
+	0x1f, 0x0a, 0x55, 0xd3, 0x1b, 0xea, 0x3e, 0x4e, 0x53, 0x56, 0x61, 0xca, 0x6d, 0x28, 0xf4, 0x29,
+	0xd2, 0xe1, 0x03, 0xaa, 0x63, 0x4a, 0xa5, 0xae, 0xe9, 0xf4, 0xce, 0xb5, 0xa5, 0x2b, 0xa1, 0x56,
+	0x8b, 0x2b, 0xa9, 0x5f, 0x21, 0x01, 0x60, 0xcf, 0x5c, 0xd2, 0xee, 0x2b, 0x70, 0xc1, 0xb3, 0xf5,
+	0xa1, 0xd7, 0x77, 0xfc, 0xae, 0x69, 0xfb, 0xec, 0x5d, 0xd7, 0x92, 0x54, 0xba, 0x10, 0x74, 0xd4,
+	0xa5, 0x1c, 0x43, 0xbb, 0x72, 0x4c, 0xe9, 0xb0, 0xeb, 0x58, 0xbd, 0x6e, 0xd0, 0x29, 0xde, 0x72,
+	0x11, 0xcd, 0x7a, 0x9a, 0x56, 0xaf, 0x1d, 0xc8, 0x95, 0x32, 0xac, 0xb3, 0x1d, 0xc0, 0x4d, 0x72,
+	0x31, 0x6c, 0x74, 0x0f, 0x1d, 0xb7, 0xeb, 0x59, 0xce, 0x29, 0x7e, 0x58, 0xf8, 0x43, 0xdd, 0xa0,
+	0x4e, 0x29, 0x22, 0xaa, 0x26, 0x40, 0x5b, 0x8e, 0xdb, 0xc6, 0xbe, 0xad, 0x00, 0xc1, 0x58, 0xc2,
+	0x64, 0xd9, 0xbe, 0x69, 0x1c, 0x07, 0x2c, 0x21, 0x94, 0x76, 0x50, 0x88, 0x81, 0x72, 0x89, 0x5a,
+	0xd4, 0xe0, 0xe7, 0xc5, 0x51, 0x29, 0x8e, 0xca, 0x07, 0x42, 0x06, 0x52, 0xff, 0x17, 0xb2, 0x2d,
+	0x4b, 0x37, 0xf8, 0x8b, 0x39, 0x2b, 0x1e, 0x30, 0x03, 0x32, 0x27, 0xc0, 0x55, 0x8b, 0xe8, 0x98,
+	0x25, 0xd3, 0x22, 0xf5, 0x5d, 0x80, 0xf7, 0x1d, 0xd3, 0xee, 0x38, 0xc7, 0xd4, 0xe6, 0x8f, 0x8b,
+	0xa7, 0x8e, 0x7b, 0x2c, 0x8f, 0x12, 0x89, 0xa3, 0x68, 0x71, 0xa2, 0xac, 0xdb, 0x48, 0x8c, 0xdd,
+	0xf0, 0x8d, 0x4d, 0x34, 0x59, 0x72, 0x49, 0x13, 0xc7, 0xf1, 0x31, 0x5e, 0x6c, 0x40, 0xda, 0xd0,
+	0xbb, 0xc1, 0xcd, 0xcb, 0x97, 0xb3, 0xe8, 0xa1, 0xa9, 0x8a, 0x76, 0x87, 0x8e, 0x49, 0xca, 0xd0,
+	0xf1, 0x87, 0x65, 0x5f, 0x44, 0xb0, 0xfb, 0xc2, 0xcd, 0xe4, 0x45, 0xf6, 0xc5, 0x0b, 0x85, 0x12,
+	0x82, 0xca, 0xec, 0x17, 0x03, 0x6c, 0x5e, 0x82, 0xba, 0x7d, 0xdd, 0xeb, 0x0b, 0xae, 0x5a, 0x5e,
+	0x46, 0x24, 0x08, 0xe4, 0x36, 0x4a, 0x09, 0x08, 0x34, 0xfb, 0xc6, 0x30, 0x92, 0xbb, 0x87, 0x6b,
+	0xe8, 0xfa, 0x7c, 0x11, 0xb2, 0xf4, 0x8b, 0xbc, 0x3f, 0x93, 0xa5, 0xca, 0x42, 0x08, 0xee, 0x85,
+	0x12, 0xf5, 0x2f, 0x31, 0xc8, 0x31, 0x9b, 0xe6, 0xa1, 0x69, 0xb0, 0x6c, 0xf9, 0xcd, 0x23, 0x3d,
+	0x86, 0x3a, 0xc3, 0x73, 0xe5, 0xda, 0x78, 0xa8, 0xab, 0xb4, 0x09, 0x61, 0x32, 0xe5, 0x3d, 0x0c,
+	0xf2, 0x3c, 0x5b, 0xcb, 0x20, 0xaf, 0x7e, 0x7d, 0x5e, 0x97, 0x53, 0x94, 0x7a, 0xfc, 0x2c, 0x27,
+	0xb3, 0xe3, 0xab, 0xcc, 0x93, 0x69, 0x11, 0xfb, 0xa7, 0x83, 0x61, 0x73, 0xa7, 0x90, 0xff, 0x74,
+	0xa8, 0x34, 0x08, 0x4a, 0xd4, 0x3f, 0xc5, 0x60, 0xa9, 0x66, 0x1b, 0xee, 0x98, 0x07, 0x49, 0x76,
+	0x10, 0x6b, 0x90, 0xc5, 0x92, 0xc0, 0x1b, 0x7b, 0x58, 0x37, 0x07, 0x6f, 0x9a, 0xa1, 0x40, 0xa9,
+	0x43, 0x16, 0xd3, 0x81, 0xe3, 0x9a, 0x7e, 0x7f, 0x20, 0xb9, 0x71, 0x74, 0x60, 0x9e, 0xb6, 0x59,
+	0xd2, 0x02, 0x15, 0x32, 0xd1, 0x0e, 0x42, 0x71, 0x82, 0x4f, 0x96, 0x87, 0x62, 0xac, 0xe2, 0x2d,
+	0x2c, 0xd8, 0x90, 0xf5, 0x76, 0x59, 0x1d, 0xc4, 0xd7, 0x81, 0x05, 0xad, 0x94, 0xb1, 0xda, 0x4e,
+	0x55, 0x21, 0x1b, 0x1a, 0x63, 0x2f, 0xc9, 0x5a, 0xad, 0xdd, 0xbd, 0xb1, 0x79, 0xb3, 0x7b, 0xbb,
+	0xb2, 0x8b, 0x81, 0x59, 0x30, 0x81, 0x3f, 0xe0, 0x9a, 0x76, 0x85, 0x0f, 0x4a, 0xe2, 0x84, 0xce,
+	0xe5, 0xe2, 0x8d, 0x0f, 0xa8, 0x5d, 0x52, 0x38, 0x17, 0x0b, 0x02, 0x8c, 0xda, 0xb1, 0xae, 0x68,
+	0x6a, 0x37, 0xf5, 0xa2, 0x9e, 0x38, 0xf3, 0x45, 0x3d, 0xf9, 0x9d, 0xbc, 0xa8, 0xbf, 0xfc, 0x55,
+	0x02, 0xb2, 0x61, 0x25, 0xca, 0x5c, 0x86, 0x31, 0xad, 0x05, 0xf1, 0x46, 0x10, 0xca, 0x1b, 0x9c,
+	0x63, 0x65, 0xb5, 0x9d, 0x9d, 0x66, 0x45, 0x63, 0x0f, 0xd2, 0xef, 0x09, 0x2a, 0x16, 0x02, 0x34,
+	0x8c, 0x1d, 0xec, 0xd0, 0x7b, 0x8a, 0x3a, 0xa1, 0x62, 0x0f, 0xe4, 0x4b, 0x44, 0x88, 0x0a, 0x78,
+	0xd8, 0xf3, 0x90, 0xd1, 0xda, 0xed, 0xfa, 0xed, 0x06, 0x5a, 0x7a, 0x18, 0x2b, 0x3e, 0x85, 0xa0,
+	0x0b, 0x13, 0x53, 0x48, 0x21, 0x8e, 0x6c, 0xb4, 0xc4, 0x50, 0x95, 0x4a, 0xad, 0xc5, 0xc6, 0x7b,
+	0x10, 0x9f, 0x47, 0x71, 0x02, 0xc2, 0x5f, 0x15, 0xb3, 0x2d, 0x52, 0x6b, 0x69, 0x84, 0x8d, 0xf8,
+	0x30, 0x3e, 0x37, 0xaf, 0x96, 0x4b, 0x87, 0xba, 0xcb, 0xc6, 0x5c, 0x0f, 0x5e, 0xd7, 0x1f, 0x24,
+	0xc4, 0xcb, 0xd3, 0xa4, 0xfc, 0xc6, 0xfd, 0x1d, 0xb3, 0xd1, 0xda, 0x1d, 0x8d, 0x74, 0xb8, 0x99,
+	0xc4, 0xdc, 0x68, 0x6d, 0xf6, 0x28, 0xc2, 0xac, 0xe0, 0xea, 0xc8, 0x5e, 0xa3, 0xc1, 0x57, 0x97,
+	0x9c, 0x5b, 0x1d, 0x19, 0xd9, 0x36, 0xc3, 0x5c, 0xc3, 0xa4, 0xdc, 0xdc, 0x6d, 0xed, 0xd4, 0x3a,
+	0xb5, 0xc2, 0xc3, 0xe4, 0xdc, 0x84, 0x2a, 0xce, 0x60, 0x68, 0x51, 0x5f, 0x2c, 0xaf, 0xbd, 0xbd,
+	0xd7, 0xe1, 0x8f, 0xff, 0x0f, 0x52, 0xf3, 0x03, 0xf6, 0x47, 0x7e, 0x8f, 0x91, 0xdf, 0x8d, 0x90,
+	0x8d, 0x3e, 0x4c, 0x09, 0x12, 0x10, 0x62, 0x04, 0x15, 0x65, 0x76, 0x48, 0xed, 0x7d, 0xf1, 0x7f,
+	0x82, 0x07, 0xe9, 0x39, 0x3b, 0x84, 0xde, 0xc3, 0x60, 0x8c, 0x84, 0x35, 0x7c, 0x58, 0x0b, 0xbb,
+	0x5e, 0xfe, 0x01, 0x64, 0x82, 0x80, 0x81, 0xbb, 0x93, 0xbe, 0xdb, 0x24, 0x77, 0x6a, 0x04, 0x8f,
+	0x9e, 0xef, 0x4e, 0xd0, 0x73, 0x57, 0x44, 0xdc, 0x0d, 0x58, 0xdc, 0xd5, 0x1a, 0xda, 0x6d, 0x04,
+	0xc8, 0x87, 0xbd, 0x00, 0x20, 0xbd, 0xbe, 0x58, 0x90, 0x03, 0x84, 0x36, 0xcb, 0x6b, 0x8f, 0x3e,
+	0x5f, 0x5f, 0xf8, 0x14, 0xff, 0xbe, 0xfc, 0x7c, 0x3d, 0xf6, 0xe0, 0x8b, 0xf5, 0xd8, 0x23, 0xfc,
+	0xfb, 0x04, 0xff, 0xfe, 0x8e, 0x7f, 0x07, 0x69, 0xce, 0xc8, 0xde, 0xf8, 0x4f, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0x0e, 0xef, 0x48, 0x56, 0xe9, 0x1e, 0x00, 0x00,
 }

+ 23 - 0
vendor/src/github.com/docker/swarmkit/api/types.proto

@@ -521,6 +521,17 @@ message OrchestrationConfig {
 	// TaskHistoryRetentionLimit is the number of historic tasks to keep per instance or
 	// node. If negative, never remove completed or failed tasks.
 	int64 task_history_retention_limit = 1;
+
+}
+
+// TaskDefaults specifies default values for task creation.
+message TaskDefaults {
+	// LogDriver specifies the log driver to use for the cluster if not
+	// specified for each task.
+	//
+	// If this is changed, only new tasks will pick up the new log driver.
+	// Existing tasks will continue to use the previous default until rescheduled.
+	Driver log_driver = 1;
 }
 
 // DispatcherConfig defines cluster-level dispatcher settings.
@@ -554,6 +565,15 @@ message Placement {
 	repeated string constraints = 1;
 }
 
+// JoinToken contains the join tokens for workers and managers.
+message JoinTokens {
+	// Worker is the join token workers may use to join the swarm.
+	string worker = 1;
+
+	// Manager is the join token workers may use to join the swarm.
+	string manager = 2;
+}
+
 message RootCA {
 	// CAKey is the root CA private key.
 	bytes ca_key = 1 [(gogoproto.customname) = "CAKey"];
@@ -563,6 +583,9 @@ message RootCA {
 
 	// CACertHash is the digest of the CA Certificate.
 	string ca_cert_hash = 3 [(gogoproto.customname) = "CACertHash"];
+
+	// JoinTokens contains the join tokens for workers and managers.
+	JoinTokens join_tokens = 4 [(gogoproto.nullable) = false];
 }
 
 

+ 11 - 14
vendor/src/github.com/docker/swarmkit/ca/certificates.go

@@ -156,7 +156,7 @@ func (rca *RootCA) IssueAndSaveNewCertificates(paths CertPaths, cn, ou, org stri
 
 // RequestAndSaveNewCertificates gets new certificates issued, either by signing them locally if a signer is
 // available, or by requesting them from the remote server at remoteAddr.
-func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths CertPaths, role, secret string, picker *picker.Picker, transport credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) (*tls.Certificate, error) {
+func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths CertPaths, token string, picker *picker.Picker, transport credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) (*tls.Certificate, error) {
 	// Create a new key/pair and CSR for the new manager
 	// Write the new CSR and the new key to a temporary location so we can survive crashes on rotation
 	tempPaths := genTempPaths(paths)
@@ -171,7 +171,7 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths Cert
 	// responding properly (for example, it may have just been demoted).
 	var signedCert []byte
 	for i := 0; i != 5; i++ {
-		signedCert, err = GetRemoteSignedCertificate(ctx, csr, role, secret, rca.Pool, picker, transport, nodeInfo)
+		signedCert, err = GetRemoteSignedCertificate(ctx, csr, token, rca.Pool, picker, transport, nodeInfo)
 		if err == nil {
 			break
 		}
@@ -207,7 +207,9 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths Cert
 		return nil, err
 	}
 
-	log.Infof("Downloaded new TLS credentials with role: %s.", role)
+	if len(X509Cert.Subject.OrganizationalUnit) != 0 {
+		log.Infof("Downloaded new TLS credentials with role: %s.", X509Cert.Subject.OrganizationalUnit[0])
+	}
 
 	// Ensure directory exists
 	err = os.MkdirAll(filepath.Dir(paths.Cert), 0755)
@@ -480,7 +482,7 @@ func GetRemoteCA(ctx context.Context, d digest.Digest, picker *picker.Picker) (R
 		return RootCA{}, fmt.Errorf("failed to append certificate to cert pool")
 	}
 
-	return RootCA{Cert: response.Certificate, Pool: pool}, nil
+	return RootCA{Cert: response.Certificate, Digest: digest.FromBytes(response.Certificate), Pool: pool}, nil
 }
 
 // CreateAndWriteRootCA creates a Certificate authority for a new Swarm Cluster, potentially
@@ -595,9 +597,10 @@ func GenerateAndWriteNewKey(paths CertPaths) (csr, key []byte, err error) {
 	return
 }
 
-// GetRemoteSignedCertificate submits a CSR together with the intended role to a remote CA server address
-// available through a picker, and that is part of a CA identified by a specific certificate pool.
-func GetRemoteSignedCertificate(ctx context.Context, csr []byte, role, secret string, rootCAPool *x509.CertPool, picker *picker.Picker, creds credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) ([]byte, error) {
+// GetRemoteSignedCertificate submits a CSR to a remote CA server address
+// available through a picker, and that is part of a CA identified by a
+// specific certificate pool.
+func GetRemoteSignedCertificate(ctx context.Context, csr []byte, token string, rootCAPool *x509.CertPool, picker *picker.Picker, creds credentials.TransportAuthenticator, nodeInfo chan<- api.IssueNodeCertificateResponse) ([]byte, error) {
 	if rootCAPool == nil {
 		return nil, fmt.Errorf("valid root CA pool required")
 	}
@@ -630,14 +633,8 @@ func GetRemoteSignedCertificate(ctx context.Context, csr []byte, role, secret st
 	// Create a CAClient to retrieve a new Certificate
 	caClient := api.NewNodeCAClient(conn)
 
-	// Convert our internal string roles into an API role
-	apiRole, err := FormatRole(role)
-	if err != nil {
-		return nil, err
-	}
-
 	// Send the Request and retrieve the request token
-	issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Role: apiRole, Secret: secret}
+	issueRequest := &api.IssueNodeCertificateRequest{CSR: csr, Token: token}
 	issueResponse, err := caClient.IssueNodeCertificate(ctx, issueRequest)
 	if err != nil {
 		return nil, err

+ 45 - 9
vendor/src/github.com/docker/swarmkit/ca/config.go

@@ -1,11 +1,14 @@
 package ca
 
 import (
+	cryptorand "crypto/rand"
 	"crypto/tls"
 	"crypto/x509"
 	"encoding/pem"
+	"errors"
 	"fmt"
 	"io/ioutil"
+	"math/big"
 	"math/rand"
 	"path/filepath"
 	"strings"
@@ -28,9 +31,7 @@ const (
 	nodeTLSCertFilename = "swarm-node.crt"
 	nodeTLSKeyFilename  = "swarm-node.key"
 	nodeCSRFilename     = "swarm-node.csr"
-)
 
-const (
 	rootCN = "swarm-ca"
 	// ManagerRole represents the Manager node type, and is used for authorization to endpoints
 	ManagerRole = "swarm-manager"
@@ -38,6 +39,13 @@ const (
 	AgentRole = "swarm-worker"
 	// CARole represents the CA node type, and is used for clients attempting to get new certificates issued
 	CARole = "swarm-ca"
+
+	generatedSecretEntropyBytes = 16
+	joinTokenBase               = 36
+	// ceil(log(2^128-1, 36))
+	maxGeneratedSecretLength = 25
+	// ceil(log(2^256-1, 36))
+	base36DigestLen = 50
 )
 
 // SecurityConfig is used to represent a node's security configuration. It includes information about
@@ -148,10 +156,36 @@ func NewConfigPaths(baseCertDir string) *SecurityConfigPaths {
 	}
 }
 
+// GenerateJoinToken creates a new join token.
+func GenerateJoinToken(rootCA *RootCA) string {
+	var secretBytes [generatedSecretEntropyBytes]byte
+
+	if _, err := cryptorand.Read(secretBytes[:]); err != nil {
+		panic(fmt.Errorf("failed to read random bytes: %v", err))
+	}
+
+	var nn, digest big.Int
+	nn.SetBytes(secretBytes[:])
+	digest.SetString(rootCA.Digest.Hex(), 16)
+	return fmt.Sprintf("SWMTKN-1-%0[1]*s-%0[3]*s", base36DigestLen, digest.Text(joinTokenBase), maxGeneratedSecretLength, nn.Text(joinTokenBase))
+}
+
+func getCAHashFromToken(token string) (digest.Digest, error) {
+	split := strings.Split(token, "-")
+	if len(split) != 4 || split[0] != "SWMTKN" || split[1] != "1" {
+		return "", errors.New("invalid join token")
+	}
+
+	var digestInt big.Int
+	digestInt.SetString(split[2], joinTokenBase)
+
+	return digest.ParseDigest(fmt.Sprintf("sha256:%0[1]*s", 64, digestInt.Text(16)))
+}
+
 // LoadOrCreateSecurityConfig encapsulates the security logic behind joining a cluster.
 // Every node requires at least a set of TLS certificates with which to join the cluster with.
 // In the case of a manager, these certificates will be used both for client and server credentials.
-func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, caHash, secret, proposedRole string, picker *picker.Picker, nodeInfo chan<- api.IssueNodeCertificateResponse) (*SecurityConfig, error) {
+func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, token, proposedRole string, picker *picker.Picker, nodeInfo chan<- api.IssueNodeCertificateResponse) (*SecurityConfig, error) {
 	paths := NewConfigPaths(baseCertDir)
 
 	var (
@@ -171,9 +205,12 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, caHash, secret
 		// Get a digest for the optional CA hash string that we've been provided
 		// If we were provided a non-empty string, and it is an invalid hash, return
 		// otherwise, allow the invalid digest through.
-		d, err := digest.ParseDigest(caHash)
-		if err != nil && caHash != "" {
-			return nil, err
+		var d digest.Digest
+		if token != "" {
+			d, err = getCAHashFromToken(token)
+			if err != nil {
+				return nil, err
+			}
 		}
 
 		// Get the remote CA certificate, verify integrity with the
@@ -232,7 +269,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, caHash, secret
 		} else {
 			// There was an error loading our Credentials, let's get a new certificate issued
 			// Last argument is nil because at this point we don't have any valid TLS creds
-			tlsKeyPair, err = rootCA.RequestAndSaveNewCertificates(ctx, paths.Node, proposedRole, secret, picker, nil, nodeInfo)
+			tlsKeyPair, err = rootCA.RequestAndSaveNewCertificates(ctx, paths.Node, token, picker, nil, nodeInfo)
 			if err != nil {
 				return nil, err
 			}
@@ -304,11 +341,10 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string,
 			}
 			log.Infof("Renewing TLS Certificate.")
 
-			// Let's request new certs. Renewals don't require a secret.
+			// Let's request new certs. Renewals don't require a token.
 			rootCA := s.RootCA()
 			tlsKeyPair, err := rootCA.RequestAndSaveNewCertificates(ctx,
 				paths.Node,
-				s.ClientTLSCreds.Role(),
 				"",
 				picker,
 				s.ClientTLSCreds,

+ 41 - 96
vendor/src/github.com/docker/swarmkit/ca/server.go

@@ -2,9 +2,7 @@ package ca
 
 import (
 	"crypto/subtle"
-	"errors"
 	"fmt"
-	"strings"
 	"sync"
 
 	"github.com/Sirupsen/logrus"
@@ -14,7 +12,6 @@ import (
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/protobuf/ptypes"
-	"golang.org/x/crypto/bcrypt"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
@@ -25,35 +22,19 @@ import (
 // CA, NodeCA, and other hypothetical future CA services. At the moment,
 // breaking it apart doesn't seem worth it.
 type Server struct {
-	mu               sync.Mutex
-	wg               sync.WaitGroup
-	ctx              context.Context
-	cancel           func()
-	store            *store.MemoryStore
-	securityConfig   *SecurityConfig
-	acceptancePolicy *api.AcceptancePolicy
+	mu             sync.Mutex
+	wg             sync.WaitGroup
+	ctx            context.Context
+	cancel         func()
+	store          *store.MemoryStore
+	securityConfig *SecurityConfig
+	joinTokens     *api.JoinTokens
 
 	// Started is a channel which gets closed once the server is running
 	// and able to service RPCs.
 	started chan struct{}
 }
 
-// DefaultAcceptancePolicy returns the default acceptance policy.
-func DefaultAcceptancePolicy() api.AcceptancePolicy {
-	return api.AcceptancePolicy{
-		Policies: []*api.AcceptancePolicy_RoleAdmissionPolicy{
-			{
-				Role:       api.NodeRoleWorker,
-				Autoaccept: true,
-			},
-			{
-				Role:       api.NodeRoleManager,
-				Autoaccept: false,
-			},
-		},
-	}
-}
-
 // DefaultCAConfig returns the default CA Config, with a default expiration.
 func DefaultCAConfig() api.CAConfig {
 	return api.CAConfig{
@@ -154,14 +135,12 @@ func (s *Server) NodeCertificateStatus(ctx context.Context, request *api.NodeCer
 // IssueNodeCertificate is responsible for gatekeeping both certificate requests from new nodes in the swarm,
 // and authorizing certificate renewals.
 // If a node presented a valid certificate, the corresponding certificate is set in a RENEW state.
-// If a node failed to present a valid certificate, we enforce all the policies currently configured in
-// the swarm for node acceptance: check for the validity of the presented secret and check what is the
-// acceptance state the certificate should be put in (PENDING or ACCEPTED).
-// After going through the configured policies, a new random node ID is generated, and the corresponding node
-// entry is created. IssueNodeCertificate is the only place where new node entries to raft should be created.
+// If a node failed to present a valid certificate, we check for a valid join token and set the
+// role accordingly. A new random node ID is generated, and the corresponding node entry is created.
+// IssueNodeCertificate is the only place where new node entries to raft should be created.
 func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNodeCertificateRequest) (*api.IssueNodeCertificateResponse, error) {
-	// First, let's see if the remote node is proposing to be added as a valid node, and with a non-empty CSR
-	if len(request.CSR) == 0 || (request.Role != api.NodeRoleWorker && request.Role != api.NodeRoleManager) {
+	// First, let's see if the remote node is presenting a non-empty CSR
+	if len(request.CSR) == 0 {
 		return nil, grpc.Errorf(codes.InvalidArgument, codes.InvalidArgument.String())
 	}
 
@@ -184,23 +163,20 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
 		return s.issueRenewCertificate(ctx, nodeID, request.CSR)
 	}
 
-	// The remote node didn't successfully present a valid MTLS certificate, let's issue a PENDING
+	// The remote node didn't successfully present a valid MTLS certificate, let's issue a
 	// certificate with a new random ID
-	nodeMembership := api.NodeMembershipPending
-
-	// If there are acceptance policies configured in the system, we should enforce them
-	policy := s.getRolePolicy(request.Role)
-	if policy != nil {
-		// If the policy has a Secret set, let's verify it
-		if policy.Secret != nil {
-			if err := checkSecretValidity(policy, request.Secret); err != nil {
-				return nil, grpc.Errorf(codes.InvalidArgument, "A valid secret token is necessary to join this cluster: %v", err)
-			}
-		}
-		// Check to see if our autoacceptance policy allows this node to be issued without manual intervention
-		if policy.Autoaccept {
-			nodeMembership = api.NodeMembershipAccepted
-		}
+	role := api.NodeRole(-1)
+
+	s.mu.Lock()
+	if subtle.ConstantTimeCompare([]byte(s.joinTokens.Manager), []byte(request.Token)) == 1 {
+		role = api.NodeRoleManager
+	} else if subtle.ConstantTimeCompare([]byte(s.joinTokens.Worker), []byte(request.Token)) == 1 {
+		role = api.NodeRoleWorker
+	}
+	s.mu.Unlock()
+
+	if role < 0 {
+		return nil, grpc.Errorf(codes.InvalidArgument, "A valid join token is necessary to join this cluster")
 	}
 
 	// Max number of collisions of ID or CN to tolerate before giving up
@@ -216,14 +192,14 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
 				Certificate: api.Certificate{
 					CSR:  request.CSR,
 					CN:   nodeID,
-					Role: request.Role,
+					Role: role,
 					Status: api.IssuanceStatus{
 						State: api.IssuanceStatePending,
 					},
 				},
 				Spec: api.NodeSpec{
-					Role:       request.Role,
-					Membership: nodeMembership,
+					Role:       role,
+					Membership: api.NodeMembershipAccepted,
 				},
 			}
 
@@ -232,7 +208,7 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
 		if err == nil {
 			log.G(ctx).WithFields(logrus.Fields{
 				"node.id":   nodeID,
-				"node.role": request.Role,
+				"node.role": role,
 				"method":    "IssueNodeCertificate",
 			}).Debugf("new certificate entry added")
 			break
@@ -245,55 +221,17 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
 		}
 		log.G(ctx).WithFields(logrus.Fields{
 			"node.id":   nodeID,
-			"node.role": request.Role,
+			"node.role": role,
 			"method":    "IssueNodeCertificate",
 		}).Errorf("randomly generated node ID collided with an existing one - retrying")
 	}
 
 	return &api.IssueNodeCertificateResponse{
 		NodeID:         nodeID,
-		NodeMembership: nodeMembership,
+		NodeMembership: api.NodeMembershipAccepted,
 	}, nil
 }
 
-// checkSecretValidity verifies if a secret string matches the secret hash stored in the
-// Acceptance Policy. It currently only supports bcrypted hashes and plaintext.
-func checkSecretValidity(policy *api.AcceptancePolicy_RoleAdmissionPolicy, secret string) error {
-	if policy == nil || secret == "" {
-		return fmt.Errorf("invalid policy or secret")
-	}
-
-	switch strings.ToLower(policy.Secret.Alg) {
-	case "bcrypt":
-		return bcrypt.CompareHashAndPassword(policy.Secret.Data, []byte(secret))
-	case "plaintext":
-		if subtle.ConstantTimeCompare(policy.Secret.Data, []byte(secret)) == 1 {
-			return nil
-		}
-		return errors.New("incorrect secret")
-	}
-
-	return fmt.Errorf("hash algorithm not supported: %s", policy.Secret.Alg)
-}
-
-// getRolePolicy is a helper method that returns all the admission policies that should be
-// enforced for a particular role
-func (s *Server) getRolePolicy(role api.NodeRole) *api.AcceptancePolicy_RoleAdmissionPolicy {
-	s.mu.Lock()
-	defer s.mu.Unlock()
-
-	if s.acceptancePolicy != nil && len(s.acceptancePolicy.Policies) > 0 {
-		// Let's go through all the configured policies and try to find one for this role
-		for _, p := range s.acceptancePolicy.Policies {
-			if role == p.Role {
-				return p
-			}
-		}
-	}
-
-	return nil
-}
-
 // issueRenewCertificate receives a nodeID and a CSR and modifies the node's certificate entry with the new CSR
 // and changes the state to RENEW, so it can be picked up and signed by the signing reconciliation loop
 func (s *Server) issueRenewCertificate(ctx context.Context, nodeID string, csr []byte) (*api.IssueNodeCertificateResponse, error) {
@@ -365,11 +303,11 @@ func (s *Server) Run(ctx context.Context) error {
 		return fmt.Errorf("CA signer is already running")
 	}
 	s.wg.Add(1)
+	s.mu.Unlock()
+
 	defer s.wg.Done()
 	logger := log.G(ctx).WithField("module", "ca")
 	ctx = log.WithLogger(ctx, logger)
-	s.ctx, s.cancel = context.WithCancel(ctx)
-	s.mu.Unlock()
 
 	// Run() should never be called twice, but just in case, we're
 	// attempting to close the started channel in a safe way
@@ -402,6 +340,13 @@ func (s *Server) Run(ctx context.Context) error {
 		state.EventUpdateNode{},
 		state.EventUpdateCluster{},
 	)
+
+	// Do this after updateCluster has been called, so isRunning never
+	// returns true without joinTokens being set correctly.
+	s.mu.Lock()
+	s.ctx, s.cancel = context.WithCancel(ctx)
+	s.mu.Unlock()
+
 	if err != nil {
 		log.G(ctx).WithFields(logrus.Fields{
 			"method": "(*Server).Run",
@@ -497,7 +442,7 @@ func (s *Server) isRunning() bool {
 // always aware of changes in clusterExpiry and the Root CA key material
 func (s *Server) updateCluster(ctx context.Context, cluster *api.Cluster) {
 	s.mu.Lock()
-	s.acceptancePolicy = cluster.Spec.AcceptancePolicy.Copy()
+	s.joinTokens = cluster.RootCA.JoinTokens.Copy()
 	s.mu.Unlock()
 	var err error
 

+ 8 - 0
vendor/src/github.com/docker/swarmkit/manager/controlapi/cluster.go

@@ -97,6 +97,13 @@ func (s *Server) UpdateCluster(ctx context.Context, request *api.UpdateClusterRe
 		}
 		cluster.Meta.Version = *request.ClusterVersion
 		cluster.Spec = *request.Spec.Copy()
+
+		if request.Rotation.RotateWorkerToken {
+			cluster.RootCA.JoinTokens.Worker = ca.GenerateJoinToken(s.rootCA)
+		}
+		if request.Rotation.RotateManagerToken {
+			cluster.RootCA.JoinTokens.Manager = ca.GenerateJoinToken(s.rootCA)
+		}
 		return store.UpdateCluster(tx, cluster)
 	})
 	if err != nil {
@@ -193,6 +200,7 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster {
 			RootCA: api.RootCA{
 				CACert:     cluster.RootCA.CACert,
 				CACertHash: cluster.RootCA.CACertHash,
+				JoinTokens: cluster.RootCA.JoinTokens,
 			},
 		}
 

+ 8 - 5
vendor/src/github.com/docker/swarmkit/manager/controlapi/server.go

@@ -3,6 +3,7 @@ package controlapi
 import (
 	"errors"
 
+	"github.com/docker/swarmkit/ca"
 	"github.com/docker/swarmkit/manager/state/raft"
 	"github.com/docker/swarmkit/manager/state/store"
 )
@@ -14,14 +15,16 @@ var (
 
 // Server is the Cluster API gRPC server.
 type Server struct {
-	store *store.MemoryStore
-	raft  *raft.Node
+	store  *store.MemoryStore
+	raft   *raft.Node
+	rootCA *ca.RootCA
 }
 
 // NewServer creates a Cluster API server.
-func NewServer(store *store.MemoryStore, raft *raft.Node) *Server {
+func NewServer(store *store.MemoryStore, raft *raft.Node, rootCA *ca.RootCA) *Server {
 	return &Server{
-		store: store,
-		raft:  raft,
+		store:  store,
+		raft:   raft,
+		rootCA: rootCA,
 	}
 }

+ 11 - 1
vendor/src/github.com/docker/swarmkit/manager/keymanager/keymanager.go

@@ -7,6 +7,7 @@ package keymanager
 // plane information. It can also be used to encrypt overlay data traffic.
 import (
 	"crypto/rand"
+	"encoding/binary"
 	"fmt"
 	"sync"
 	"time"
@@ -87,7 +88,7 @@ func New(store *store.MemoryStore, config *Config) *KeyManager {
 	return &KeyManager{
 		config:  config,
 		store:   store,
-		keyRing: &keyRing{},
+		keyRing: &keyRing{lClock: genSkew()},
 	}
 }
 
@@ -230,3 +231,12 @@ func (k *KeyManager) Stop() error {
 	k.cancel()
 	return nil
 }
+
+// genSkew generates a random uint64 number between 0 and 65535
+func genSkew() uint64 {
+	b := make([]byte, 2)
+	if _, err := rand.Read(b); err != nil {
+		panic(err)
+	}
+	return uint64(binary.BigEndian.Uint16(b))
+}

+ 5 - 2
vendor/src/github.com/docker/swarmkit/manager/manager.go

@@ -301,7 +301,6 @@ func (m *Manager) Run(parent context.Context) error {
 							Annotations: api.Annotations{
 								Name: store.DefaultClusterName,
 							},
-							AcceptancePolicy: ca.DefaultAcceptancePolicy(),
 							Orchestration: api.OrchestrationConfig{
 								TaskHistoryRetentionLimit: defaultTaskHistoryRetentionLimit,
 							},
@@ -315,6 +314,10 @@ func (m *Manager) Run(parent context.Context) error {
 							CAKey:      rootCA.Key,
 							CACert:     rootCA.Cert,
 							CACertHash: rootCA.Digest.String(),
+							JoinTokens: api.JoinTokens{
+								Worker:  ca.GenerateJoinToken(rootCA),
+								Manager: ca.GenerateJoinToken(rootCA),
+							},
 						},
 					})
 					// Add Node entry for ourself, if one
@@ -449,7 +452,7 @@ func (m *Manager) Run(parent context.Context) error {
 		return err
 	}
 
-	baseControlAPI := controlapi.NewServer(m.RaftNode.MemoryStore(), m.RaftNode)
+	baseControlAPI := controlapi.NewServer(m.RaftNode.MemoryStore(), m.RaftNode, m.config.SecurityConfig.RootCA())
 	healthServer := health.NewHealthServer()
 
 	authenticatedControlAPI := api.NewAuthenticatedWrapperControlServer(baseControlAPI, authorize)

+ 1 - 1
vendor/src/github.com/docker/swarmkit/manager/orchestrator/replicated.go

@@ -111,7 +111,7 @@ func newTask(cluster *api.Cluster, service *api.Service, instance uint64) *api.T
 		logDriver = service.Spec.Task.LogDriver
 	} else if cluster != nil {
 		// pick up the cluster default, if available.
-		logDriver = cluster.Spec.DefaultLogDriver // nil is okay here.
+		logDriver = cluster.Spec.TaskDefaults.LogDriver // nil is okay here.
 	}
 
 	// NOTE(stevvooe): For now, we don't override the container naming and

+ 0 - 35
vendor/src/golang.org/x/crypto/bcrypt/base64.go

@@ -1,35 +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 bcrypt
-
-import "encoding/base64"
-
-const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
-
-var bcEncoding = base64.NewEncoding(alphabet)
-
-func base64Encode(src []byte) []byte {
-	n := bcEncoding.EncodedLen(len(src))
-	dst := make([]byte, n)
-	bcEncoding.Encode(dst, src)
-	for dst[n-1] == '=' {
-		n--
-	}
-	return dst[:n]
-}
-
-func base64Decode(src []byte) ([]byte, error) {
-	numOfEquals := 4 - (len(src) % 4)
-	for i := 0; i < numOfEquals; i++ {
-		src = append(src, '=')
-	}
-
-	dst := make([]byte, bcEncoding.DecodedLen(len(src)))
-	n, err := bcEncoding.Decode(dst, src)
-	if err != nil {
-		return nil, err
-	}
-	return dst[:n], nil
-}

+ 0 - 294
vendor/src/golang.org/x/crypto/bcrypt/bcrypt.go

@@ -1,294 +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 bcrypt implements Provos and Mazières's bcrypt adaptive hashing
-// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
-package bcrypt // import "golang.org/x/crypto/bcrypt"
-
-// The code is a port of Provos and Mazières's C implementation.
-import (
-	"crypto/rand"
-	"crypto/subtle"
-	"errors"
-	"fmt"
-	"golang.org/x/crypto/blowfish"
-	"io"
-	"strconv"
-)
-
-const (
-	MinCost     int = 4  // the minimum allowable cost as passed in to GenerateFromPassword
-	MaxCost     int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
-	DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
-)
-
-// The error returned from CompareHashAndPassword when a password and hash do
-// not match.
-var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password")
-
-// The error returned from CompareHashAndPassword when a hash is too short to
-// be a bcrypt hash.
-var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
-
-// The error returned from CompareHashAndPassword when a hash was created with
-// a bcrypt algorithm newer than this implementation.
-type HashVersionTooNewError byte
-
-func (hv HashVersionTooNewError) Error() string {
-	return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
-}
-
-// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
-type InvalidHashPrefixError byte
-
-func (ih InvalidHashPrefixError) Error() string {
-	return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
-}
-
-type InvalidCostError int
-
-func (ic InvalidCostError) Error() string {
-	return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
-}
-
-const (
-	majorVersion       = '2'
-	minorVersion       = 'a'
-	maxSaltSize        = 16
-	maxCryptedHashSize = 23
-	encodedSaltSize    = 22
-	encodedHashSize    = 31
-	minHashSize        = 59
-)
-
-// magicCipherData is an IV for the 64 Blowfish encryption calls in
-// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
-var magicCipherData = []byte{
-	0x4f, 0x72, 0x70, 0x68,
-	0x65, 0x61, 0x6e, 0x42,
-	0x65, 0x68, 0x6f, 0x6c,
-	0x64, 0x65, 0x72, 0x53,
-	0x63, 0x72, 0x79, 0x44,
-	0x6f, 0x75, 0x62, 0x74,
-}
-
-type hashed struct {
-	hash  []byte
-	salt  []byte
-	cost  int // allowed range is MinCost to MaxCost
-	major byte
-	minor byte
-}
-
-// GenerateFromPassword returns the bcrypt hash of the password at the given
-// cost. If the cost given is less than MinCost, the cost will be set to
-// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package,
-// to compare the returned hashed password with its cleartext version.
-func GenerateFromPassword(password []byte, cost int) ([]byte, error) {
-	p, err := newFromPassword(password, cost)
-	if err != nil {
-		return nil, err
-	}
-	return p.Hash(), nil
-}
-
-// CompareHashAndPassword compares a bcrypt hashed password with its possible
-// plaintext equivalent. Returns nil on success, or an error on failure.
-func CompareHashAndPassword(hashedPassword, password []byte) error {
-	p, err := newFromHash(hashedPassword)
-	if err != nil {
-		return err
-	}
-
-	otherHash, err := bcrypt(password, p.cost, p.salt)
-	if err != nil {
-		return err
-	}
-
-	otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
-	if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
-		return nil
-	}
-
-	return ErrMismatchedHashAndPassword
-}
-
-// Cost returns the hashing cost used to create the given hashed
-// password. When, in the future, the hashing cost of a password system needs
-// to be increased in order to adjust for greater computational power, this
-// function allows one to establish which passwords need to be updated.
-func Cost(hashedPassword []byte) (int, error) {
-	p, err := newFromHash(hashedPassword)
-	if err != nil {
-		return 0, err
-	}
-	return p.cost, nil
-}
-
-func newFromPassword(password []byte, cost int) (*hashed, error) {
-	if cost < MinCost {
-		cost = DefaultCost
-	}
-	p := new(hashed)
-	p.major = majorVersion
-	p.minor = minorVersion
-
-	err := checkCost(cost)
-	if err != nil {
-		return nil, err
-	}
-	p.cost = cost
-
-	unencodedSalt := make([]byte, maxSaltSize)
-	_, err = io.ReadFull(rand.Reader, unencodedSalt)
-	if err != nil {
-		return nil, err
-	}
-
-	p.salt = base64Encode(unencodedSalt)
-	hash, err := bcrypt(password, p.cost, p.salt)
-	if err != nil {
-		return nil, err
-	}
-	p.hash = hash
-	return p, err
-}
-
-func newFromHash(hashedSecret []byte) (*hashed, error) {
-	if len(hashedSecret) < minHashSize {
-		return nil, ErrHashTooShort
-	}
-	p := new(hashed)
-	n, err := p.decodeVersion(hashedSecret)
-	if err != nil {
-		return nil, err
-	}
-	hashedSecret = hashedSecret[n:]
-	n, err = p.decodeCost(hashedSecret)
-	if err != nil {
-		return nil, err
-	}
-	hashedSecret = hashedSecret[n:]
-
-	// The "+2" is here because we'll have to append at most 2 '=' to the salt
-	// when base64 decoding it in expensiveBlowfishSetup().
-	p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
-	copy(p.salt, hashedSecret[:encodedSaltSize])
-
-	hashedSecret = hashedSecret[encodedSaltSize:]
-	p.hash = make([]byte, len(hashedSecret))
-	copy(p.hash, hashedSecret)
-
-	return p, nil
-}
-
-func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) {
-	cipherData := make([]byte, len(magicCipherData))
-	copy(cipherData, magicCipherData)
-
-	c, err := expensiveBlowfishSetup(password, uint32(cost), salt)
-	if err != nil {
-		return nil, err
-	}
-
-	for i := 0; i < 24; i += 8 {
-		for j := 0; j < 64; j++ {
-			c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
-		}
-	}
-
-	// Bug compatibility with C bcrypt implementations. We only encode 23 of
-	// the 24 bytes encrypted.
-	hsh := base64Encode(cipherData[:maxCryptedHashSize])
-	return hsh, nil
-}
-
-func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) {
-
-	csalt, err := base64Decode(salt)
-	if err != nil {
-		return nil, err
-	}
-
-	// Bug compatibility with C bcrypt implementations. They use the trailing
-	// NULL in the key string during expansion.
-	ckey := append(key, 0)
-
-	c, err := blowfish.NewSaltedCipher(ckey, csalt)
-	if err != nil {
-		return nil, err
-	}
-
-	var i, rounds uint64
-	rounds = 1 << cost
-	for i = 0; i < rounds; i++ {
-		blowfish.ExpandKey(ckey, c)
-		blowfish.ExpandKey(csalt, c)
-	}
-
-	return c, nil
-}
-
-func (p *hashed) Hash() []byte {
-	arr := make([]byte, 60)
-	arr[0] = '$'
-	arr[1] = p.major
-	n := 2
-	if p.minor != 0 {
-		arr[2] = p.minor
-		n = 3
-	}
-	arr[n] = '$'
-	n += 1
-	copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
-	n += 2
-	arr[n] = '$'
-	n += 1
-	copy(arr[n:], p.salt)
-	n += encodedSaltSize
-	copy(arr[n:], p.hash)
-	n += encodedHashSize
-	return arr[:n]
-}
-
-func (p *hashed) decodeVersion(sbytes []byte) (int, error) {
-	if sbytes[0] != '$' {
-		return -1, InvalidHashPrefixError(sbytes[0])
-	}
-	if sbytes[1] > majorVersion {
-		return -1, HashVersionTooNewError(sbytes[1])
-	}
-	p.major = sbytes[1]
-	n := 3
-	if sbytes[2] != '$' {
-		p.minor = sbytes[2]
-		n++
-	}
-	return n, nil
-}
-
-// sbytes should begin where decodeVersion left off.
-func (p *hashed) decodeCost(sbytes []byte) (int, error) {
-	cost, err := strconv.Atoi(string(sbytes[0:2]))
-	if err != nil {
-		return -1, err
-	}
-	err = checkCost(cost)
-	if err != nil {
-		return -1, err
-	}
-	p.cost = cost
-	return 3, nil
-}
-
-func (p *hashed) String() string {
-	return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
-}
-
-func checkCost(cost int) error {
-	if cost < MinCost || cost > MaxCost {
-		return InvalidCostError(cost)
-	}
-	return nil
-}

+ 0 - 159
vendor/src/golang.org/x/crypto/blowfish/block.go

@@ -1,159 +0,0 @@
-// Copyright 2010 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 blowfish
-
-// getNextWord returns the next big-endian uint32 value from the byte slice
-// at the given position in a circular manner, updating the position.
-func getNextWord(b []byte, pos *int) uint32 {
-	var w uint32
-	j := *pos
-	for i := 0; i < 4; i++ {
-		w = w<<8 | uint32(b[j])
-		j++
-		if j >= len(b) {
-			j = 0
-		}
-	}
-	*pos = j
-	return w
-}
-
-// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
-// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
-// pi and substitution tables for calls to Encrypt. This is used, primarily,
-// by the bcrypt package to reuse the Blowfish key schedule during its
-// set up. It's unlikely that you need to use this directly.
-func ExpandKey(key []byte, c *Cipher) {
-	j := 0
-	for i := 0; i < 18; i++ {
-		// Using inlined getNextWord for performance.
-		var d uint32
-		for k := 0; k < 4; k++ {
-			d = d<<8 | uint32(key[j])
-			j++
-			if j >= len(key) {
-				j = 0
-			}
-		}
-		c.p[i] ^= d
-	}
-
-	var l, r uint32
-	for i := 0; i < 18; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.p[i], c.p[i+1] = l, r
-	}
-
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s0[i], c.s0[i+1] = l, r
-	}
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s1[i], c.s1[i+1] = l, r
-	}
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s2[i], c.s2[i+1] = l, r
-	}
-	for i := 0; i < 256; i += 2 {
-		l, r = encryptBlock(l, r, c)
-		c.s3[i], c.s3[i+1] = l, r
-	}
-}
-
-// This is similar to ExpandKey, but folds the salt during the key
-// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
-// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
-// and specializing it here is useful.
-func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
-	j := 0
-	for i := 0; i < 18; i++ {
-		c.p[i] ^= getNextWord(key, &j)
-	}
-
-	j = 0
-	var l, r uint32
-	for i := 0; i < 18; i += 2 {
-		l ^= getNextWord(salt, &j)
-		r ^= getNextWord(salt, &j)
-		l, r = encryptBlock(l, r, c)
-		c.p[i], c.p[i+1] = l, r
-	}
-
-	for i := 0; i < 256; i += 2 {
-		l ^= getNextWord(salt, &j)
-		r ^= getNextWord(salt, &j)
-		l, r = encryptBlock(l, r, c)
-		c.s0[i], c.s0[i+1] = l, r
-	}
-
-	for i := 0; i < 256; i += 2 {
-		l ^= getNextWord(salt, &j)
-		r ^= getNextWord(salt, &j)
-		l, r = encryptBlock(l, r, c)
-		c.s1[i], c.s1[i+1] = l, r
-	}
-
-	for i := 0; i < 256; i += 2 {
-		l ^= getNextWord(salt, &j)
-		r ^= getNextWord(salt, &j)
-		l, r = encryptBlock(l, r, c)
-		c.s2[i], c.s2[i+1] = l, r
-	}
-
-	for i := 0; i < 256; i += 2 {
-		l ^= getNextWord(salt, &j)
-		r ^= getNextWord(salt, &j)
-		l, r = encryptBlock(l, r, c)
-		c.s3[i], c.s3[i+1] = l, r
-	}
-}
-
-func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
-	xl, xr := l, r
-	xl ^= c.p[0]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
-	xr ^= c.p[17]
-	return xr, xl
-}
-
-func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
-	xl, xr := l, r
-	xl ^= c.p[17]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
-	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
-	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
-	xr ^= c.p[0]
-	return xr, xl
-}

+ 0 - 91
vendor/src/golang.org/x/crypto/blowfish/cipher.go

@@ -1,91 +0,0 @@
-// Copyright 2010 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 blowfish implements Bruce Schneier's Blowfish encryption algorithm.
-package blowfish // import "golang.org/x/crypto/blowfish"
-
-// The code is a port of Bruce Schneier's C implementation.
-// See http://www.schneier.com/blowfish.html.
-
-import "strconv"
-
-// The Blowfish block size in bytes.
-const BlockSize = 8
-
-// A Cipher is an instance of Blowfish encryption using a particular key.
-type Cipher struct {
-	p              [18]uint32
-	s0, s1, s2, s3 [256]uint32
-}
-
-type KeySizeError int
-
-func (k KeySizeError) Error() string {
-	return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
-}
-
-// NewCipher creates and returns a Cipher.
-// The key argument should be the Blowfish key, from 1 to 56 bytes.
-func NewCipher(key []byte) (*Cipher, error) {
-	var result Cipher
-	if k := len(key); k < 1 || k > 56 {
-		return nil, KeySizeError(k)
-	}
-	initCipher(&result)
-	ExpandKey(key, &result)
-	return &result, nil
-}
-
-// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
-// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
-// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
-// bytes.
-func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
-	if len(salt) == 0 {
-		return NewCipher(key)
-	}
-	var result Cipher
-	if k := len(key); k < 1 {
-		return nil, KeySizeError(k)
-	}
-	initCipher(&result)
-	expandKeyWithSalt(key, salt, &result)
-	return &result, nil
-}
-
-// BlockSize returns the Blowfish block size, 8 bytes.
-// It is necessary to satisfy the Block interface in the
-// package "crypto/cipher".
-func (c *Cipher) BlockSize() int { return BlockSize }
-
-// Encrypt encrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-// Note that for amounts of data larger than a block,
-// it is not safe to just call Encrypt on successive blocks;
-// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
-func (c *Cipher) Encrypt(dst, src []byte) {
-	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-	l, r = encryptBlock(l, r, c)
-	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
-	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-// Decrypt decrypts the 8-byte buffer src using the key k
-// and stores the result in dst.
-func (c *Cipher) Decrypt(dst, src []byte) {
-	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
-	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
-	l, r = decryptBlock(l, r, c)
-	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
-	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
-}
-
-func initCipher(c *Cipher) {
-	copy(c.p[0:], p[0:])
-	copy(c.s0[0:], s0[0:])
-	copy(c.s1[0:], s1[0:])
-	copy(c.s2[0:], s2[0:])
-	copy(c.s3[0:], s3[0:])
-}

+ 0 - 199
vendor/src/golang.org/x/crypto/blowfish/const.go

@@ -1,199 +0,0 @@
-// Copyright 2010 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.
-
-// The startup permutation array and substitution boxes.
-// They are the hexadecimal digits of PI; see:
-// http://www.schneier.com/code/constants.txt.
-
-package blowfish
-
-var s0 = [256]uint32{
-	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
-	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
-	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
-	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
-	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
-	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
-	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
-	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
-	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
-	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
-	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
-	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
-	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
-	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
-	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
-	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
-	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
-	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
-	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
-	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
-	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
-	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
-	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
-	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
-	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
-	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
-	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
-	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
-	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
-	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
-	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
-	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
-	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
-	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
-	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
-	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
-	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
-	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
-	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
-	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
-	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
-	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
-	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
-}
-
-var s1 = [256]uint32{
-	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
-	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
-	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
-	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
-	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
-	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
-	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
-	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
-	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
-	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
-	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
-	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
-	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
-	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
-	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
-	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
-	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
-	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
-	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
-	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
-	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
-	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
-	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
-	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
-	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
-	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
-	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
-	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
-	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
-	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
-	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
-	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
-	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
-	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
-	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
-	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
-	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
-	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
-	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
-	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
-	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
-	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
-	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
-}
-
-var s2 = [256]uint32{
-	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
-	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
-	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
-	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
-	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
-	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
-	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
-	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
-	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
-	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
-	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
-	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
-	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
-	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
-	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
-	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
-	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
-	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
-	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
-	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
-	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
-	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
-	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
-	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
-	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
-	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
-	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
-	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
-	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
-	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
-	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
-	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
-	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
-	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
-	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
-	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
-	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
-	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
-	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
-	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
-	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
-	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
-	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
-}
-
-var s3 = [256]uint32{
-	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
-	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
-	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
-	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
-	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
-	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
-	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
-	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
-	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
-	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
-	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
-	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
-	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
-	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
-	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
-	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
-	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
-	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
-	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
-	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
-	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
-	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
-	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
-	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
-	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
-	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
-	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
-	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
-	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
-	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
-	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
-	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
-	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
-	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
-	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
-	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
-	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
-	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
-	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
-	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
-	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
-	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
-	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
-}
-
-var p = [18]uint32{
-	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
-	0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
-	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
-}