瀏覽代碼

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(
 	cmd.AddCommand(
-		newAcceptCommand(dockerCli),
 		newDemoteCommand(dockerCli),
 		newDemoteCommand(dockerCli),
 		newInspectCommand(dockerCli),
 		newInspectCommand(dockerCli),
 		newListCommand(dockerCli),
 		newListCommand(dockerCli),

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

@@ -16,7 +16,7 @@ import (
 )
 )
 
 
 const (
 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 {
 type listOptions struct {
@@ -74,11 +74,10 @@ func printTable(out io.Writer, nodes []swarm.Node, info types.Info) {
 	// Ignore flushing errors
 	// Ignore flushing errors
 	defer writer.Flush()
 	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 {
 	for _, node := range nodes {
 		name := node.Description.Hostname
 		name := node.Description.Hostname
 		availability := string(node.Spec.Availability)
 		availability := string(node.Spec.Availability)
-		membership := string(node.Spec.Membership)
 
 
 		reachability := ""
 		reachability := ""
 		if node.ManagerStatus != nil {
 		if node.ManagerStatus != nil {
@@ -99,7 +98,6 @@ func printTable(out io.Writer, nodes []swarm.Node, info types.Info) {
 			listItemFmt,
 			listItemFmt,
 			ID,
 			ID,
 			name,
 			name,
-			client.PrettyPrint(membership),
 			client.PrettyPrint(string(node.Status.State)),
 			client.PrettyPrint(string(node.Status.State)),
 			client.PrettyPrint(availability),
 			client.PrettyPrint(availability),
 			client.PrettyPrint(reachability))
 			client.PrettyPrint(reachability))

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

@@ -12,7 +12,6 @@ import (
 type nodeOptions struct {
 type nodeOptions struct {
 	annotations
 	annotations
 	role         string
 	role         string
-	membership   string
 	availability 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)
 		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)) {
 	switch swarm.NodeAvailability(strings.ToLower(opts.availability)) {
 	case swarm.NodeAvailabilityActive:
 	case swarm.NodeAvailabilityActive:
 		spec.Availability = 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 := cmd.Flags()
 	flags.StringVar(&nodeOpts.role, flagRole, "", "Role of the node (worker/manager)")
 	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.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)")
 	flags.Var(&nodeOpts.annotations.labels, flagLabelAdd, "Add or update a node label (key=value)")
 	labelKeys := opts.NewListOpts(nil)
 	labelKeys := opts.NewListOpts(nil)
@@ -76,13 +75,6 @@ func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) error {
 			}
 			}
 			spec.Role = swarm.NodeRole(str)
 			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) {
 		if flags.Changed(flagAvailability) {
 			str, err := flags.GetString(flagAvailability)
 			str, err := flags.GetString(flagAvailability)
 			if err != nil {
 			if err != nil {
@@ -115,7 +107,6 @@ func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) error {
 
 
 const (
 const (
 	flagRole         = "role"
 	flagRole         = "role"
-	flagMembership   = "membership"
 	flagAvailability = "availability"
 	flagAvailability = "availability"
 	flagLabelAdd     = "label-add"
 	flagLabelAdd     = "label-add"
 	flagLabelRemove  = "label-rm"
 	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.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.StringVar(&opts.logDriver.name, flagLogDriver, "", "Logging driver for service")
 	flags.Var(&opts.logDriver.opts, flagLogOpt, "Logging driver options")
 	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),
 		newUpdateCommand(dockerCli),
 		newLeaveCommand(dockerCli),
 		newLeaveCommand(dockerCli),
 		newInspectCommand(dockerCli),
 		newInspectCommand(dockerCli),
+		newJoinTokenCommand(dockerCli),
 	)
 	)
 	return cmd
 	return cmd
 }
 }

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

@@ -28,14 +28,11 @@ type initOptions struct {
 func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
 func newInitCommand(dockerCli *client.DockerCli) *cobra.Command {
 	opts := initOptions{
 	opts := initOptions{
 		listenAddr: NewListenAddrOption(),
 		listenAddr: NewListenAddrOption(),
-		swarmOptions: swarmOptions{
-			autoAccept: NewAutoAcceptOption(),
-		},
 	}
 	}
 
 
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
 		Use:   "init [OPTIONS]",
 		Use:   "init [OPTIONS]",
-		Short: "Initialize a Swarm",
+		Short: "Initialize a swarm",
 		Args:  cli.NoArgs,
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runInit(dockerCli, cmd.Flags(), opts)
 			return runInit(dockerCli, cmd.Flags(), opts)
@@ -53,12 +50,6 @@ func runInit(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts initOptions
 	client := dockerCli.Client()
 	client := dockerCli.Client()
 	ctx := context.Background()
 	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{
 	req := swarm.InitRequest{
 		ListenAddr:      opts.listenAddr.String(),
 		ListenAddr:      opts.listenAddr.String(),
 		ForceNewCluster: opts.forceNewCluster,
 		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)
 	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{
 	cmd := &cobra.Command{
 		Use:   "inspect [OPTIONS]",
 		Use:   "inspect [OPTIONS]",
-		Short: "Inspect the Swarm",
+		Short: "Inspect the swarm",
 		Args:  cli.NoArgs,
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runInspect(dockerCli, opts)
 			return runInspect(dockerCli, opts)

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

@@ -2,6 +2,7 @@ package swarm
 
 
 import (
 import (
 	"fmt"
 	"fmt"
+	"strings"
 
 
 	"github.com/docker/docker/api/client"
 	"github.com/docker/docker/api/client"
 	"github.com/docker/docker/cli"
 	"github.com/docker/docker/cli"
@@ -13,9 +14,7 @@ import (
 type joinOptions struct {
 type joinOptions struct {
 	remote     string
 	remote     string
 	listenAddr NodeAddrOption
 	listenAddr NodeAddrOption
-	manager    bool
-	secret     string
-	CACertHash string
+	token      string
 }
 }
 
 
 func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
 func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
@@ -25,7 +24,7 @@ func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
 
 
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
 		Use:   "join [OPTIONS] HOST:PORT",
 		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),
 		Args:  cli.ExactArgs(1),
 		RunE: func(cmd *cobra.Command, args []string) error {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			opts.remote = args[0]
 			opts.remote = args[0]
@@ -35,9 +34,7 @@ func newJoinCommand(dockerCli *client.DockerCli) *cobra.Command {
 
 
 	flags := cmd.Flags()
 	flags := cmd.Flags()
 	flags.Var(&opts.listenAddr, flagListenAddr, "Listen address")
 	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
 	return cmd
 }
 }
 
 
@@ -46,20 +43,29 @@ func runJoin(dockerCli *client.DockerCli, opts joinOptions) error {
 	ctx := context.Background()
 	ctx := context.Background()
 
 
 	req := swarm.JoinRequest{
 	req := swarm.JoinRequest{
-		Manager:     opts.manager,
-		Secret:      opts.secret,
+		JoinToken:   opts.token,
 		ListenAddr:  opts.listenAddr.String(),
 		ListenAddr:  opts.listenAddr.String(),
 		RemoteAddrs: []string{opts.remote},
 		RemoteAddrs: []string{opts.remote},
-		CACertHash:  opts.CACertHash,
 	}
 	}
 	err := client.SwarmJoin(ctx, req)
 	err := client.SwarmJoin(ctx, req)
 	if err != nil {
 	if err != nil {
 		return err
 		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 {
 	} 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
 	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{
 	cmd := &cobra.Command{
 		Use:   "leave [OPTIONS]",
 		Use:   "leave [OPTIONS]",
-		Short: "Leave a Swarm",
+		Short: "Leave a swarm",
 		Args:  cli.NoArgs,
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runLeave(dockerCli, opts)
 			return runLeave(dockerCli, opts)

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

@@ -15,29 +15,15 @@ import (
 const (
 const (
 	defaultListenAddr = "0.0.0.0:2377"
 	defaultListenAddr = "0.0.0.0:2377"
 
 
-	worker  = "WORKER"
-	manager = "MANAGER"
-	none    = "NONE"
-
-	flagAutoAccept          = "auto-accept"
 	flagCertExpiry          = "cert-expiry"
 	flagCertExpiry          = "cert-expiry"
 	flagDispatcherHeartbeat = "dispatcher-heartbeat"
 	flagDispatcherHeartbeat = "dispatcher-heartbeat"
 	flagListenAddr          = "listen-addr"
 	flagListenAddr          = "listen-addr"
-	flagSecret              = "secret"
+	flagToken               = "token"
 	flagTaskHistoryLimit    = "task-history-limit"
 	flagTaskHistoryLimit    = "task-history-limit"
 	flagExternalCA          = "external-ca"
 	flagExternalCA          = "external-ca"
 )
 )
 
 
-var (
-	defaultPolicies = []swarm.Policy{
-		{Role: worker, Autoaccept: true},
-		{Role: manager, Autoaccept: false},
-	}
-)
-
 type swarmOptions struct {
 type swarmOptions struct {
-	autoAccept          AutoAcceptOption
-	secret              string
 	taskHistoryLimit    int64
 	taskHistoryLimit    int64
 	dispatcherHeartbeat time.Duration
 	dispatcherHeartbeat time.Duration
 	nodeCertExpiry      time.Duration
 	nodeCertExpiry      time.Duration
@@ -84,71 +70,6 @@ func NewListenAddrOption() NodeAddrOption {
 	return NewNodeAddrOption(defaultListenAddr)
 	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.
 // ExternalCAOption is a Value type for parsing external CA specifications.
 type ExternalCAOption struct {
 type ExternalCAOption struct {
 	values []*swarm.ExternalCA
 	values []*swarm.ExternalCA
@@ -239,8 +160,6 @@ func parseExternalCA(caSpec string) (*swarm.ExternalCA, error) {
 }
 }
 
 
 func addSwarmFlags(flags *pflag.FlagSet, opts *swarmOptions) {
 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.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.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")
 	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 {
 func (opts *swarmOptions) ToSpec() swarm.Spec {
 	spec := 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.Orchestration.TaskHistoryRetentionLimit = opts.taskHistoryLimit
 	spec.Dispatcher.HeartbeatPeriod = uint64(opts.dispatcherHeartbeat.Nanoseconds())
 	spec.Dispatcher.HeartbeatPeriod = uint64(opts.dispatcherHeartbeat.Nanoseconds())
 	spec.CAConfig.NodeCertExpiry = opts.nodeCertExpiry
 	spec.CAConfig.NodeCertExpiry = opts.nodeCertExpiry

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

@@ -4,7 +4,6 @@ import (
 	"testing"
 	"testing"
 
 
 	"github.com/docker/docker/pkg/testutil/assert"
 	"github.com/docker/docker/pkg/testutil/assert"
-	"github.com/docker/engine-api/types/swarm"
 )
 )
 
 
 func TestNodeAddrOptionSetHostAndPort(t *testing.T) {
 func TestNodeAddrOptionSetHostAndPort(t *testing.T) {
@@ -36,101 +35,3 @@ func TestNodeAddrOptionSetInvalidFormat(t *testing.T) {
 	opt := NewListenAddrOption()
 	opt := NewListenAddrOption()
 	assert.Error(t, opt.Set("http://localhost:4545"), "Invalid")
 	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 {
 func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
-	opts := swarmOptions{autoAccept: NewAutoAcceptOption()}
+	opts := swarmOptions{}
 
 
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
 		Use:   "update [OPTIONS]",
 		Use:   "update [OPTIONS]",
-		Short: "Update the Swarm",
+		Short: "Update the swarm",
 		Args:  cli.NoArgs,
 		Args:  cli.NoArgs,
 		RunE: func(cmd *cobra.Command, args []string) error {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			return runUpdate(dockerCli, cmd.Flags(), opts)
 			return runUpdate(dockerCli, cmd.Flags(), opts)
@@ -32,6 +32,8 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts swarmOpti
 	client := dockerCli.Client()
 	client := dockerCli.Client()
 	ctx := context.Background()
 	ctx := context.Background()
 
 
+	var updateFlags swarm.UpdateFlags
+
 	swarm, err := client.SwarmInspect(ctx)
 	swarm, err := client.SwarmInspect(ctx)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
@@ -42,7 +44,7 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts swarmOpti
 		return err
 		return err
 	}
 	}
 
 
-	err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec)
+	err = client.SwarmUpdate(ctx, swarm.Version, swarm.Spec, updateFlags)
 	if err != nil {
 	if err != nil {
 		return err
 		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 {
 func mergeSwarm(swarm *swarm.Swarm, flags *pflag.FlagSet) error {
 	spec := &swarm.Spec
 	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) {
 	if flags.Changed(flagTaskHistoryLimit) {
 		spec.Orchestration.TaskHistoryRetentionLimit, _ = flags.GetInt64(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 {
 		if info.Swarm.ControlAvailable {
 			fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers)
 			fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers)
 			fmt.Fprintf(dockerCli.Out(), " Nodes: %d\n", info.Swarm.Nodes)
 			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
 	Join(req types.JoinRequest) error
 	Leave(force bool) error
 	Leave(force bool) error
 	Inspect() (types.Swarm, error)
 	Inspect() (types.Swarm, error)
-	Update(uint64, types.Spec) error
+	Update(uint64, types.Spec, types.UpdateFlags) error
 	GetServices(basictypes.ServiceListOptions) ([]types.Service, error)
 	GetServices(basictypes.ServiceListOptions) ([]types.Service, error)
 	GetService(string) (types.Service, error)
 	GetService(string) (types.Service, error)
 	CreateService(types.ServiceSpec, string) (string, 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())
 		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)
 		logrus.Errorf("Error configuring swarm: %v", err)
 		return err
 		return err
 	}
 	}

+ 6 - 6
contrib/completion/zsh/_docker

@@ -1087,7 +1087,7 @@ __docker_service_subcommand() {
         "($help)--name=[Service name]:name: "
         "($help)--name=[Service name]:name: "
         "($help)*--network=[Network attachments]:network: "
         "($help)*--network=[Network attachments]:network: "
         "($help)*"{-p=,--publish=}"[Publish a port as a node port]:port: "
         "($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)--replicas=[Number of tasks]:replicas: "
         "($help)--reserve-cpu=[Reserve CPUs]:value: "
         "($help)--reserve-cpu=[Reserve CPUs]:value: "
         "($help)--reserve-memory=[Reserve Memory]:value: "
         "($help)--reserve-memory=[Reserve Memory]:value: "
@@ -1185,11 +1185,11 @@ __docker_service_subcommand() {
 __docker_swarm_commands() {
 __docker_swarm_commands() {
     local -a _docker_swarm_subcommands
     local -a _docker_swarm_subcommands
     _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
     _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"
 	"google.golang.org/grpc"
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/digest"
 	"github.com/docker/docker/daemon/cluster/convert"
 	"github.com/docker/docker/daemon/cluster/convert"
 	executorpkg "github.com/docker/docker/daemon/cluster/executor"
 	executorpkg "github.com/docker/docker/daemon/cluster/executor"
 	"github.com/docker/docker/daemon/cluster/executor/container"
 	"github.com/docker/docker/daemon/cluster/executor/container"
@@ -42,16 +41,16 @@ const (
 )
 )
 
 
 // ErrNoSwarm is returned on leaving a cluster that was never initialized
 // 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
 // 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.
 // 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.")
 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.
 // 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
 // defaultSpec contains some sane defaults if cluster options are missing on init
 var defaultSpec = types.Spec{
 var defaultSpec = types.Spec{
@@ -127,7 +126,7 @@ func New(config Config) (*Cluster, error) {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	n, err := c.startNewNode(false, st.ListenAddr, "", "", "", false)
+	n, err := c.startNewNode(false, st.ListenAddr, "", "")
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -196,7 +195,7 @@ func (c *Cluster) reconnectOnFailure(n *node) {
 			return
 			return
 		}
 		}
 		var err error
 		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 {
 		if err != nil {
 			c.err = err
 			c.err = err
 			close(n.done)
 			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 {
 	if err := c.config.Backend.IsSwarmCompatible(); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
@@ -219,12 +218,10 @@ func (c *Cluster) startNewNode(forceNewCluster bool, listenAddr, joinAddr, secre
 		ListenRemoteAPI:  listenAddr,
 		ListenRemoteAPI:  listenAddr,
 		JoinAddr:         joinAddr,
 		JoinAddr:         joinAddr,
 		StateDir:         c.root,
 		StateDir:         c.root,
-		CAHash:           cahash,
-		Secret:           secret,
+		JoinToken:        joinToken,
 		Executor:         container.NewExecutor(c.config.Backend),
 		Executor:         container.NewExecutor(c.config.Backend),
 		HeartbeatTick:    1,
 		HeartbeatTick:    1,
 		ElectionTick:     3,
 		ElectionTick:     3,
-		IsManager:        ismanager,
 	})
 	})
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
@@ -291,7 +288,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
 	if node := c.node; node != nil {
 	if node := c.node; node != nil {
 		if !req.ForceNewCluster {
 		if !req.ForceNewCluster {
 			c.Unlock()
 			c.Unlock()
-			return "", errSwarmExists(node)
+			return "", ErrSwarmExists
 		}
 		}
 		if err := c.stopNode(); err != nil {
 		if err := c.stopNode(); err != nil {
 			c.Unlock()
 			c.Unlock()
@@ -305,7 +302,7 @@ func (c *Cluster) Init(req types.InitRequest) (string, error) {
 	}
 	}
 
 
 	// todo: check current state existing
 	// 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 {
 	if err != nil {
 		c.Unlock()
 		c.Unlock()
 		return "", err
 		return "", err
@@ -336,40 +333,32 @@ func (c *Cluster) Join(req types.JoinRequest) error {
 	c.Lock()
 	c.Lock()
 	if node := c.node; node != nil {
 	if node := c.node; node != nil {
 		c.Unlock()
 		c.Unlock()
-		return errSwarmExists(node)
+		return ErrSwarmExists
 	}
 	}
 	if err := validateAndSanitizeJoinRequest(&req); err != nil {
 	if err := validateAndSanitizeJoinRequest(&req); err != nil {
 		c.Unlock()
 		c.Unlock()
 		return err
 		return err
 	}
 	}
 	// todo: check current state existing
 	// 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 {
 	if err != nil {
 		c.Unlock()
 		c.Unlock()
 		return err
 		return err
 	}
 	}
 	c.Unlock()
 	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.
 // 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()
 	c.RLock()
 	defer c.RUnlock()
 	defer c.RUnlock()
 
 
@@ -505,7 +494,7 @@ func (c *Cluster) Update(version uint64, spec types.Spec) error {
 		return err
 		return err
 	}
 	}
 
 
-	swarmSpec, err := convert.SwarmSpecToGRPCandMerge(spec, &swarm.Spec)
+	swarmSpec, err := convert.SwarmSpecToGRPC(spec)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -518,6 +507,10 @@ func (c *Cluster) Update(version uint64, spec types.Spec) error {
 			ClusterVersion: &swarmapi.Version{
 			ClusterVersion: &swarmapi.Version{
 				Index: version,
 				Index: version,
 			},
 			},
+			Rotation: swarmapi.JoinTokenRotation{
+				RotateWorkerToken:  flags.RotateWorkerToken,
+				RotateManagerToken: flags.RotateManagerToken,
+			},
 		},
 		},
 	)
 	)
 	return err
 	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 {
 	if c.node != nil {
@@ -636,12 +625,12 @@ func (c *Cluster) isActiveManager() bool {
 // Call with read lock.
 // Call with read lock.
 func (c *Cluster) errNoManager() error {
 func (c *Cluster) errNoManager() error {
 	if c.node == nil {
 	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 {
 	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.
 // 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)
 			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
 	return nil
 }
 }
 
 
@@ -1238,13 +1222,6 @@ func validateAddr(addr string) (string, error) {
 	return strings.TrimPrefix(newaddr, "tcp://"), nil
 	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 {
 func initClusterSpec(node *node, spec types.Spec) error {
 	ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
 	ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
 	for conn := range node.ListenControlSocket(ctx) {
 	for conn := range node.ListenControlSocket(ctx) {
@@ -1269,7 +1246,7 @@ func initClusterSpec(node *node, spec types.Spec) error {
 				cluster = lcr.Clusters[0]
 				cluster = lcr.Clusters[0]
 				break
 				break
 			}
 			}
-			newspec, err := convert.SwarmSpecToGRPCandMerge(spec, &cluster.Spec)
+			newspec, err := convert.SwarmSpecToGRPC(spec)
 			if err != nil {
 			if err != nil {
 				return fmt.Errorf("error updating cluster settings: %v", err)
 				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,
 		ID: n.ID,
 		Spec: types.NodeSpec{
 		Spec: types.NodeSpec{
 			Role:         types.NodeRole(strings.ToLower(n.Spec.Role.String())),
 			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())),
 			Availability: types.NodeAvailability(strings.ToLower(n.Spec.Availability.String())),
 		},
 		},
 		Status: types.NodeStatus{
 		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)
 		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 {
 	if availability, ok := swarmapi.NodeSpec_Availability_value[strings.ToUpper(string(s.Availability))]; ok {
 		spec.Availability = swarmapi.NodeSpec_Availability(availability)
 		spec.Availability = swarmapi.NodeSpec_Availability(availability)
 	} else {
 	} else {

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

@@ -5,8 +5,6 @@ import (
 	"strings"
 	"strings"
 	"time"
 	"time"
 
 
-	"golang.org/x/crypto/bcrypt"
-
 	types "github.com/docker/engine-api/types/swarm"
 	types "github.com/docker/engine-api/types/swarm"
 	swarmapi "github.com/docker/swarmkit/api"
 	swarmapi "github.com/docker/swarmkit/api"
 	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/docker/swarmkit/protobuf/ptypes"
@@ -28,6 +26,10 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
 				ElectionTick:               c.Spec.Raft.ElectionTick,
 				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)
 	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.Name = c.Spec.Annotations.Name
 	swarm.Spec.Labels = c.Spec.Annotations.Labels
 	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
 	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{
 	spec := swarmapi.ClusterSpec{
 		Annotations: swarmapi.Annotations{
 		Annotations: swarmapi.Annotations{
 			Name:   s.Name,
 			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
 	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",
         "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
         "Spec": {
         "Spec": {
           "Role": "MANAGER",
           "Role": "MANAGER",
-          "Membership": "ACCEPTED",
           "Availability": "ACTIVE"
           "Availability": "ACTIVE"
         },
         },
         "Description": {
         "Description": {
@@ -3481,7 +3480,6 @@ Return low-level information on the node `id`
       "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
       "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
       "Spec": {
       "Spec": {
         "Role": "MANAGER",
         "Role": "MANAGER",
-        "Membership": "ACCEPTED",
         "Availability": "ACTIVE"
         "Availability": "ACTIVE"
       },
       },
       "Description": {
       "Description": {
@@ -3595,18 +3593,6 @@ Initialize a new Swarm
       "ListenAddr": "0.0.0.0:4500",
       "ListenAddr": "0.0.0.0:4500",
       "ForceNewCluster": false,
       "ForceNewCluster": false,
       "Spec": {
       "Spec": {
-        "AcceptancePolicy": {
-          "Policies": [
-            {
-              "Role": "MANAGER",
-              "Autoaccept": false
-            },
-            {
-              "Role": "WORKER",
-              "Autoaccept": true
-            }
-          ]
-        },
         "Orchestration": {},
         "Orchestration": {},
         "Raft": {},
         "Raft": {},
         "Dispatcher": {},
         "Dispatcher": {},
@@ -3676,9 +3662,7 @@ Join an existing new Swarm
     {
     {
       "ListenAddr": "0.0.0.0:4500",
       "ListenAddr": "0.0.0.0:4500",
       "RemoteAddrs": ["node1:4500"],
       "RemoteAddrs": ["node1:4500"],
-      "Secret": "",
-      "CACertHash": "",
-      "Manager": false
+      "JoinToken": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
     }
     }
 
 
 **Example response**:
 **Example response**:
@@ -3698,9 +3682,7 @@ JSON Parameters:
 - **ListenAddr** – Listen address used for inter-manager communication if the node gets promoted to
 - **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).
   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.
 - **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
 ### Leave a Swarm
 
 
@@ -3741,18 +3723,6 @@ Update a Swarm
 
 
     {
     {
       "Name": "default",
       "Name": "default",
-      "AcceptancePolicy": {
-        "Policies": [
-          {
-            "Role": "WORKER",
-            "Autoaccept": false
-          },
-          {
-            "Role": "MANAGER",
-            "Autoaccept": false
-          }
-        ]
-      },
       "Orchestration": {
       "Orchestration": {
         "TaskHistoryRetentionLimit": 10
         "TaskHistoryRetentionLimit": 10
       },
       },
@@ -3767,6 +3737,10 @@ Update a Swarm
       },
       },
       "CAConfig": {
       "CAConfig": {
         "NodeCertExpiry": 7776000000000000
         "NodeCertExpiry": 7776000000000000
+      },
+      "JoinTokens": {
+        "Worker": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx",
+        "Manager": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
       }
       }
     }
     }
 
 
@@ -3777,6 +3751,13 @@ Update a Swarm
     Content-Length: 0
     Content-Length: 0
     Content-Type: text/plain; charset=utf-8
     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**:
 **Status codes**:
 
 
 - **200** – no error
 - **200** – no error
@@ -3785,11 +3766,6 @@ Update a Swarm
 
 
 JSON Parameters:
 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.
 - **Orchestration** – Configuration settings for the orchestration aspects of the Swarm.
     - **TaskHistoryRetentionLimit** – Maximum number of tasks history stored.
     - **TaskHistoryRetentionLimit** – Maximum number of tasks history stored.
 - **Raft** – Raft related configuration.
 - **Raft** – Raft related configuration.
@@ -3811,6 +3787,9 @@ JSON Parameters:
         - **URL** - URL where certificate signing requests should be sent.
         - **URL** - URL where certificate signing requests should be sent.
         - **Options** - An object with key/value pairs that are interpreted
         - **Options** - An object with key/value pairs that are interpreted
           as protocol-specific options for the external CA driver.
           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
 ## 3.8 Services
 
 
@@ -4292,6 +4271,10 @@ Update the service `id`.
           of: `"Ports": { "<port>/<tcp|udp>: {}" }`
           of: `"Ports": { "<port>/<tcp|udp>: {}" }`
     - **VirtualIPs**
     - **VirtualIPs**
 
 
+**Query parameters**:
+
+- **version** – The version number of the service object being updated. This is
+  required to avoid conflicting writes.
 
 
 **Status codes**:
 **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",
         "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
         "Spec": {
         "Spec": {
           "Role": "MANAGER",
           "Role": "MANAGER",
-          "Membership": "ACCEPTED",
           "Availability": "ACTIVE"
           "Availability": "ACTIVE"
         },
         },
         "Description": {
         "Description": {
@@ -3482,7 +3481,6 @@ Return low-level information on the node `id`
       "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
       "UpdatedAt": "2016-06-07T20:31:11.999868824Z",
       "Spec": {
       "Spec": {
         "Role": "MANAGER",
         "Role": "MANAGER",
-        "Membership": "ACCEPTED",
         "Availability": "ACTIVE"
         "Availability": "ACTIVE"
       },
       },
       "Description": {
       "Description": {
@@ -3596,18 +3594,6 @@ Initialize a new Swarm
       "ListenAddr": "0.0.0.0:4500",
       "ListenAddr": "0.0.0.0:4500",
       "ForceNewCluster": false,
       "ForceNewCluster": false,
       "Spec": {
       "Spec": {
-        "AcceptancePolicy": {
-          "Policies": [
-            {
-              "Role": "MANAGER",
-              "Autoaccept": false
-            },
-            {
-              "Role": "WORKER",
-              "Autoaccept": true
-            }
-          ]
-        },
         "Orchestration": {},
         "Orchestration": {},
         "Raft": {},
         "Raft": {},
         "Dispatcher": {},
         "Dispatcher": {},
@@ -3677,9 +3663,7 @@ Join an existing new Swarm
     {
     {
       "ListenAddr": "0.0.0.0:4500",
       "ListenAddr": "0.0.0.0:4500",
       "RemoteAddrs": ["node1:4500"],
       "RemoteAddrs": ["node1:4500"],
-      "Secret": "",
-      "CACertHash": "",
-      "Manager": false
+      "JoinToken": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
     }
     }
 
 
 **Example response**:
 **Example response**:
@@ -3699,9 +3683,7 @@ JSON Parameters:
 - **ListenAddr** – Listen address used for inter-manager communication if the node gets promoted to
 - **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).
   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.
 - **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
 ### Leave a Swarm
 
 
@@ -3742,18 +3724,6 @@ Update a Swarm
 
 
     {
     {
       "Name": "default",
       "Name": "default",
-      "AcceptancePolicy": {
-        "Policies": [
-          {
-            "Role": "WORKER",
-            "Autoaccept": false
-          },
-          {
-            "Role": "MANAGER",
-            "Autoaccept": false
-          }
-        ]
-      },
       "Orchestration": {
       "Orchestration": {
         "TaskHistoryRetentionLimit": 10
         "TaskHistoryRetentionLimit": 10
       },
       },
@@ -3768,6 +3738,10 @@ Update a Swarm
       },
       },
       "CAConfig": {
       "CAConfig": {
         "NodeCertExpiry": 7776000000000000
         "NodeCertExpiry": 7776000000000000
+      },
+      "JoinTokens": {
+        "Worker": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx",
+        "Manager": "SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-7p73s1dx5in4tatdymyhg9hu2"
       }
       }
     }
     }
 
 
@@ -3778,6 +3752,13 @@ Update a Swarm
     Content-Length: 0
     Content-Length: 0
     Content-Type: text/plain; charset=utf-8
     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**:
 **Status codes**:
 
 
 - **200** – no error
 - **200** – no error
@@ -3786,11 +3767,6 @@ Update a Swarm
 
 
 JSON Parameters:
 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.
 - **Orchestration** – Configuration settings for the orchestration aspects of the Swarm.
     - **TaskHistoryRetentionLimit** – Maximum number of tasks history stored.
     - **TaskHistoryRetentionLimit** – Maximum number of tasks history stored.
 - **Raft** – Raft related configuration.
 - **Raft** – Raft related configuration.
@@ -3812,6 +3788,9 @@ JSON Parameters:
         - **URL** - URL where certificate signing requests should be sent.
         - **URL** - URL where certificate signing requests should be sent.
         - **Options** - An object with key/value pairs that are interpreted
         - **Options** - An object with key/value pairs that are interpreted
           as protocol-specific options for the external CA driver.
           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
 ## 3.8 Services
 
 
@@ -4293,6 +4272,10 @@ Update the service `id`.
           of: `"Ports": { "<port>/<tcp|udp>: {}" }`
           of: `"Ports": { "<port>/<tcp|udp>: {}" }`
     - **VirtualIPs**
     - **VirtualIPs**
 
 
+**Query parameters**:
+
+- **version** – The version number of the service object being updated. This is
+  required to avoid conflicting writes.
 
 
 **Status codes**:
 **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:
 Options:
       --file   string   Path to a Distributed Application Bundle file (Default: STACK.dab)
       --file   string   Path to a Distributed Application Bundle file (Default: STACK.dab)
       --help            Print usage
       --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
 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                                                        |
 | 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 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 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                |
 | [node inspect](node_inspect.md) | Inspect a node in the swarm                |
@@ -124,10 +123,11 @@ read the [`dockerd`](dockerd.md) reference page.
 
 
 | Command | Description                                                        |
 | 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 leave](swarm_leave.md) | Remove the current node from the swarm       |
 | [swarm update](swarm_update.md) | Update attributes of a 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
 ### 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
 ## Display Docker system information
 
 
 Here is a sample output for a daemon running on Ubuntu, using the overlay
 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
     $ docker -D info
     Containers: 14
     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
 ## Related information
 
 
-* [node accept](node_accept.md)
 * [node promote](node_promote.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",
         "UpdatedAt": "2016-06-16T22:52:45.230878043Z",
         "Spec": {
         "Spec": {
             "Role": "manager",
             "Role": "manager",
-            "Membership": "accepted",
             "Availability": "active"
             "Availability": "active"
         },
         },
         "Description": {
         "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:
 Example output:
 
 
     $ docker node ls
     $ 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
 ## 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.
 The following filter matches the node with a name equal to `swarm-master` string.
 
 
     $ docker node ls -f name=swarm-manager1
     $ 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
 ### id
 
 
 The `id` filter matches all or part of a node's id.
 The `id` filter matches all or part of a node's id.
 
 
     $ docker node ls -f id=1
     $ 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
 #### label
@@ -75,8 +75,8 @@ The following filter matches nodes with the `usage` label regardless of its valu
 
 
 ```bash
 ```bash
 $ docker node ls -f "label=foo"
 $ 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
 ## Related information
 
 
-* [node accept](node_accept.md)
 * [node demote](node_demote.md)
 * [node demote](node_demote.md)

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

@@ -23,14 +23,13 @@ Options:
       --help   Print usage
       --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:
 Example output:
 
 
     $ docker node rm swarm-node-02
     $ docker node rm swarm-node-02
-    Node swarm-node-02 removed from Swarm
+    Node swarm-node-02 removed from swarm
 
 
 
 
 ## Related information
 ## Related information

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

@@ -21,7 +21,6 @@ Options:
       --help                  Print usage
       --help                  Print usage
       --label-add value       Add or update a node label (key=value) (default [])
       --label-add value       Add or update a node label (key=value) (default [])
       --label-rm value        Remove a node label if exists (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)
       --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
       --name string                  Service name
       --network value                Network attachments (default [])
       --network value                Network attachments (default [])
   -p, --publish value                Publish a port as a node port (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)
       --replicas value               Number of tasks (default none)
       --reserve-cpu value            Reserve CPUs (default 0.000)
       --reserve-cpu value            Reserve CPUs (default 0.000)
       --reserve-memory value         Reserve Memory (default 0 B)
       --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 [])
       --network-rm value             Remove a network by name (default [])
       --publish-add value            Add or update a published port (default [])
       --publish-add value            Add or update a published port (default [])
       --publish-rm value             Remove a published port by its target 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)
       --replicas value               Number of tasks (default none)
       --reserve-cpu value            Reserve CPUs (default 0.000)
       --reserve-cpu value            Reserve CPUs (default 0.000)
       --reserve-memory value         Reserve Memory (default 0 B)
       --reserve-memory value         Reserve Memory (default 0 B)

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

@@ -14,74 +14,43 @@ parent = "smn_cli"
 ```markdown
 ```markdown
 Usage:  docker swarm init [OPTIONS]
 Usage:  docker swarm init [OPTIONS]
 
 
-Initialize a Swarm
+Initialize a swarm
 
 
 Options:
 Options:
-      --auto-accept value               Auto acceptance policy (default worker)
       --cert-expiry duration            Validity period for node certificates (default 2160h0m0s)
       --cert-expiry duration            Validity period for node certificates (default 2160h0m0s)
       --dispatcher-heartbeat duration   Dispatcher heartbeat period (default 5s)
       --dispatcher-heartbeat duration   Dispatcher heartbeat period (default 5s)
       --external-ca value               Specifications of one or more certificate signing endpoints
       --external-ca value               Specifications of one or more certificate signing endpoints
       --force-new-cluster               Force create a new cluster from current state.
       --force-new-cluster               Force create a new cluster from current state.
       --help                            Print usage
       --help                            Print usage
       --listen-addr value               Listen address (default 0.0.0.0:2377)
       --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)
       --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
 ```bash
 $ docker swarm init --listen-addr 192.168.99.121:2377
 $ 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:
 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`
 ### `--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`
 ### `--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`
 ### `--task-history-limit`
 
 
@@ -120,5 +85,5 @@ This flag sets up task history retention limit.
 * [swarm join](swarm_join.md)
 * [swarm join](swarm_join.md)
 * [swarm leave](swarm_leave.md)
 * [swarm leave](swarm_leave.md)
 * [swarm update](swarm_update.md)
 * [swarm update](swarm_update.md)
-* [node accept](node_accept.md)
+* [swarm join-token](swarm_join_token.md)
 * [node rm](node_rm.md)
 * [node rm](node_rm.md)

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

@@ -14,55 +14,54 @@ parent = "smn_cli"
 ```markdown
 ```markdown
 Usage:  docker swarm join [OPTIONS] HOST:PORT
 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:
 Options:
-      --ca-hash string      Hash of the Root Certificate Authority certificate used for trusted join
       --help                Print usage
       --help                Print usage
       --listen-addr value   Listen address (default 0.0.0.0:2377)
       --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
 ### Join a node to swarm as a manager
 
 
+The example below demonstrates joining a manager node using a manager token.
+
 ```bash
 ```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
 $ 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
 ### Join a node to swarm as a worker
 
 
+The example below demonstrates joining a worker node using a worker token.
+
 ```bash
 ```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
 $ 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`
 ### `--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
 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
 ```markdown
 Usage:  docker swarm leave [OPTIONS]
 Usage:  docker swarm leave [OPTIONS]
 
 
-Leave a Swarm
+Leave a swarm
 
 
 Options:
 Options:
       --force   Force leave ignoring warnings.
       --force   Force leave ignoring warnings.
@@ -26,10 +26,10 @@ This command causes the node to leave the swarm.
 On a manager node:
 On a manager node:
 ```bash
 ```bash
 $ docker node ls
 $ 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:
 On a worker node:
@@ -41,10 +41,10 @@ Node left the default swarm.
 On a manager node:
 On a manager node:
 ```bash
 ```bash
 $ docker node ls
 $ 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
 ## Related information

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

@@ -14,23 +14,21 @@ parent = "smn_cli"
 ```markdown
 ```markdown
 Usage:  docker swarm update [OPTIONS]
 Usage:  docker swarm update [OPTIONS]
 
 
-Update the Swarm
+Update the swarm
 
 
 Options:
 Options:
-      --auto-accept value               Auto acceptance policy (worker, manager or none)
       --cert-expiry duration            Validity period for node certificates (default 2160h0m0s)
       --cert-expiry duration            Validity period for node certificates (default 2160h0m0s)
       --dispatcher-heartbeat duration   Dispatcher heartbeat period (default 5s)
       --dispatcher-heartbeat duration   Dispatcher heartbeat period (default 5s)
       --external-ca value               Specifications of one or more certificate signing endpoints
       --external-ca value               Specifications of one or more certificate signing endpoints
       --help                            Print usage
       --help                            Print usage
-      --secret string                   Set secret value needed to accept nodes into cluster
       --task-history-limit int          Task history retention limit (default 10)
       --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
 ```bash
-$ docker swarm update --auto-accept manager
+$ docker swarm update --cert-expirty 4000h0m0s
 ```
 ```
 
 
 ## Related information
 ## 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 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-units 651fc226e7441360384da338d0fd37f2440ffbe3
 clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d
 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/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
 clone git github.com/imdario/mergo 0.2.1
 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
 clone git github.com/docker/containerd 0ac3cd1be170d180b2baed755e8f0da547ceb267
 
 
 # cluster
 # 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/golang/mock bd3c8e81be01eef76d4b503f5e687d2d1354d2d9
 clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028
 clone git github.com/gogo/protobuf 43a2e0b1c32252bfbbdf81f7faa7a88fb3fa4028
 clone git github.com/cloudflare/cfssl b895b0549c0ff676f92cf09ba971ae02bb41367b
 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 joinSwarm == true {
 		if len(s.daemons) > 0 {
 		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{
 			c.Assert(d.Join(swarm.JoinRequest{
 				RemoteAddrs: []string{s.daemons[0].listenAddr},
 				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)
 			}), 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
 	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.
 // Init initializes a new swarm cluster.
 func (d *SwarmDaemon) Init(req swarm.InitRequest) error {
 func (d *SwarmDaemon) Init(req swarm.InitRequest) error {
 	if req.ListenAddr == "" {
 	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)))
 	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) {
 func (d *SwarmDaemon) checkLocalNodeState(c *check.C) (interface{}, check.CommentInterface) {
 	info, err := d.info()
 	info, err := d.info()
 	c.Assert(err, checker.IsNil)
 	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.ControlAvailable, checker.False)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	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()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
@@ -72,89 +72,29 @@ func (s *DockerSwarmSuite) TestApiSwarmInit(c *check.C) {
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
 	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)
 	testRequires(c, Network)
 	d1 := s.AddDaemon(c, false, false)
 	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)
 	d2 := s.AddDaemon(c, false, false)
 	err := d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}})
 	err := d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}})
 	c.Assert(err, checker.NotNil)
 	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()
 	info, err := d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	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, 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()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	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()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
 	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(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	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, 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()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	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()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
 	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(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	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}})
 	err = d2.Join(swarm.JoinRequest{RemoteAddrs: []string{d1.listenAddr}})
 	c.Assert(err, checker.NotNil)
 	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()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	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()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateActive)
@@ -229,34 +142,24 @@ func (s *DockerSwarmSuite) TestApiSwarmSecretAcceptance(c *check.C) {
 	info, err = d2.info()
 	info, err = d2.info()
 	c.Assert(err, checker.IsNil)
 	c.Assert(err, checker.IsNil)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
 	c.Assert(info.LocalNodeState, checker.Equals, swarm.LocalNodeStateInactive)
-
 }
 }
 
 
 func (s *DockerSwarmSuite) TestApiSwarmCAHash(c *check.C) {
 func (s *DockerSwarmSuite) TestApiSwarmCAHash(c *check.C) {
 	testRequires(c, Network)
 	testRequires(c, Network)
 	d1 := s.AddDaemon(c, true, true)
 	d1 := s.AddDaemon(c, true, true)
 	d2 := s.AddDaemon(c, false, false)
 	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, 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) {
 func (s *DockerSwarmSuite) TestApiSwarmPromoteDemote(c *check.C) {
 	testRequires(c, Network)
 	testRequires(c, Network)
 	d1 := s.AddDaemon(c, false, false)
 	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)
 	d2 := s.AddDaemon(c, true, false)
 
 
 	info, err := d2.info()
 	info, err := d2.info()
@@ -838,9 +741,7 @@ func (s *DockerSwarmSuite) TestApiSwarmForceNewCluster(c *check.C) {
 
 
 	c.Assert(d1.Init(swarm.InitRequest{
 	c.Assert(d1.Init(swarm.InitRequest{
 		ForceNewCluster: true,
 		ForceNewCluster: true,
-		Spec: swarm.Spec{
-			AcceptancePolicy: autoAcceptPolicy,
-		},
+		Spec:            swarm.Spec{},
 	}), checker.IsNil)
 	}), checker.IsNil)
 
 
 	waitAndAssert(c, defaultReconciliationTimeout, d1.checkActiveContainerCount, checker.Equals, instances)
 	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) {
 		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.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.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 {
 			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))
 				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 {
 				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
 		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))
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
 
 
 	spec := getSpec()
 	spec := getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
 	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(11*time.Second))
 	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
 	// setting anything under 30m for cert-expiry is not allowed
 	out, err = d.Cmd("swarm", "update", "--cert-expiry", "15m")
 	out, err = d.Cmd("swarm", "update", "--cert-expiry", "15m")
 	c.Assert(err, checker.NotNil)
 	c.Assert(err, checker.NotNil)
@@ -89,37 +52,21 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
 		return sw[0].Spec
 		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))
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
 
 
 	spec := getSpec()
 	spec := getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
 	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(11*time.Second))
 	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)
 	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))
 	c.Assert(err, checker.IsNil, check.Commentf("out: %v", out))
 
 
 	spec = getSpec()
 	spec = getSpec()
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour)
 	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.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) {
 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
 	SwarmJoin(ctx context.Context, req swarm.JoinRequest) error
 	SwarmLeave(ctx context.Context, force bool) error
 	SwarmLeave(ctx context.Context, force bool) error
 	SwarmInspect(ctx context.Context) (swarm.Swarm, 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
 // 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
 package client
 
 
 import (
 import (
+	"fmt"
 	"net/url"
 	"net/url"
 	"strconv"
 	"strconv"
 
 
@@ -9,9 +10,11 @@ import (
 )
 )
 
 
 // SwarmUpdate updates the Swarm.
 // 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 := url.Values{}
 	query.Set("version", strconv.FormatUint(version.Index, 10))
 	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)
 	resp, err := cli.post(ctx, "/swarm/update", query, swarm, nil)
 	ensureReaderClosed(resp)
 	ensureReaderClosed(resp)
 	return err
 	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
 // 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
 // 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) {
 func Do(ctx context.Context, client transport.Sender, req *http.Request) (*http.Response, error) {
 	if client == nil {
 	if client == nil {
 		client = http.DefaultClient
 		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
 	Privileged   bool     // Is the container in privileged mode
 	Tty          bool     // Attach standard streams to a tty.
 	Tty          bool     // Attach standard streams to a tty.
 	AttachStdin  bool     // Attach the standard input, makes possible user interaction
 	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
 	Detach       bool     // Execute in detach mode
 	DetachKeys   string   // Escape keys for detach
 	DetachKeys   string   // Escape keys for detach
 	Cmd          []string // Execution commands and args
 	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 {
 type NodeSpec struct {
 	Annotations
 	Annotations
 	Role         NodeRole         `json:",omitempty"`
 	Role         NodeRole         `json:",omitempty"`
-	Membership   NodeMembership   `json:",omitempty"`
 	Availability NodeAvailability `json:",omitempty"`
 	Availability NodeAvailability `json:",omitempty"`
 }
 }
 
 
@@ -29,16 +28,6 @@ const (
 	NodeRoleManager NodeRole = "manager"
 	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.
 // NodeAvailability represents the availability of a node.
 type NodeAvailability string
 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 {
 type Swarm struct {
 	ID string
 	ID string
 	Meta
 	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.
 // Spec represents the spec of a swarm.
 type Spec struct {
 type Spec struct {
 	Annotations
 	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.
 // OrchestrationConfig represents orchestration configuration.
@@ -45,6 +32,17 @@ type OrchestrationConfig struct {
 	TaskHistoryRetentionLimit int64 `json:",omitempty"`
 	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.
 // RaftConfig represents raft configuration.
 type RaftConfig struct {
 type RaftConfig struct {
 	SnapshotInterval           uint64 `json:",omitempty"`
 	SnapshotInterval           uint64 `json:",omitempty"`
@@ -81,17 +79,17 @@ type ExternalCA struct {
 // InitRequest is the request used to init a swarm.
 // InitRequest is the request used to init a swarm.
 type InitRequest struct {
 type InitRequest struct {
 	ListenAddr      string
 	ListenAddr      string
+	AdvertiseAddr   string
 	ForceNewCluster bool
 	ForceNewCluster bool
 	Spec            Spec
 	Spec            Spec
 }
 }
 
 
 // JoinRequest is the request used to join a swarm.
 // JoinRequest is the request used to join a swarm.
 type JoinRequest struct {
 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.
 // LocalNodeState represents the state of the local node.
@@ -110,7 +108,8 @@ const (
 
 
 // Info represents generic information about swarm.
 // Info represents generic information about swarm.
 type Info struct {
 type Info struct {
-	NodeID string
+	NodeID   string
+	NodeAddr string
 
 
 	LocalNodeState   LocalNodeState
 	LocalNodeState   LocalNodeState
 	ControlAvailable bool
 	ControlAvailable bool
@@ -119,7 +118,6 @@ type Info struct {
 	RemoteManagers []Peer
 	RemoteManagers []Peer
 	Nodes          int
 	Nodes          int
 	Managers       int
 	Managers       int
-	CACertHash     string
 }
 }
 
 
 // Peer represents a peer.
 // Peer represents a peer.
@@ -127,3 +125,9 @@ type Peer struct {
 	NodeID string
 	NodeID string
 	Addr   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.
 	// remote managers and certificates.
 	StateDir string
 	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
 	// ExternalCAs is a list of CAs to which a manager node
 	// will make certificate signing requests for node certificates.
 	// will make certificate signing requests for node certificates.
@@ -73,9 +70,6 @@ type NodeConfig struct {
 	// HeartbeatTick defines the amount of ticks between each
 	// HeartbeatTick defines the amount of ticks between each
 	// heartbeat sent to other members for health-check purposes
 	// heartbeat sent to other members for health-check purposes
 	HeartbeatTick uint32
 	HeartbeatTick uint32
-
-	// todo: temporary to bypass promotion not working yet
-	IsManager bool
 }
 }
 
 
 // Node implements the primary node functionality for a member of a swarm
 // 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:
 	// Obtain new certs and setup TLS certificates renewal for this node:
 	// - We call LoadOrCreateSecurityConfig which blocks until a valid certificate has been issued
 	// - We call LoadOrCreateSecurityConfig which blocks until a valid certificate has been issued
 	// - We retrieve the nodeID from LoadOrCreateSecurityConfig through the info channel. This allows
 	// - 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")
 	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 {
 	if err != nil {
 		return err
 		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:
 		case <-run:
 			// always check for shutdown before running.
 			// always check for shutdown before running.
 			select {
 			select {
-			case <-shutdown:
+			case <-tm.shutdown:
 				continue // ignore run request and handle shutdown
 				continue // ignore run request and handle shutdown
 			case <-tm.closed:
 			case <-tm.closed:
 				continue
 				continue
@@ -142,6 +142,13 @@ func (tm *taskManager) run(ctx context.Context) {
 			// goal is to decide whether or not we re-dispatch the operation.
 			// goal is to decide whether or not we re-dispatch the operation.
 			cancel = nil
 			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 {
 			switch err {
 			case exec.ErrTaskNoop:
 			case exec.ErrTaskNoop:
 				if !updated {
 				if !updated {
@@ -203,6 +210,12 @@ func (tm *taskManager) run(ctx context.Context) {
 			if cancel != nil {
 			if cancel != nil {
 				// cancel outstanding operation.
 				// cancel outstanding operation.
 				cancel()
 				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.
 			// 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} }
 func (*NodeCertificateStatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorCa, []int{1} }
 
 
 type IssueNodeCertificateRequest struct {
 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"`
 	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
 	// 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{} }
 func (m *IssueNodeCertificateRequest) Reset()                    { *m = IssueNodeCertificateRequest{} }
@@ -165,9 +167,9 @@ func (m *IssueNodeCertificateRequest) Copy() *IssueNodeCertificateRequest {
 	}
 	}
 
 
 	o := &IssueNodeCertificateRequest{
 	o := &IssueNodeCertificateRequest{
-		Role:   m.Role,
-		CSR:    m.CSR,
-		Secret: m.Secret,
+		Role:  m.Role,
+		CSR:   m.CSR,
+		Token: m.Token,
 	}
 	}
 
 
 	return o
 	return o
@@ -241,7 +243,7 @@ func (this *IssueNodeCertificateRequest) GoString() string {
 	s = append(s, "&api.IssueNodeCertificateRequest{")
 	s = append(s, "&api.IssueNodeCertificateRequest{")
 	s = append(s, "Role: "+fmt.Sprintf("%#v", this.Role)+",\n")
 	s = append(s, "Role: "+fmt.Sprintf("%#v", this.Role)+",\n")
 	s = append(s, "CSR: "+fmt.Sprintf("%#v", this.CSR)+",\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, "}")
 	s = append(s, "}")
 	return strings.Join(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 = encodeVarintCa(data, i, uint64(len(m.CSR)))
 		i += copy(data[i:], m.CSR)
 		i += copy(data[i:], m.CSR)
 	}
 	}
-	if len(m.Secret) > 0 {
+	if len(m.Token) > 0 {
 		data[i] = 0x1a
 		data[i] = 0x1a
 		i++
 		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
 	return i, nil
 }
 }
@@ -836,7 +838,7 @@ func (m *IssueNodeCertificateRequest) Size() (n int) {
 	if l > 0 {
 	if l > 0 {
 		n += 1 + l + sovCa(uint64(l))
 		n += 1 + l + sovCa(uint64(l))
 	}
 	}
-	l = len(m.Secret)
+	l = len(m.Token)
 	if l > 0 {
 	if l > 0 {
 		n += 1 + l + sovCa(uint64(l))
 		n += 1 + l + sovCa(uint64(l))
 	}
 	}
@@ -913,7 +915,7 @@ func (this *IssueNodeCertificateRequest) String() string {
 	s := strings.Join([]string{`&IssueNodeCertificateRequest{`,
 	s := strings.Join([]string{`&IssueNodeCertificateRequest{`,
 		`Role:` + fmt.Sprintf("%v", this.Role) + `,`,
 		`Role:` + fmt.Sprintf("%v", this.Role) + `,`,
 		`CSR:` + fmt.Sprintf("%v", this.CSR) + `,`,
 		`CSR:` + fmt.Sprintf("%v", this.CSR) + `,`,
-		`Secret:` + fmt.Sprintf("%v", this.Secret) + `,`,
+		`Token:` + fmt.Sprintf("%v", this.Token) + `,`,
 		`}`,
 		`}`,
 	}, "")
 	}, "")
 	return s
 	return s
@@ -1232,7 +1234,7 @@ func (m *IssueNodeCertificateRequest) Unmarshal(data []byte) error {
 			iNdEx = postIndex
 			iNdEx = postIndex
 		case 3:
 		case 3:
 			if wireType != 2 {
 			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
 			var stringLen uint64
 			for shift := uint(0); ; shift += 7 {
 			for shift := uint(0); ; shift += 7 {
@@ -1257,7 +1259,7 @@ func (m *IssueNodeCertificateRequest) Unmarshal(data []byte) error {
 			if postIndex > l {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 				return io.ErrUnexpectedEOF
 			}
 			}
-			m.Secret = string(data[iNdEx:postIndex])
+			m.Token = string(data[iNdEx:postIndex])
 			iNdEx = postIndex
 			iNdEx = postIndex
 		default:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
@@ -1615,36 +1617,36 @@ var (
 )
 )
 
 
 var fileDescriptorCa = []byte{
 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 {
 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"];
 	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
 	// nodes to join the cluster
-	string secret = 3;
+	string token = 3;
 }
 }
 
 
 message IssueNodeCertificateResponse {
 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) ProtoMessage()               {}
 func (*ListClustersResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{35} }
 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 {
 type UpdateClusterRequest struct {
 	// ClusterID is the cluster ID to update.
 	// ClusterID is the cluster ID to update.
 	ClusterID string `protobuf:"bytes,1,opt,name=cluster_id,json=clusterId,proto3" json:"cluster_id,omitempty"`
 	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"`
 	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 is the new spec to apply to the cluster.
 	Spec *ClusterSpec `protobuf:"bytes,3,opt,name=spec" json:"spec,omitempty"`
 	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 (m *UpdateClusterRequest) Reset()                    { *m = UpdateClusterRequest{} }
 func (*UpdateClusterRequest) ProtoMessage()               {}
 func (*UpdateClusterRequest) ProtoMessage()               {}
-func (*UpdateClusterRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{36} }
+func (*UpdateClusterRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{37} }
 
 
 type UpdateClusterResponse struct {
 type UpdateClusterResponse struct {
 	Cluster *Cluster `protobuf:"bytes,1,opt,name=cluster" json:"cluster,omitempty"`
 	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 (m *UpdateClusterResponse) Reset()                    { *m = UpdateClusterResponse{} }
 func (*UpdateClusterResponse) ProtoMessage()               {}
 func (*UpdateClusterResponse) ProtoMessage()               {}
-func (*UpdateClusterResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{37} }
+func (*UpdateClusterResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{38} }
 
 
 func init() {
 func init() {
 	proto.RegisterType((*GetNodeRequest)(nil), "docker.swarmkit.v1.GetNodeRequest")
 	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)(nil), "docker.swarmkit.v1.ListClustersRequest")
 	proto.RegisterType((*ListClustersRequest_Filters)(nil), "docker.swarmkit.v1.ListClustersRequest.Filters")
 	proto.RegisterType((*ListClustersRequest_Filters)(nil), "docker.swarmkit.v1.ListClustersRequest.Filters")
 	proto.RegisterType((*ListClustersResponse)(nil), "docker.swarmkit.v1.ListClustersResponse")
 	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((*UpdateClusterRequest)(nil), "docker.swarmkit.v1.UpdateClusterRequest")
 	proto.RegisterType((*UpdateClusterResponse)(nil), "docker.swarmkit.v1.UpdateClusterResponse")
 	proto.RegisterType((*UpdateClusterResponse)(nil), "docker.swarmkit.v1.UpdateClusterResponse")
 }
 }
@@ -1314,6 +1328,19 @@ func (m *ListClustersResponse) Copy() *ListClustersResponse {
 	return o
 	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 {
 func (m *UpdateClusterRequest) Copy() *UpdateClusterRequest {
 	if m == nil {
 	if m == nil {
 		return nil
 		return nil
@@ -1323,6 +1350,7 @@ func (m *UpdateClusterRequest) Copy() *UpdateClusterRequest {
 		ClusterID:      m.ClusterID,
 		ClusterID:      m.ClusterID,
 		ClusterVersion: m.ClusterVersion.Copy(),
 		ClusterVersion: m.ClusterVersion.Copy(),
 		Spec:           m.Spec.Copy(),
 		Spec:           m.Spec.Copy(),
+		Rotation:       *m.Rotation.Copy(),
 	}
 	}
 
 
 	return o
 	return o
@@ -1882,11 +1910,22 @@ func (this *ListClustersResponse) GoString() string {
 	s = append(s, "}")
 	s = append(s, "}")
 	return strings.Join(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 {
 func (this *UpdateClusterRequest) GoString() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
 	}
 	}
-	s := make([]string, 0, 7)
+	s := make([]string, 0, 8)
 	s = append(s, "&api.UpdateClusterRequest{")
 	s = append(s, "&api.UpdateClusterRequest{")
 	s = append(s, "ClusterID: "+fmt.Sprintf("%#v", this.ClusterID)+",\n")
 	s = append(s, "ClusterID: "+fmt.Sprintf("%#v", this.ClusterID)+",\n")
 	if this.ClusterVersion != nil {
 	if this.ClusterVersion != nil {
@@ -1895,6 +1934,7 @@ func (this *UpdateClusterRequest) GoString() string {
 	if this.Spec != nil {
 	if this.Spec != nil {
 		s = append(s, "Spec: "+fmt.Sprintf("%#v", this.Spec)+",\n")
 		s = append(s, "Spec: "+fmt.Sprintf("%#v", this.Spec)+",\n")
 	}
 	}
+	s = append(s, "Rotation: "+strings.Replace(this.Rotation.GoString(), `&`, ``, 1)+",\n")
 	s = append(s, "}")
 	s = append(s, "}")
 	return strings.Join(s, "")
 	return strings.Join(s, "")
 }
 }
@@ -4038,6 +4078,44 @@ func (m *ListClustersResponse) MarshalTo(data []byte) (int, error) {
 	return i, nil
 	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) {
 func (m *UpdateClusterRequest) Marshal() (data []byte, err error) {
 	size := m.Size()
 	size := m.Size()
 	data = make([]byte, size)
 	data = make([]byte, size)
@@ -4079,6 +4157,14 @@ func (m *UpdateClusterRequest) MarshalTo(data []byte) (int, error) {
 		}
 		}
 		i += n22
 		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
 	return i, nil
 }
 }
 
 
@@ -4101,11 +4187,11 @@ func (m *UpdateClusterResponse) MarshalTo(data []byte) (int, error) {
 		data[i] = 0xa
 		data[i] = 0xa
 		i++
 		i++
 		i = encodeVarintControl(data, i, uint64(m.Cluster.Size()))
 		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 {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n23
+		i += n24
 	}
 	}
 	return i, nil
 	return i, nil
 }
 }
@@ -5052,6 +5138,18 @@ func (m *ListClustersResponse) Size() (n int) {
 	return n
 	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) {
 func (m *UpdateClusterRequest) Size() (n int) {
 	var l int
 	var l int
 	_ = l
 	_ = l
@@ -5067,6 +5165,8 @@ func (m *UpdateClusterRequest) Size() (n int) {
 		l = m.Spec.Size()
 		l = m.Spec.Size()
 		n += 1 + l + sovControl(uint64(l))
 		n += 1 + l + sovControl(uint64(l))
 	}
 	}
+	l = m.Rotation.Size()
+	n += 1 + l + sovControl(uint64(l))
 	return n
 	return n
 }
 }
 
 
@@ -5575,6 +5675,17 @@ func (this *ListClustersResponse) String() string {
 	}, "")
 	}, "")
 	return s
 	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 {
 func (this *UpdateClusterRequest) String() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
@@ -5583,6 +5694,7 @@ func (this *UpdateClusterRequest) String() string {
 		`ClusterID:` + fmt.Sprintf("%v", this.ClusterID) + `,`,
 		`ClusterID:` + fmt.Sprintf("%v", this.ClusterID) + `,`,
 		`ClusterVersion:` + strings.Replace(fmt.Sprintf("%v", this.ClusterVersion), "Version", "Version", 1) + `,`,
 		`ClusterVersion:` + strings.Replace(fmt.Sprintf("%v", this.ClusterVersion), "Version", "Version", 1) + `,`,
 		`Spec:` + strings.Replace(fmt.Sprintf("%v", this.Spec), "ClusterSpec", "ClusterSpec", 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
 	return s
@@ -9955,6 +10067,96 @@ func (m *ListClustersResponse) Unmarshal(data []byte) error {
 	}
 	}
 	return nil
 	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 {
 func (m *UpdateClusterRequest) Unmarshal(data []byte) error {
 	l := len(data)
 	l := len(data)
 	iNdEx := 0
 	iNdEx := 0
@@ -10079,6 +10281,36 @@ func (m *UpdateClusterRequest) Unmarshal(data []byte) error {
 				return err
 				return err
 			}
 			}
 			iNdEx = postIndex
 			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:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
 			skippy, err := skipControl(data[iNdEx:])
 			skippy, err := skipControl(data[iNdEx:])
@@ -10289,93 +10521,99 @@ var (
 )
 )
 
 
 var fileDescriptorControl = []byte{
 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;
 	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 {
 message UpdateClusterRequest {
 	// ClusterID is the cluster ID to update.
 	// ClusterID is the cluster ID to update.
 	string cluster_id = 1 [(gogoproto.customname) = "ClusterID"];
 	string cluster_id = 1 [(gogoproto.customname) = "ClusterID"];
@@ -276,6 +284,9 @@ message UpdateClusterRequest {
 
 
 	// Spec is the new spec to apply to the cluster.
 	// Spec is the new spec to apply to the cluster.
 	ClusterSpec spec = 3;
 	ClusterSpec spec = 3;
+
+	// Rotation contains flags for join token rotation
+	JoinTokenRotation rotation = 4 [(gogoproto.nullable) = false];
 }
 }
 
 
 message UpdateClusterResponse {
 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.
 // ClusterSpec specifies global cluster settings.
 type ClusterSpec struct {
 type ClusterSpec struct {
 	Annotations Annotations `protobuf:"bytes,1,opt,name=annotations" json:"annotations"`
 	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"`
 	AcceptancePolicy AcceptancePolicy `protobuf:"bytes,2,opt,name=acceptance_policy,json=acceptancePolicy" json:"acceptance_policy"`
 	// Orchestration defines cluster-level orchestration settings.
 	// Orchestration defines cluster-level orchestration settings.
 	Orchestration OrchestrationConfig `protobuf:"bytes,3,opt,name=orchestration" json:"orchestration"`
 	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"`
 	Dispatcher DispatcherConfig `protobuf:"bytes,5,opt,name=dispatcher" json:"dispatcher"`
 	// CAConfig defines cluster-level certificate authority settings.
 	// CAConfig defines cluster-level certificate authority settings.
 	CAConfig CAConfig `protobuf:"bytes,6,opt,name=ca_config,json=caConfig" json:"ca_config"`
 	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{} }
 func (m *ClusterSpec) Reset()                    { *m = ClusterSpec{} }
@@ -759,7 +757,7 @@ func (m *ClusterSpec) Copy() *ClusterSpec {
 		Raft:             *m.Raft.Copy(),
 		Raft:             *m.Raft.Copy(),
 		Dispatcher:       *m.Dispatcher.Copy(),
 		Dispatcher:       *m.Dispatcher.Copy(),
 		CAConfig:         *m.CAConfig.Copy(),
 		CAConfig:         *m.CAConfig.Copy(),
-		DefaultLogDriver: m.DefaultLogDriver.Copy(),
+		TaskDefaults:     *m.TaskDefaults.Copy(),
 	}
 	}
 
 
 	return o
 	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, "Raft: "+strings.Replace(this.Raft.GoString(), `&`, ``, 1)+",\n")
 	s = append(s, "Dispatcher: "+strings.Replace(this.Dispatcher.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")
 	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, "}")
 	s = append(s, "}")
 	return strings.Join(s, "")
 	return strings.Join(s, "")
 }
 }
@@ -1621,16 +1617,14 @@ func (m *ClusterSpec) MarshalTo(data []byte) (int, error) {
 		return 0, err
 		return 0, err
 	}
 	}
 	i += n25
 	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
 	return i, nil
 }
 }
 
 
@@ -1909,10 +1903,8 @@ func (m *ClusterSpec) Size() (n int) {
 	n += 1 + l + sovSpecs(uint64(l))
 	n += 1 + l + sovSpecs(uint64(l))
 	l = m.CAConfig.Size()
 	l = m.CAConfig.Size()
 	n += 1 + l + sovSpecs(uint64(l))
 	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
 	return n
 }
 }
 
 
@@ -2106,7 +2098,7 @@ func (this *ClusterSpec) String() string {
 		`Raft:` + strings.Replace(strings.Replace(this.Raft.String(), "RaftConfig", "RaftConfig", 1), `&`, ``, 1) + `,`,
 		`Raft:` + strings.Replace(strings.Replace(this.Raft.String(), "RaftConfig", "RaftConfig", 1), `&`, ``, 1) + `,`,
 		`Dispatcher:` + strings.Replace(strings.Replace(this.Dispatcher.String(), "DispatcherConfig", "DispatcherConfig", 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) + `,`,
 		`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
 	return s
@@ -3976,7 +3968,7 @@ func (m *ClusterSpec) Unmarshal(data []byte) error {
 			iNdEx = postIndex
 			iNdEx = postIndex
 		case 7:
 		case 7:
 			if wireType != 2 {
 			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
 			var msglen int
 			for shift := uint(0); ; shift += 7 {
 			for shift := uint(0); ; shift += 7 {
@@ -4000,10 +3992,7 @@ func (m *ClusterSpec) Unmarshal(data []byte) error {
 			if postIndex > l {
 			if postIndex > l {
 				return io.ErrUnexpectedEOF
 				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
 				return err
 			}
 			}
 			iNdEx = postIndex
 			iNdEx = postIndex
@@ -4134,88 +4123,89 @@ var (
 )
 )
 
 
 var fileDescriptorSpecs = []byte{
 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,
 	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 {
 message ClusterSpec {
 	Annotations annotations = 1 [(gogoproto.nullable) = false];
 	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.
 	// Orchestration defines cluster-level orchestration settings.
 	OrchestrationConfig orchestration = 3 [(gogoproto.nullable) = false];
 	OrchestrationConfig orchestration = 3 [(gogoproto.nullable) = false];
@@ -248,10 +250,6 @@ message ClusterSpec {
 	// CAConfig defines cluster-level certificate authority settings.
 	// CAConfig defines cluster-level certificate authority settings.
 	CAConfig ca_config = 6 [(gogoproto.nullable) = false, (gogoproto.customname) = "CAConfig"];
 	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
 		ExternalCA
 		CAConfig
 		CAConfig
 		OrchestrationConfig
 		OrchestrationConfig
+		TaskDefaults
 		DispatcherConfig
 		DispatcherConfig
 		RaftConfig
 		RaftConfig
 		Placement
 		Placement
+		JoinTokens
 		RootCA
 		RootCA
 		Certificate
 		Certificate
 		EncryptionKey
 		EncryptionKey
@@ -104,6 +106,7 @@
 		GetClusterResponse
 		GetClusterResponse
 		ListClustersRequest
 		ListClustersRequest
 		ListClustersResponse
 		ListClustersResponse
+		JoinTokenRotation
 		UpdateClusterRequest
 		UpdateClusterRequest
 		UpdateClusterResponse
 		UpdateClusterResponse
 		SessionRequest
 		SessionRequest
@@ -509,7 +512,7 @@ func (x EncryptionKey_Algorithm) String() string {
 	return proto.EnumName(EncryptionKey_Algorithm_name, int32(x))
 	return proto.EnumName(EncryptionKey_Algorithm_name, int32(x))
 }
 }
 func (EncryptionKey_Algorithm) EnumDescriptor() ([]byte, []int) {
 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.
 // 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) ProtoMessage()               {}
 func (*OrchestrationConfig) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{26} }
 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.
 // DispatcherConfig defines cluster-level dispatcher settings.
 type DispatcherConfig struct {
 type DispatcherConfig struct {
 	// HeartbeatPeriod defines how often agent should send heartbeats to
 	// HeartbeatPeriod defines how often agent should send heartbeats to
@@ -1057,7 +1074,7 @@ type DispatcherConfig struct {
 
 
 func (m *DispatcherConfig) Reset()                    { *m = DispatcherConfig{} }
 func (m *DispatcherConfig) Reset()                    { *m = DispatcherConfig{} }
 func (*DispatcherConfig) ProtoMessage()               {}
 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.
 // RaftConfig defines raft settings for the cluster.
 type RaftConfig struct {
 type RaftConfig struct {
@@ -1079,7 +1096,7 @@ type RaftConfig struct {
 
 
 func (m *RaftConfig) Reset()                    { *m = RaftConfig{} }
 func (m *RaftConfig) Reset()                    { *m = RaftConfig{} }
 func (*RaftConfig) ProtoMessage()               {}
 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.
 // Placement specifies task distribution constraints.
 type Placement struct {
 type Placement struct {
@@ -1089,7 +1106,19 @@ type Placement struct {
 
 
 func (m *Placement) Reset()                    { *m = Placement{} }
 func (m *Placement) Reset()                    { *m = Placement{} }
 func (*Placement) ProtoMessage()               {}
 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 {
 type RootCA struct {
 	// CAKey is the root CA private key.
 	// 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"`
 	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 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"`
 	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 (m *RootCA) Reset()                    { *m = RootCA{} }
 func (*RootCA) ProtoMessage()               {}
 func (*RootCA) ProtoMessage()               {}
-func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{30} }
+func (*RootCA) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{32} }
 
 
 type Certificate struct {
 type Certificate struct {
 	Role        NodeRole       `protobuf:"varint,1,opt,name=role,proto3,enum=docker.swarmkit.v1.NodeRole" json:"role,omitempty"`
 	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 (m *Certificate) Reset()                    { *m = Certificate{} }
 func (*Certificate) ProtoMessage()               {}
 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.
 // Symmetric keys to encrypt inter-agent communication.
 type EncryptionKey struct {
 type EncryptionKey struct {
@@ -1131,7 +1162,7 @@ type EncryptionKey struct {
 
 
 func (m *EncryptionKey) Reset()                    { *m = EncryptionKey{} }
 func (m *EncryptionKey) Reset()                    { *m = EncryptionKey{} }
 func (*EncryptionKey) ProtoMessage()               {}
 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.
 // ManagerStatus provides informations about the state of a manager in the cluster.
 type ManagerStatus struct {
 type ManagerStatus struct {
@@ -1148,7 +1179,7 @@ type ManagerStatus struct {
 
 
 func (m *ManagerStatus) Reset()                    { *m = ManagerStatus{} }
 func (m *ManagerStatus) Reset()                    { *m = ManagerStatus{} }
 func (*ManagerStatus) ProtoMessage()               {}
 func (*ManagerStatus) ProtoMessage()               {}
-func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{33} }
+func (*ManagerStatus) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{35} }
 
 
 func init() {
 func init() {
 	proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
 	proto.RegisterType((*Version)(nil), "docker.swarmkit.v1.Version")
@@ -1183,9 +1214,11 @@ func init() {
 	proto.RegisterType((*ExternalCA)(nil), "docker.swarmkit.v1.ExternalCA")
 	proto.RegisterType((*ExternalCA)(nil), "docker.swarmkit.v1.ExternalCA")
 	proto.RegisterType((*CAConfig)(nil), "docker.swarmkit.v1.CAConfig")
 	proto.RegisterType((*CAConfig)(nil), "docker.swarmkit.v1.CAConfig")
 	proto.RegisterType((*OrchestrationConfig)(nil), "docker.swarmkit.v1.OrchestrationConfig")
 	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((*DispatcherConfig)(nil), "docker.swarmkit.v1.DispatcherConfig")
 	proto.RegisterType((*RaftConfig)(nil), "docker.swarmkit.v1.RaftConfig")
 	proto.RegisterType((*RaftConfig)(nil), "docker.swarmkit.v1.RaftConfig")
 	proto.RegisterType((*Placement)(nil), "docker.swarmkit.v1.Placement")
 	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((*RootCA)(nil), "docker.swarmkit.v1.RootCA")
 	proto.RegisterType((*Certificate)(nil), "docker.swarmkit.v1.Certificate")
 	proto.RegisterType((*Certificate)(nil), "docker.swarmkit.v1.Certificate")
 	proto.RegisterType((*EncryptionKey)(nil), "docker.swarmkit.v1.EncryptionKey")
 	proto.RegisterType((*EncryptionKey)(nil), "docker.swarmkit.v1.EncryptionKey")
@@ -1705,6 +1738,18 @@ func (m *OrchestrationConfig) Copy() *OrchestrationConfig {
 	return o
 	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 {
 func (m *DispatcherConfig) Copy() *DispatcherConfig {
 	if m == nil {
 	if m == nil {
 		return nil
 		return nil
@@ -1750,6 +1795,19 @@ func (m *Placement) Copy() *Placement {
 	return o
 	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 {
 func (m *RootCA) Copy() *RootCA {
 	if m == nil {
 	if m == nil {
 		return nil
 		return nil
@@ -1759,6 +1817,7 @@ func (m *RootCA) Copy() *RootCA {
 		CAKey:      m.CAKey,
 		CAKey:      m.CAKey,
 		CACert:     m.CACert,
 		CACert:     m.CACert,
 		CACertHash: m.CACertHash,
 		CACertHash: m.CACertHash,
+		JoinTokens: *m.JoinTokens.Copy(),
 	}
 	}
 
 
 	return o
 	return o
@@ -2302,6 +2361,18 @@ func (this *OrchestrationConfig) GoString() string {
 	s = append(s, "}")
 	s = append(s, "}")
 	return strings.Join(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 {
 func (this *DispatcherConfig) GoString() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
@@ -2338,15 +2409,27 @@ func (this *Placement) GoString() string {
 	s = append(s, "}")
 	s = append(s, "}")
 	return strings.Join(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 {
 func (this *RootCA) GoString() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
 	}
 	}
-	s := make([]string, 0, 7)
+	s := make([]string, 0, 8)
 	s = append(s, "&api.RootCA{")
 	s = append(s, "&api.RootCA{")
 	s = append(s, "CAKey: "+fmt.Sprintf("%#v", this.CAKey)+",\n")
 	s = append(s, "CAKey: "+fmt.Sprintf("%#v", this.CAKey)+",\n")
 	s = append(s, "CACert: "+fmt.Sprintf("%#v", this.CACert)+",\n")
 	s = append(s, "CACert: "+fmt.Sprintf("%#v", this.CACert)+",\n")
 	s = append(s, "CACertHash: "+fmt.Sprintf("%#v", this.CACertHash)+",\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, "}")
 	s = append(s, "}")
 	return strings.Join(s, "")
 	return strings.Join(s, "")
 }
 }
@@ -3646,6 +3729,34 @@ func (m *OrchestrationConfig) MarshalTo(data []byte) (int, error) {
 	return i, nil
 	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) {
 func (m *DispatcherConfig) Marshal() (data []byte, err error) {
 	size := m.Size()
 	size := m.Size()
 	data = make([]byte, size)
 	data = make([]byte, size)
@@ -3665,11 +3776,11 @@ func (m *DispatcherConfig) MarshalTo(data []byte) (int, error) {
 		data[i] = 0xa
 		data[i] = 0xa
 		i++
 		i++
 		i = encodeVarintTypes(data, i, uint64(m.HeartbeatPeriod.Size()))
 		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 {
 		if err != nil {
 			return 0, err
 			return 0, err
 		}
 		}
-		i += n20
+		i += n21
 	}
 	}
 	return i, nil
 	return i, nil
 }
 }
@@ -3750,6 +3861,36 @@ func (m *Placement) MarshalTo(data []byte) (int, error) {
 	return i, nil
 	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) {
 func (m *RootCA) Marshal() (data []byte, err error) {
 	size := m.Size()
 	size := m.Size()
 	data = make([]byte, 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 = encodeVarintTypes(data, i, uint64(len(m.CACertHash)))
 		i += copy(data[i:], 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
 	return i, nil
 }
 }
 
 
@@ -3815,11 +3964,11 @@ func (m *Certificate) MarshalTo(data []byte) (int, error) {
 	data[i] = 0x1a
 	data[i] = 0x1a
 	i++
 	i++
 	i = encodeVarintTypes(data, i, uint64(m.Status.Size()))
 	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 {
 	if err != nil {
 		return 0, err
 		return 0, err
 	}
 	}
-	i += n21
+	i += n23
 	if len(m.Certificate) > 0 {
 	if len(m.Certificate) > 0 {
 		data[i] = 0x22
 		data[i] = 0x22
 		i++
 		i++
@@ -4477,6 +4626,16 @@ func (m *OrchestrationConfig) Size() (n int) {
 	return n
 	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) {
 func (m *DispatcherConfig) Size() (n int) {
 	var l int
 	var l int
 	_ = l
 	_ = l
@@ -4520,6 +4679,20 @@ func (m *Placement) Size() (n int) {
 	return n
 	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) {
 func (m *RootCA) Size() (n int) {
 	var l int
 	var l int
 	_ = l
 	_ = l
@@ -4535,6 +4708,8 @@ func (m *RootCA) Size() (n int) {
 	if l > 0 {
 	if l > 0 {
 		n += 1 + l + sovTypes(uint64(l))
 		n += 1 + l + sovTypes(uint64(l))
 	}
 	}
+	l = m.JoinTokens.Size()
+	n += 1 + l + sovTypes(uint64(l))
 	return n
 	return n
 }
 }
 
 
@@ -5053,6 +5228,16 @@ func (this *OrchestrationConfig) String() string {
 	}, "")
 	}, "")
 	return s
 	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 {
 func (this *DispatcherConfig) String() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
@@ -5087,6 +5272,17 @@ func (this *Placement) String() string {
 	}, "")
 	}, "")
 	return s
 	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 {
 func (this *RootCA) String() string {
 	if this == nil {
 	if this == nil {
 		return "nil"
 		return "nil"
@@ -5095,6 +5291,7 @@ func (this *RootCA) String() string {
 		`CAKey:` + fmt.Sprintf("%v", this.CAKey) + `,`,
 		`CAKey:` + fmt.Sprintf("%v", this.CAKey) + `,`,
 		`CACert:` + fmt.Sprintf("%v", this.CACert) + `,`,
 		`CACert:` + fmt.Sprintf("%v", this.CACert) + `,`,
 		`CACertHash:` + fmt.Sprintf("%v", this.CACertHash) + `,`,
 		`CACertHash:` + fmt.Sprintf("%v", this.CACertHash) + `,`,
+		`JoinTokens:` + strings.Replace(strings.Replace(this.JoinTokens.String(), "JoinTokens", "JoinTokens", 1), `&`, ``, 1) + `,`,
 		`}`,
 		`}`,
 	}, "")
 	}, "")
 	return s
 	return s
@@ -9419,6 +9616,89 @@ func (m *OrchestrationConfig) Unmarshal(data []byte) error {
 	}
 	}
 	return nil
 	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 {
 func (m *DispatcherConfig) Unmarshal(data []byte) error {
 	l := len(data)
 	l := len(data)
 	iNdEx := 0
 	iNdEx := 0
@@ -9726,6 +10006,114 @@ func (m *Placement) Unmarshal(data []byte) error {
 	}
 	}
 	return nil
 	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 {
 func (m *RootCA) Unmarshal(data []byte) error {
 	l := len(data)
 	l := len(data)
 	iNdEx := 0
 	iNdEx := 0
@@ -9846,6 +10234,36 @@ func (m *RootCA) Unmarshal(data []byte) error {
 			}
 			}
 			m.CACertHash = string(data[iNdEx:postIndex])
 			m.CACertHash = string(data[iNdEx:postIndex])
 			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:
 		default:
 			iNdEx = preIndex
 			iNdEx = preIndex
 			skippy, err := skipTypes(data[iNdEx:])
 			skippy, err := skipTypes(data[iNdEx:])
@@ -10448,201 +10866,206 @@ var (
 )
 )
 
 
 var fileDescriptorTypes = []byte{
 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,
 	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
 	// TaskHistoryRetentionLimit is the number of historic tasks to keep per instance or
 	// node. If negative, never remove completed or failed tasks.
 	// node. If negative, never remove completed or failed tasks.
 	int64 task_history_retention_limit = 1;
 	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.
 // DispatcherConfig defines cluster-level dispatcher settings.
@@ -554,6 +565,15 @@ message Placement {
 	repeated string constraints = 1;
 	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 {
 message RootCA {
 	// CAKey is the root CA private key.
 	// CAKey is the root CA private key.
 	bytes ca_key = 1 [(gogoproto.customname) = "CAKey"];
 	bytes ca_key = 1 [(gogoproto.customname) = "CAKey"];
@@ -563,6 +583,9 @@ message RootCA {
 
 
 	// CACertHash is the digest of the CA Certificate.
 	// CACertHash is the digest of the CA Certificate.
 	string ca_cert_hash = 3 [(gogoproto.customname) = "CACertHash"];
 	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
 // 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.
 // 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
 	// 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
 	// Write the new CSR and the new key to a temporary location so we can survive crashes on rotation
 	tempPaths := genTempPaths(paths)
 	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).
 	// responding properly (for example, it may have just been demoted).
 	var signedCert []byte
 	var signedCert []byte
 	for i := 0; i != 5; i++ {
 	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 {
 		if err == nil {
 			break
 			break
 		}
 		}
@@ -207,7 +207,9 @@ func (rca *RootCA) RequestAndSaveNewCertificates(ctx context.Context, paths Cert
 		return nil, err
 		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
 	// Ensure directory exists
 	err = os.MkdirAll(filepath.Dir(paths.Cert), 0755)
 	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{}, 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
 // 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
 	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 {
 	if rootCAPool == nil {
 		return nil, fmt.Errorf("valid root CA pool required")
 		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
 	// Create a CAClient to retrieve a new Certificate
 	caClient := api.NewNodeCAClient(conn)
 	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
 	// 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)
 	issueResponse, err := caClient.IssueNodeCertificate(ctx, issueRequest)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err

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

@@ -1,11 +1,14 @@
 package ca
 package ca
 
 
 import (
 import (
+	cryptorand "crypto/rand"
 	"crypto/tls"
 	"crypto/tls"
 	"crypto/x509"
 	"crypto/x509"
 	"encoding/pem"
 	"encoding/pem"
+	"errors"
 	"fmt"
 	"fmt"
 	"io/ioutil"
 	"io/ioutil"
+	"math/big"
 	"math/rand"
 	"math/rand"
 	"path/filepath"
 	"path/filepath"
 	"strings"
 	"strings"
@@ -28,9 +31,7 @@ const (
 	nodeTLSCertFilename = "swarm-node.crt"
 	nodeTLSCertFilename = "swarm-node.crt"
 	nodeTLSKeyFilename  = "swarm-node.key"
 	nodeTLSKeyFilename  = "swarm-node.key"
 	nodeCSRFilename     = "swarm-node.csr"
 	nodeCSRFilename     = "swarm-node.csr"
-)
 
 
-const (
 	rootCN = "swarm-ca"
 	rootCN = "swarm-ca"
 	// ManagerRole represents the Manager node type, and is used for authorization to endpoints
 	// ManagerRole represents the Manager node type, and is used for authorization to endpoints
 	ManagerRole = "swarm-manager"
 	ManagerRole = "swarm-manager"
@@ -38,6 +39,13 @@ const (
 	AgentRole = "swarm-worker"
 	AgentRole = "swarm-worker"
 	// CARole represents the CA node type, and is used for clients attempting to get new certificates issued
 	// CARole represents the CA node type, and is used for clients attempting to get new certificates issued
 	CARole = "swarm-ca"
 	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
 // 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.
 // 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.
 // 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.
 // 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)
 	paths := NewConfigPaths(baseCertDir)
 
 
 	var (
 	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
 		// 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
 		// If we were provided a non-empty string, and it is an invalid hash, return
 		// otherwise, allow the invalid digest through.
 		// 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
 		// Get the remote CA certificate, verify integrity with the
@@ -232,7 +269,7 @@ func LoadOrCreateSecurityConfig(ctx context.Context, baseCertDir, caHash, secret
 		} else {
 		} else {
 			// There was an error loading our Credentials, let's get a new certificate issued
 			// 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
 			// 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 {
 			if err != nil {
 				return nil, err
 				return nil, err
 			}
 			}
@@ -304,11 +341,10 @@ func RenewTLSConfig(ctx context.Context, s *SecurityConfig, baseCertDir string,
 			}
 			}
 			log.Infof("Renewing TLS Certificate.")
 			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()
 			rootCA := s.RootCA()
 			tlsKeyPair, err := rootCA.RequestAndSaveNewCertificates(ctx,
 			tlsKeyPair, err := rootCA.RequestAndSaveNewCertificates(ctx,
 				paths.Node,
 				paths.Node,
-				s.ClientTLSCreds.Role(),
 				"",
 				"",
 				picker,
 				picker,
 				s.ClientTLSCreds,
 				s.ClientTLSCreds,

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

@@ -2,9 +2,7 @@ package ca
 
 
 import (
 import (
 	"crypto/subtle"
 	"crypto/subtle"
-	"errors"
 	"fmt"
 	"fmt"
-	"strings"
 	"sync"
 	"sync"
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
@@ -14,7 +12,6 @@ import (
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/protobuf/ptypes"
 	"github.com/docker/swarmkit/protobuf/ptypes"
-	"golang.org/x/crypto/bcrypt"
 	"golang.org/x/net/context"
 	"golang.org/x/net/context"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/codes"
@@ -25,35 +22,19 @@ import (
 // CA, NodeCA, and other hypothetical future CA services. At the moment,
 // CA, NodeCA, and other hypothetical future CA services. At the moment,
 // breaking it apart doesn't seem worth it.
 // breaking it apart doesn't seem worth it.
 type Server struct {
 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
 	// Started is a channel which gets closed once the server is running
 	// and able to service RPCs.
 	// and able to service RPCs.
 	started chan struct{}
 	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.
 // DefaultCAConfig returns the default CA Config, with a default expiration.
 func DefaultCAConfig() api.CAConfig {
 func DefaultCAConfig() api.CAConfig {
 	return 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,
 // IssueNodeCertificate is responsible for gatekeeping both certificate requests from new nodes in the swarm,
 // and authorizing certificate renewals.
 // and authorizing certificate renewals.
 // If a node presented a valid certificate, the corresponding certificate is set in a RENEW state.
 // 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) {
 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())
 		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)
 		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
 	// 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
 	// 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{
 				Certificate: api.Certificate{
 					CSR:  request.CSR,
 					CSR:  request.CSR,
 					CN:   nodeID,
 					CN:   nodeID,
-					Role: request.Role,
+					Role: role,
 					Status: api.IssuanceStatus{
 					Status: api.IssuanceStatus{
 						State: api.IssuanceStatePending,
 						State: api.IssuanceStatePending,
 					},
 					},
 				},
 				},
 				Spec: api.NodeSpec{
 				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 {
 		if err == nil {
 			log.G(ctx).WithFields(logrus.Fields{
 			log.G(ctx).WithFields(logrus.Fields{
 				"node.id":   nodeID,
 				"node.id":   nodeID,
-				"node.role": request.Role,
+				"node.role": role,
 				"method":    "IssueNodeCertificate",
 				"method":    "IssueNodeCertificate",
 			}).Debugf("new certificate entry added")
 			}).Debugf("new certificate entry added")
 			break
 			break
@@ -245,55 +221,17 @@ func (s *Server) IssueNodeCertificate(ctx context.Context, request *api.IssueNod
 		}
 		}
 		log.G(ctx).WithFields(logrus.Fields{
 		log.G(ctx).WithFields(logrus.Fields{
 			"node.id":   nodeID,
 			"node.id":   nodeID,
-			"node.role": request.Role,
+			"node.role": role,
 			"method":    "IssueNodeCertificate",
 			"method":    "IssueNodeCertificate",
 		}).Errorf("randomly generated node ID collided with an existing one - retrying")
 		}).Errorf("randomly generated node ID collided with an existing one - retrying")
 	}
 	}
 
 
 	return &api.IssueNodeCertificateResponse{
 	return &api.IssueNodeCertificateResponse{
 		NodeID:         nodeID,
 		NodeID:         nodeID,
-		NodeMembership: nodeMembership,
+		NodeMembership: api.NodeMembershipAccepted,
 	}, nil
 	}, 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
 // 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
 // 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) {
 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")
 		return fmt.Errorf("CA signer is already running")
 	}
 	}
 	s.wg.Add(1)
 	s.wg.Add(1)
+	s.mu.Unlock()
+
 	defer s.wg.Done()
 	defer s.wg.Done()
 	logger := log.G(ctx).WithField("module", "ca")
 	logger := log.G(ctx).WithField("module", "ca")
 	ctx = log.WithLogger(ctx, logger)
 	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
 	// Run() should never be called twice, but just in case, we're
 	// attempting to close the started channel in a safe way
 	// 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.EventUpdateNode{},
 		state.EventUpdateCluster{},
 		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 {
 	if err != nil {
 		log.G(ctx).WithFields(logrus.Fields{
 		log.G(ctx).WithFields(logrus.Fields{
 			"method": "(*Server).Run",
 			"method": "(*Server).Run",
@@ -497,7 +442,7 @@ func (s *Server) isRunning() bool {
 // always aware of changes in clusterExpiry and the Root CA key material
 // always aware of changes in clusterExpiry and the Root CA key material
 func (s *Server) updateCluster(ctx context.Context, cluster *api.Cluster) {
 func (s *Server) updateCluster(ctx context.Context, cluster *api.Cluster) {
 	s.mu.Lock()
 	s.mu.Lock()
-	s.acceptancePolicy = cluster.Spec.AcceptancePolicy.Copy()
+	s.joinTokens = cluster.RootCA.JoinTokens.Copy()
 	s.mu.Unlock()
 	s.mu.Unlock()
 	var err error
 	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.Meta.Version = *request.ClusterVersion
 		cluster.Spec = *request.Spec.Copy()
 		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)
 		return store.UpdateCluster(tx, cluster)
 	})
 	})
 	if err != nil {
 	if err != nil {
@@ -193,6 +200,7 @@ func redactClusters(clusters []*api.Cluster) []*api.Cluster {
 			RootCA: api.RootCA{
 			RootCA: api.RootCA{
 				CACert:     cluster.RootCA.CACert,
 				CACert:     cluster.RootCA.CACert,
 				CACertHash: cluster.RootCA.CACertHash,
 				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 (
 import (
 	"errors"
 	"errors"
 
 
+	"github.com/docker/swarmkit/ca"
 	"github.com/docker/swarmkit/manager/state/raft"
 	"github.com/docker/swarmkit/manager/state/raft"
 	"github.com/docker/swarmkit/manager/state/store"
 	"github.com/docker/swarmkit/manager/state/store"
 )
 )
@@ -14,14 +15,16 @@ var (
 
 
 // Server is the Cluster API gRPC server.
 // Server is the Cluster API gRPC server.
 type Server struct {
 type Server struct {
-	store *store.MemoryStore
-	raft  *raft.Node
+	store  *store.MemoryStore
+	raft   *raft.Node
+	rootCA *ca.RootCA
 }
 }
 
 
 // NewServer creates a Cluster API server.
 // 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{
 	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.
 // plane information. It can also be used to encrypt overlay data traffic.
 import (
 import (
 	"crypto/rand"
 	"crypto/rand"
+	"encoding/binary"
 	"fmt"
 	"fmt"
 	"sync"
 	"sync"
 	"time"
 	"time"
@@ -87,7 +88,7 @@ func New(store *store.MemoryStore, config *Config) *KeyManager {
 	return &KeyManager{
 	return &KeyManager{
 		config:  config,
 		config:  config,
 		store:   store,
 		store:   store,
-		keyRing: &keyRing{},
+		keyRing: &keyRing{lClock: genSkew()},
 	}
 	}
 }
 }
 
 
@@ -230,3 +231,12 @@ func (k *KeyManager) Stop() error {
 	k.cancel()
 	k.cancel()
 	return nil
 	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{
 							Annotations: api.Annotations{
 								Name: store.DefaultClusterName,
 								Name: store.DefaultClusterName,
 							},
 							},
-							AcceptancePolicy: ca.DefaultAcceptancePolicy(),
 							Orchestration: api.OrchestrationConfig{
 							Orchestration: api.OrchestrationConfig{
 								TaskHistoryRetentionLimit: defaultTaskHistoryRetentionLimit,
 								TaskHistoryRetentionLimit: defaultTaskHistoryRetentionLimit,
 							},
 							},
@@ -315,6 +314,10 @@ func (m *Manager) Run(parent context.Context) error {
 							CAKey:      rootCA.Key,
 							CAKey:      rootCA.Key,
 							CACert:     rootCA.Cert,
 							CACert:     rootCA.Cert,
 							CACertHash: rootCA.Digest.String(),
 							CACertHash: rootCA.Digest.String(),
+							JoinTokens: api.JoinTokens{
+								Worker:  ca.GenerateJoinToken(rootCA),
+								Manager: ca.GenerateJoinToken(rootCA),
+							},
 						},
 						},
 					})
 					})
 					// Add Node entry for ourself, if one
 					// Add Node entry for ourself, if one
@@ -449,7 +452,7 @@ func (m *Manager) Run(parent context.Context) error {
 		return err
 		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()
 	healthServer := health.NewHealthServer()
 
 
 	authenticatedControlAPI := api.NewAuthenticatedWrapperControlServer(baseControlAPI, authorize)
 	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
 		logDriver = service.Spec.Task.LogDriver
 	} else if cluster != nil {
 	} else if cluster != nil {
 		// pick up the cluster default, if available.
 		// 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
 	// 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,
-}