Browse code

vendor docker/engine-api@f9cef590446e4e6073b49b652f47a337b897c1a3

Signed-off-by: Antonio Murdaca <runcom@redhat.com>

Antonio Murdaca authored on 2016/09/01 00:25:14
Showing 26 changed files
... ...
@@ -135,13 +135,21 @@ func runUpdate(dockerCli *client.DockerCli, opts *updateOptions) error {
135 135
 
136 136
 	ctx := context.Background()
137 137
 
138
-	var errs []string
138
+	var (
139
+		warns []string
140
+		errs  []string
141
+	)
139 142
 	for _, container := range opts.containers {
140
-		if err := dockerCli.Client().ContainerUpdate(ctx, container, updateConfig); err != nil {
143
+		r, err := dockerCli.Client().ContainerUpdate(ctx, container, updateConfig)
144
+		if err != nil {
141 145
 			errs = append(errs, err.Error())
142 146
 		} else {
143 147
 			fmt.Fprintf(dockerCli.Out(), "%s\n", container)
144 148
 		}
149
+		warns = append(warns, r.Warnings...)
150
+	}
151
+	if len(warns) > 0 {
152
+		fmt.Fprintf(dockerCli.Out(), "%s", strings.Join(warns, "\n"))
145 153
 	}
146 154
 	if len(errs) > 0 {
147 155
 		return fmt.Errorf("%s", strings.Join(errs, "\n"))
... ...
@@ -79,7 +79,7 @@ func runCreate(dockerCli *client.DockerCli, opts createOptions) error {
79 79
 	nc := types.NetworkCreate{
80 80
 		Driver:  opts.driver,
81 81
 		Options: opts.driverOpts.GetAll(),
82
-		IPAM: network.IPAM{
82
+		IPAM: &network.IPAM{
83 83
 			Driver:  opts.ipamDriver,
84 84
 			Config:  ipamCfg,
85 85
 			Options: opts.ipamOpt.GetAll(),
... ...
@@ -12,7 +12,6 @@ import (
12 12
 	"github.com/docker/docker/api/client/bundlefile"
13 13
 	"github.com/docker/docker/cli"
14 14
 	"github.com/docker/engine-api/types"
15
-	"github.com/docker/engine-api/types/network"
16 15
 	"github.com/docker/engine-api/types/swarm"
17 16
 )
18 17
 
... ...
@@ -105,8 +104,6 @@ func updateNetworks(
105 105
 	createOpts := types.NetworkCreate{
106 106
 		Labels: getStackLabels(namespace, nil),
107 107
 		Driver: defaultNetworkDriver,
108
-		// TODO: remove when engine-api uses omitempty for IPAM
109
-		IPAM: network.IPAM{Driver: "default"},
110 108
 	}
111 109
 
112 110
 	for _, internalName := range networks {
... ...
@@ -172,7 +172,7 @@ func addSwarmFlags(flags *pflag.FlagSet, opts *swarmOptions) {
172 172
 func (opts *swarmOptions) ToSpec() swarm.Spec {
173 173
 	spec := swarm.Spec{}
174 174
 	spec.Orchestration.TaskHistoryRetentionLimit = opts.taskHistoryLimit
175
-	spec.Dispatcher.HeartbeatPeriod = uint64(opts.dispatcherHeartbeat.Nanoseconds())
175
+	spec.Dispatcher.HeartbeatPeriod = opts.dispatcherHeartbeat
176 176
 	spec.CAConfig.NodeCertExpiry = opts.nodeCertExpiry
177 177
 	spec.CAConfig.ExternalCAs = opts.externalCA.Value()
178 178
 	return spec
... ...
@@ -63,7 +63,7 @@ func mergeSwarm(swarm *swarm.Swarm, flags *pflag.FlagSet) error {
63 63
 
64 64
 	if flags.Changed(flagDispatcherHeartbeat) {
65 65
 		if v, err := flags.GetDuration(flagDispatcherHeartbeat); err == nil {
66
-			spec.Dispatcher.HeartbeatPeriod = uint64(v.Nanoseconds())
66
+			spec.Dispatcher.HeartbeatPeriod = v
67 67
 		}
68 68
 	}
69 69
 
... ...
@@ -42,7 +42,7 @@ type stateBackend interface {
42 42
 	ContainerStart(name string, hostConfig *container.HostConfig, validateHostname bool) error
43 43
 	ContainerStop(name string, seconds int) error
44 44
 	ContainerUnpause(name string) error
45
-	ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error)
45
+	ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) (types.ContainerUpdateResponse, error)
46 46
 	ContainerWait(name string, timeout time.Duration) (int, error)
47 47
 }
48 48
 
... ...
@@ -327,14 +327,12 @@ func (s *containerRouter) postContainerUpdate(ctx context.Context, w http.Respon
327 327
 
328 328
 	name := vars["name"]
329 329
 	validateHostname := versions.GreaterThanOrEqualTo(version, "1.24")
330
-	warnings, err := s.backend.ContainerUpdate(name, hostConfig, validateHostname)
330
+	resp, err := s.backend.ContainerUpdate(name, hostConfig, validateHostname)
331 331
 	if err != nil {
332 332
 		return err
333 333
 	}
334 334
 
335
-	return httputils.WriteJSON(w, http.StatusOK, &types.ContainerUpdateResponse{
336
-		Warnings: warnings,
337
-	})
335
+	return httputils.WriteJSON(w, http.StatusOK, resp)
338 336
 }
339 337
 
340 338
 func (s *containerRouter) postContainersCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -67,7 +67,7 @@ var defaultSpec = types.Spec{
67 67
 		NodeCertExpiry: 90 * 24 * time.Hour,
68 68
 	},
69 69
 	Dispatcher: types.DispatcherConfig{
70
-		HeartbeatPeriod: uint64((5 * time.Second).Nanoseconds()),
70
+		HeartbeatPeriod: 5 * time.Second,
71 71
 	},
72 72
 	Orchestration: types.OrchestrationConfig{
73 73
 		TaskHistoryRetentionLimit: 10,
... ...
@@ -179,21 +179,23 @@ func BasicNetworkCreateToGRPC(create basictypes.NetworkCreateRequest) swarmapi.N
179 179
 		},
180 180
 		Ipv6Enabled: create.EnableIPv6,
181 181
 		Internal:    create.Internal,
182
-		IPAM: &swarmapi.IPAMOptions{
182
+	}
183
+	if create.IPAM != nil {
184
+		ns.IPAM = &swarmapi.IPAMOptions{
183 185
 			Driver: &swarmapi.Driver{
184 186
 				Name:    create.IPAM.Driver,
185 187
 				Options: create.IPAM.Options,
186 188
 			},
187
-		},
188
-	}
189
-	ipamSpec := make([]*swarmapi.IPAMConfig, 0, len(create.IPAM.Config))
190
-	for _, ipamConfig := range create.IPAM.Config {
191
-		ipamSpec = append(ipamSpec, &swarmapi.IPAMConfig{
192
-			Subnet:  ipamConfig.Subnet,
193
-			Range:   ipamConfig.IPRange,
194
-			Gateway: ipamConfig.Gateway,
195
-		})
189
+		}
190
+		ipamSpec := make([]*swarmapi.IPAMConfig, 0, len(create.IPAM.Config))
191
+		for _, ipamConfig := range create.IPAM.Config {
192
+			ipamSpec = append(ipamSpec, &swarmapi.IPAMConfig{
193
+				Subnet:  ipamConfig.Subnet,
194
+				Range:   ipamConfig.IPRange,
195
+				Gateway: ipamConfig.Gateway,
196
+			})
197
+		}
198
+		ns.IPAM.Configs = ipamSpec
196 199
 	}
197
-	ns.IPAM.Configs = ipamSpec
198 200
 	return ns
199 201
 }
... ...
@@ -23,8 +23,8 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
23 23
 					SnapshotInterval:           c.Spec.Raft.SnapshotInterval,
24 24
 					KeepOldSnapshots:           c.Spec.Raft.KeepOldSnapshots,
25 25
 					LogEntriesForSlowFollowers: c.Spec.Raft.LogEntriesForSlowFollowers,
26
-					HeartbeatTick:              c.Spec.Raft.HeartbeatTick,
27
-					ElectionTick:               c.Spec.Raft.ElectionTick,
26
+					HeartbeatTick:              int(c.Spec.Raft.HeartbeatTick),
27
+					ElectionTick:               int(c.Spec.Raft.ElectionTick),
28 28
 				},
29 29
 			},
30 30
 		},
... ...
@@ -35,7 +35,7 @@ func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
35 35
 	}
36 36
 
37 37
 	heartbeatPeriod, _ := ptypes.Duration(c.Spec.Dispatcher.HeartbeatPeriod)
38
-	swarm.Spec.Dispatcher.HeartbeatPeriod = uint64(heartbeatPeriod)
38
+	swarm.Spec.Dispatcher.HeartbeatPeriod = heartbeatPeriod
39 39
 
40 40
 	swarm.Spec.CAConfig.NodeCertExpiry, _ = ptypes.Duration(c.Spec.CAConfig.NodeCertExpiry)
41 41
 
... ...
@@ -73,8 +73,8 @@ func SwarmSpecToGRPC(s types.Spec) (swarmapi.ClusterSpec, error) {
73 73
 			SnapshotInterval:           s.Raft.SnapshotInterval,
74 74
 			KeepOldSnapshots:           s.Raft.KeepOldSnapshots,
75 75
 			LogEntriesForSlowFollowers: s.Raft.LogEntriesForSlowFollowers,
76
-			HeartbeatTick:              s.Raft.HeartbeatTick,
77
-			ElectionTick:               s.Raft.ElectionTick,
76
+			HeartbeatTick:              uint32(s.Raft.HeartbeatTick),
77
+			ElectionTick:               uint32(s.Raft.ElectionTick),
78 78
 		},
79 79
 		Dispatcher: swarmapi.DispatcherConfig{
80 80
 			HeartbeatPeriod: ptypes.DurationProto(time.Duration(s.Dispatcher.HeartbeatPeriod)),
... ...
@@ -478,7 +478,7 @@ func (c *containerConfig) networkCreateRequest(name string) (clustertypes.Networ
478 478
 	options := types.NetworkCreate{
479 479
 		// ID:     na.Network.ID,
480 480
 		Driver: na.Network.DriverState.Name,
481
-		IPAM: network.IPAM{
481
+		IPAM: &network.IPAM{
482 482
 			Driver: na.Network.IPAM.Driver.Name,
483 483
 		},
484 484
 		Options:        na.Network.DriverState.Options,
... ...
@@ -94,7 +94,7 @@ func (e *executor) Configure(ctx context.Context, node *api.Node) error {
94 94
 
95 95
 	options := types.NetworkCreate{
96 96
 		Driver: na.Network.DriverState.Name,
97
-		IPAM: network.IPAM{
97
+		IPAM: &network.IPAM{
98 98
 			Driver: na.Network.IPAM.Driver.Name,
99 99
 		},
100 100
 		Options:        na.Network.DriverState.Options,
... ...
@@ -234,18 +234,21 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string
234 234
 		driver = c.Config().Daemon.DefaultDriver
235 235
 	}
236 236
 
237
-	ipam := create.IPAM
238
-	v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
239
-	if err != nil {
240
-		return nil, err
241
-	}
242
-
243 237
 	nwOptions := []libnetwork.NetworkOption{
244
-		libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options),
245 238
 		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
246 239
 		libnetwork.NetworkOptionDriverOpts(create.Options),
247 240
 		libnetwork.NetworkOptionLabels(create.Labels),
248 241
 	}
242
+
243
+	if create.IPAM != nil {
244
+		ipam := create.IPAM
245
+		v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
246
+		if err != nil {
247
+			return nil, err
248
+		}
249
+		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options))
250
+	}
251
+
249 252
 	if create.Internal {
250 253
 		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
251 254
 	}
... ...
@@ -3,23 +3,24 @@ package daemon
3 3
 import (
4 4
 	"fmt"
5 5
 
6
+	"github.com/docker/engine-api/types"
6 7
 	"github.com/docker/engine-api/types/container"
7 8
 )
8 9
 
9 10
 // ContainerUpdate updates configuration of the container
10
-func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) ([]string, error) {
11
+func (daemon *Daemon) ContainerUpdate(name string, hostConfig *container.HostConfig, validateHostname bool) (types.ContainerUpdateResponse, error) {
11 12
 	var warnings []string
12 13
 
13 14
 	warnings, err := daemon.verifyContainerSettings(hostConfig, nil, true, validateHostname)
14 15
 	if err != nil {
15
-		return warnings, err
16
+		return types.ContainerUpdateResponse{Warnings: warnings}, err
16 17
 	}
17 18
 
18 19
 	if err := daemon.update(name, hostConfig); err != nil {
19
-		return warnings, err
20
+		return types.ContainerUpdateResponse{Warnings: warnings}, err
20 21
 	}
21 22
 
22
-	return warnings, nil
23
+	return types.ContainerUpdateResponse{Warnings: warnings}, nil
23 24
 }
24 25
 
25 26
 // ContainerUpdateCmdOnBuild updates Path and Args for the container with ID cID.
... ...
@@ -66,7 +66,7 @@ clone git golang.org/x/sys eb2c74142fd19a79b3f237334c7384d5167b1b46 https://gith
66 66
 clone git github.com/docker/go-units eb879ae3e2b84e2a142af415b679ddeda47ec71c
67 67
 clone git github.com/docker/go-connections fa2850ff103453a9ad190da0df0af134f0314b3d
68 68
 
69
-clone git github.com/docker/engine-api 8d8fffdf863b12d03c76abf6ca1377e6f8f4e549
69
+clone git github.com/docker/engine-api f9cef590446e4e6073b49b652f47a337b897c1a3
70 70
 clone git github.com/RackSec/srslog 259aed10dfa74ea2961eddd1d9847619f6e98837
71 71
 clone git github.com/imdario/mergo 0.2.1
72 72
 
... ...
@@ -101,7 +101,7 @@ func (s *DockerSuite) TestApiNetworkInspect(c *check.C) {
101 101
 	c.Assert(ip.String(), checker.Equals, containerIP)
102 102
 
103 103
 	// IPAM configuration inspect
104
-	ipam := network.IPAM{
104
+	ipam := &network.IPAM{
105 105
 		Driver: "default",
106 106
 		Config: []network.IPAMConfig{{Subnet: "172.28.0.0/16", IPRange: "172.28.5.0/24", Gateway: "172.28.5.254"}},
107 107
 	}
... ...
@@ -173,7 +173,7 @@ func (s *DockerSuite) TestApiNetworkConnectDisconnect(c *check.C) {
173 173
 func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
174 174
 	testRequires(c, DaemonIsLinux)
175 175
 	// test0 bridge network
176
-	ipam0 := network.IPAM{
176
+	ipam0 := &network.IPAM{
177 177
 		Driver: "default",
178 178
 		Config: []network.IPAMConfig{{Subnet: "192.178.0.0/16", IPRange: "192.178.128.0/17", Gateway: "192.178.138.100"}},
179 179
 	}
... ...
@@ -187,7 +187,7 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
187 187
 	id0 := createNetwork(c, config0, true)
188 188
 	c.Assert(isNetworkAvailable(c, "test0"), checker.Equals, true)
189 189
 
190
-	ipam1 := network.IPAM{
190
+	ipam1 := &network.IPAM{
191 191
 		Driver: "default",
192 192
 		Config: []network.IPAMConfig{{Subnet: "192.178.128.0/17", Gateway: "192.178.128.1"}},
193 193
 	}
... ...
@@ -202,7 +202,7 @@ func (s *DockerSuite) TestApiNetworkIpamMultipleBridgeNetworks(c *check.C) {
202 202
 	createNetwork(c, config1, false)
203 203
 	c.Assert(isNetworkAvailable(c, "test1"), checker.Equals, false)
204 204
 
205
-	ipam2 := network.IPAM{
205
+	ipam2 := &network.IPAM{
206 206
 		Driver: "default",
207 207
 		Config: []network.IPAMConfig{{Subnet: "192.169.0.0/16", Gateway: "192.169.100.100"}},
208 208
 	}
... ...
@@ -25,7 +25,7 @@ func (s *DockerSwarmSuite) TestSwarmUpdate(c *check.C) {
25 25
 
26 26
 	spec := getSpec()
27 27
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
28
-	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(11*time.Second))
28
+	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 11*time.Second)
29 29
 
30 30
 	// setting anything under 30m for cert-expiry is not allowed
31 31
 	out, err = d.Cmd("swarm", "update", "--cert-expiry", "15m")
... ...
@@ -48,7 +48,7 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
48 48
 
49 49
 	spec := getSpec()
50 50
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 30*time.Hour)
51
-	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(11*time.Second))
51
+	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 11*time.Second)
52 52
 
53 53
 	c.Assert(d.Leave(true), checker.IsNil)
54 54
 	time.Sleep(500 * time.Millisecond) // https://github.com/docker/swarmkit/issues/1421
... ...
@@ -57,7 +57,7 @@ func (s *DockerSwarmSuite) TestSwarmInit(c *check.C) {
57 57
 
58 58
 	spec = getSpec()
59 59
 	c.Assert(spec.CAConfig.NodeCertExpiry, checker.Equals, 90*24*time.Hour)
60
-	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, uint64(5*time.Second))
60
+	c.Assert(spec.Dispatcher.HeartbeatPeriod, checker.Equals, 5*time.Second)
61 61
 }
62 62
 
63 63
 func (s *DockerSwarmSuite) TestSwarmInitIPv6(c *check.C) {
... ...
@@ -1,13 +1,23 @@
1 1
 package client
2 2
 
3 3
 import (
4
+	"encoding/json"
5
+
6
+	"github.com/docker/engine-api/types"
4 7
 	"github.com/docker/engine-api/types/container"
5 8
 	"golang.org/x/net/context"
6 9
 )
7 10
 
8 11
 // ContainerUpdate updates resources of a container
9
-func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) error {
10
-	resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
11
-	ensureReaderClosed(resp)
12
-	return err
12
+func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (types.ContainerUpdateResponse, error) {
13
+	var response types.ContainerUpdateResponse
14
+	serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
15
+	if err != nil {
16
+		return response, err
17
+	}
18
+
19
+	err = json.NewDecoder(serverResp.body).Decode(&response)
20
+
21
+	ensureReaderClosed(serverResp)
22
+	return response, err
13 23
 }
... ...
@@ -56,7 +56,7 @@ type ContainerAPIClient interface {
56 56
 	ContainerStop(ctx context.Context, container string, timeout *time.Duration) error
57 57
 	ContainerTop(ctx context.Context, container string, arguments []string) (types.ContainerProcessList, error)
58 58
 	ContainerUnpause(ctx context.Context, container string) error
59
-	ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) error
59
+	ContainerUpdate(ctx context.Context, container string, updateConfig container.UpdateConfig) (types.ContainerUpdateResponse, error)
60 60
 	ContainerWait(ctx context.Context, container string) (int, error)
61 61
 	CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, types.ContainerPathStat, error)
62 62
 	CopyToContainer(ctx context.Context, container, path string, content io.Reader, options types.CopyToContainerOptions) error
... ...
@@ -49,6 +49,7 @@ type ExecConfig struct {
49 49
 	AttachStdout bool     // Attach the standard output
50 50
 	Detach       bool     // Execute in detach mode
51 51
 	DetachKeys   string   // Escape keys for detach
52
+	Env          []string // Environment variables
52 53
 	Cmd          []string // Execution commands and args
53 54
 }
54 55
 
... ...
@@ -2,12 +2,22 @@ package types
2 2
 
3 3
 // Seccomp represents the config for a seccomp profile for syscall restriction.
4 4
 type Seccomp struct {
5
-	DefaultAction Action     `json:"defaultAction"`
6
-	Architectures []Arch     `json:"architectures"`
7
-	Syscalls      []*Syscall `json:"syscalls"`
5
+	DefaultAction Action `json:"defaultAction"`
6
+	// Architectures is kept to maintain backward compatibility with the old
7
+	// seccomp profile.
8
+	Architectures []Arch         `json:"architectures,omitempty"`
9
+	ArchMap       []Architecture `json:"archMap,omitempty"`
10
+	Syscalls      []*Syscall     `json:"syscalls"`
8 11
 }
9 12
 
10
-// Arch used for additional architectures
13
+// Architecture is used to represent an specific architecture
14
+// and its sub-architectures
15
+type Architecture struct {
16
+	Arch      Arch   `json:"architecture"`
17
+	SubArches []Arch `json:"subArchitectures"`
18
+}
19
+
20
+// Arch used for architectures
11 21
 type Arch string
12 22
 
13 23
 // Additional architectures permitted to be used for system calls
... ...
@@ -65,9 +75,19 @@ type Arg struct {
65 65
 	Op       Operator `json:"op"`
66 66
 }
67 67
 
68
-// Syscall is used to match a syscall in Seccomp
68
+// Filter is used to conditionally apply Seccomp rules
69
+type Filter struct {
70
+	Caps   []string `json:"caps,omitempty"`
71
+	Arches []string `json:"arches,omitempty"`
72
+}
73
+
74
+// Syscall is used to match a group of syscalls in Seccomp
69 75
 type Syscall struct {
70
-	Name   string `json:"name"`
71
-	Action Action `json:"action"`
72
-	Args   []*Arg `json:"args"`
76
+	Name     string   `json:"name,omitempty"`
77
+	Names    []string `json:"names,omitempty"`
78
+	Action   Action   `json:"action"`
79
+	Args     []*Arg   `json:"args"`
80
+	Comment  string   `json:"comment"`
81
+	Includes Filter   `json:"includes"`
82
+	Excludes Filter   `json:"excludes"`
73 83
 }
... ...
@@ -64,6 +64,7 @@ type NetworkSpec struct {
64 64
 	DriverConfiguration *Driver      `json:",omitempty"`
65 65
 	IPv6Enabled         bool         `json:",omitempty"`
66 66
 	Internal            bool         `json:",omitempty"`
67
+	Attachable          bool         `json:",omitempty"`
67 68
 	IPAMOptions         *IPAMOptions `json:",omitempty"`
68 69
 }
69 70
 
... ...
@@ -17,9 +17,13 @@ type ServiceSpec struct {
17 17
 
18 18
 	// TaskTemplate defines how the service should construct new tasks when
19 19
 	// orchestrating this service.
20
-	TaskTemplate TaskSpec                  `json:",omitempty"`
21
-	Mode         ServiceMode               `json:",omitempty"`
22
-	UpdateConfig *UpdateConfig             `json:",omitempty"`
20
+	TaskTemplate TaskSpec      `json:",omitempty"`
21
+	Mode         ServiceMode   `json:",omitempty"`
22
+	UpdateConfig *UpdateConfig `json:",omitempty"`
23
+
24
+	// Networks field in ServiceSpec is being deprecated. Users of
25
+	// engine-api should start using the same field in
26
+	// TaskSpec. This field will be removed in future releases.
23 27
 	Networks     []NetworkAttachmentConfig `json:",omitempty"`
24 28
 	EndpointSpec *EndpointSpec             `json:",omitempty"`
25 29
 }
... ...
@@ -54,13 +54,27 @@ type RaftConfig struct {
54 54
 	SnapshotInterval           uint64 `json:",omitempty"`
55 55
 	KeepOldSnapshots           uint64 `json:",omitempty"`
56 56
 	LogEntriesForSlowFollowers uint64 `json:",omitempty"`
57
-	HeartbeatTick              uint32 `json:",omitempty"`
58
-	ElectionTick               uint32 `json:",omitempty"`
57
+
58
+	// ElectionTick is the number of ticks that a follower will wait for a message
59
+	// from the leader before becoming a candidate and starting an election.
60
+	// ElectionTick must be greater than HeartbeatTick.
61
+	//
62
+	// A tick currently defaults to one second, so these translate directly to
63
+	// seconds currently, but this is NOT guaranteed.
64
+	ElectionTick int
65
+
66
+	// HeartbeatTick is the number of ticks between heartbeats. Every
67
+	// HeartbeatTick ticks, the leader will send a heartbeat to the
68
+	// followers.
69
+	//
70
+	// A tick currently defaults to one second, so these translate directly to
71
+	// seconds currently, but this is NOT guaranteed.
72
+	HeartbeatTick int
59 73
 }
60 74
 
61 75
 // DispatcherConfig represents dispatcher configuration.
62 76
 type DispatcherConfig struct {
63
-	HeartbeatPeriod uint64 `json:",omitempty"`
77
+	HeartbeatPeriod time.Duration `json:",omitempty"`
64 78
 }
65 79
 
66 80
 // CAConfig represents CA configuration.
... ...
@@ -51,10 +51,11 @@ type Task struct {
51 51
 
52 52
 // TaskSpec represents the spec of a task.
53 53
 type TaskSpec struct {
54
-	ContainerSpec ContainerSpec         `json:",omitempty"`
55
-	Resources     *ResourceRequirements `json:",omitempty"`
56
-	RestartPolicy *RestartPolicy        `json:",omitempty"`
57
-	Placement     *Placement            `json:",omitempty"`
54
+	ContainerSpec ContainerSpec             `json:",omitempty"`
55
+	Resources     *ResourceRequirements     `json:",omitempty"`
56
+	RestartPolicy *RestartPolicy            `json:",omitempty"`
57
+	Placement     *Placement                `json:",omitempty"`
58
+	Networks      []NetworkAttachmentConfig `json:",omitempty"`
58 59
 
59 60
 	// LogDriver specifies the LogDriver to use for tasks created from this
60 61
 	// spec. If not present, the one on cluster default on swarm.Spec will be
... ...
@@ -456,6 +456,7 @@ type NetworkResource struct {
456 456
 	EnableIPv6 bool                        // EnableIPv6 represents whether to enable IPv6
457 457
 	IPAM       network.IPAM                // IPAM is the network's IP Address Management
458 458
 	Internal   bool                        // Internal represents if the network is used internal only
459
+	Attachable bool                        // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode.
459 460
 	Containers map[string]EndpointResource // Containers contains endpoints belonging to the network
460 461
 	Options    map[string]string           // Options holds the network specific options to use for when creating the network
461 462
 	Labels     map[string]string           // Labels holds metadata specific to the network being created
... ...
@@ -475,8 +476,9 @@ type NetworkCreate struct {
475 475
 	CheckDuplicate bool
476 476
 	Driver         string
477 477
 	EnableIPv6     bool
478
-	IPAM           network.IPAM
478
+	IPAM           *network.IPAM
479 479
 	Internal       bool
480
+	Attachable     bool
480 481
 	Options        map[string]string
481 482
 	Labels         map[string]string
482 483
 }